/* The site's styling. One file, no framework.
 *
 * The palette, the type and the components are the organisation site's
 * (genomic-benchmarks.github.io), so that a reader who arrives from there does
 * not have to work out that this is the same project: the same teal ramp, the
 * same neutral grays, Inter over JetBrains Mono, the same uppercase eyebrow above
 * a section heading, the same bordered gap-px panel for a row of headline
 * numbers.
 *
 * Two places deliberately differ from it.
 *
 * **Link colour.** The organisation site sets body links in `brand-600`
 * (#0d9488), which reaches 3.7:1 on white. This site is mostly small text in
 * tables, so text links take `brand-700` (5.5:1) and 600 is kept for borders,
 * marks and hover, where 3:1 is the bar. Same ramp, one step down.
 *
 * **Flag colours.** The organisation site sets a flag as a coloured word. Here a
 * flag is a chip carrying the same fill the grid on the landing page draws that
 * flag in, so the key a reader learns on the grid is the key on every table
 * beside it. The word is inked in whichever of two neutrals the fill can carry
 * at 4.5:1 or better; the fills themselves were picked in `charts.py` against
 * three colour-vision-deficiency simulations, and are ordered by lightness so
 * the severity survives greyscale.
 *
 * Flags carry colour, but never colour alone -- every flag is also its own word.
 */

/* --------------------------------------------------------------- fonts --- */

/* Vendored under `docs/vendor/fonts/` rather than fetched from Google Fonts, for
 * the reason the vendored table library is vendored: an archived page should not
 * need a third party to answer in order to render. Variable, latin subset, 80 KB
 * for the pair. `swap` so the page is readable before they arrive. */

@font-face {
  font-family: Inter;
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(../vendor/fonts/inter-latin-variable.woff2) format("woff2");
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(../vendor/fonts/jetbrains-mono-latin-variable.woff2) format("woff2");
}

/* -------------------------------------------------------------- tokens --- */

:root {
  color-scheme: light;

  /* The organisation site's brand ramp, unchanged. */
  --brand-50: #f0fdfa;
  --brand-100: #ccfbf1;
  --brand-500: #14b8a6;
  --brand-600: #0d9488;
  --brand-700: #0f766e;
  --brand-900: #134e4a;

  --canvas: #f9fafb;   /* the page */
  --paper: #ffffff;    /* cards, tables, the masthead */
  --wash: #f3f4f6;     /* a quiet fill inside a card */
  --rule: #e5e7eb;
  --rule-strong: #d1d5db;

  --ink: #111827;
  --ink-soft: #4b5563;
  --ink-faint: #616a7a;   /* gray-500 taken one step darker: 4.5:1 on --wash too */

  --accent: var(--brand-700);        /* text links */
  --accent-hover: var(--brand-900);
  --accent-line: var(--brand-600);   /* borders, marks, focus */
  --accent-wash: var(--brand-50);
  --accent-wash-strong: var(--brand-100);
  --accent-on-wash: var(--brand-900);

  /* Two of these are still in use -- `--warning` rules a caution note, `--pass`
   * confirms a copy -- and the flag words they used to ink are chips now. */
  --fail: #b91c1c;
  --warning: #b45309;
  --pass: #047857;
  --unknown: #616a7a;

  /* The same four flags as an area instead of as a word.
   *
   * A fill and a text colour cannot be one hex: text on paper has to be dark to
   * be legible, a fill has to be light to be a mark rather than a blot. So what
   * the two share is mostly the hue: the amber below is the amber above at the
   * lightness an area needs, and Fail is a single hex doing both, which is what
   * makes the grid and the flag table read as one key rather than as two. Pass
   * is the one picked rather than derived -- the green above is a teal green,
   * and lightened into a fill it reads as teal rather than as green.
   *
   * Set here rather than in the theme block, because a figure keeps a light
   * canvas in both themes and so does the grid. `charts.py` carries the same
   * four values, since it writes them into SVG attributes and cannot read a
   * custom property; the two lists are changed together or not at all. */
  --flag-fill-pass: #7bc48d;
  --flag-fill-warning: #fd8c35;
  --flag-fill-fail: #b91c1c;
  --flag-fill-unknown: #616a7a;

  /* What a word set *on* one of those fills is inked in. Two values rather than
   * one, because the ramp is ordered by lightness: the two light fills take the
   * page's own ink at 8.6:1 and 7.6:1, and Fail -- the dark end -- takes white at
   * 6.5:1. Set beside the fills so a change to one is a change made next to the
   * contrast it has to keep. */
  --flag-ink-on-light: #111827;
  --flag-ink-on-dark: #ffffff;

  /* Every other row of the catalogue table. A step from --paper rather than
   * --wash, which is what a hovered row takes: a zebra the width of the hover
   * would make the pointer's row indistinguishable from the one above it. */
  --row-alt: #f7f8f9;

  /* A hovered column heading. A step further from --paper than either the zebra
   * or a hovered row, because a heading is a control and the other two are not:
   * the pointer over a row says "this row", the pointer over a heading says
   * "this sorts". Never a step *towards* the page's paper -- the vendor's own
   * value is #cdcdcd, which in the dark theme is a near-white slab under
   * --ink-faint text, and a heading that lights up is a heading you cannot
   * read. */
  --header-hover: #eaecef;

  /* A figure keeps a light canvas in both themes. The flag ramp in charts.py was
   * chosen for distinguishability under three colour-vision-deficiency
   * simulations and ordered so that severity reads by lightness as well as hue,
   * both against a light background; inverting the canvas under it would spend
   * that work. In this theme the canvas is the card, so nothing shows. */
  --figure-canvas: #ffffff;
  --figure-ink-faint: #616a7a;

  --shadow: 0 1px 2px rgb(17 24 39 / 0.05);
  --shadow-lift: 0 4px 12px rgb(17 24 39 / 0.08);
  --radius: 12px;
  --radius-sm: 6px;

  /* The masthead is sticky, so anything else that sticks to the top of the
   * viewport has to clear it. A token rather than a repeated 64, because the two
   * numbers drifting apart is a column heading that hides under the nav. */
  --masthead-height: 64px;

  /* How wide a column of text gets, in one place rather than as a `ch` count per
   * component. It was 74ch on body text and 70, 78, 80, 82 and 84 elsewhere, and
   * because `ch` resolves against each block's own font size those six counts
   * came out as six different widths: on one page a paragraph, a lede and a note
   * each stopped somewhere different, all of them well short of the 1172px the
   * figures and the grid are drawn to. One length in `rem` instead, so blocks
   * set at different sizes share an edge, and the page reads as a column rather
   * than as text pushed up against the left of the wide things.
   *
   * 60rem is about 100 characters at the body size, past the 75 a typography
   * manual would give you. That is the trade, taken deliberately: at this
   * container width the alternative is a quarter of every line left empty. Fine
   * print keeps a shorter line, because it is set smaller and would otherwise
   * run the longest of anything here. */
  --measure: 60rem;
  --measure-fine: 44rem;
}

/* The dark theme, authored once.
 *
 * `data-theme` is written onto `<html>` by the inline script in `base.html`,
 * which resolves `prefers-color-scheme` and any stored choice before the first
 * paint. There is no `@media (prefers-color-scheme: dark)` block, so a reader
 * with scripting off gets the light theme whatever their system says -- which is
 * the theme every figure on this site is drawn for. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --canvas: #0b1120;
  --paper: #0f172a;
  --wash: #1e293b;
  --rule: #1e293b;
  --rule-strong: #334155;

  --ink: #f1f5f9;
  --ink-soft: #cbd5e1;
  --ink-faint: #94a3b8;

  --accent: #2dd4bf;
  --accent-hover: #5eead4;
  --accent-line: var(--brand-500);
  --accent-wash: #10312e;
  --accent-wash-strong: #14403b;
  --accent-on-wash: #99f6e4;

  --fail: #f87171;
  --warning: #fbbf24;
  --pass: #34d399;
  --unknown: #94a3b8;

  --row-alt: #131d33;
  --header-hover: #263449;

  --shadow: 0 1px 2px rgb(0 0 0 / 0.4);
  --shadow-lift: 0 4px 14px rgb(0 0 0 / 0.5);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font: 16px/1.65 Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--ink);
  background: var(--canvas);
  font-feature-settings: "tnum" 1;   /* figures line up in a column of numbers */
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 1220px; margin: 0 auto; padding: 0 24px; }
.wrap-narrow { max-width: 800px; }

code, .mono { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; }
code {
  font-size: 0.85em; background: var(--wash); color: var(--ink);
  padding: 0.12em 0.36em; border-radius: 4px;
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-hover); }

/* One focus ring for the whole site, in the brand's own colour, on everything
 * that takes focus. The organisation site's is a 2px offset ring; this is that. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent-line);
  outline-offset: 2px;
  border-radius: 3px;
}

hr { border: none; border-top: 1px solid var(--rule); margin: 32px 0; }

/* -------------------------------------------------------------- masthead --- */

.masthead {
  border-bottom: 1px solid var(--rule);
  /* Opaque first, then the translucent version for a browser that has
   * `color-mix`. A masthead that fell back to no background at all would put the
   * page's own text through it as it scrolled. */
  background: var(--paper);
  background: color-mix(in srgb, var(--paper) 85%, transparent);
  backdrop-filter: blur(12px);
  position: sticky; top: 0; z-index: 20;
}
.masthead .wrap {
  display: flex; align-items: center; justify-content: space-between;
  height: var(--masthead-height); gap: 20px;
}
.wordmark {
  font-size: 16px; font-weight: 700; letter-spacing: -0.02em;
  color: var(--ink); text-decoration: none; white-space: nowrap;
}
.wordmark strong { color: var(--accent); font-weight: 700; }
.wordmark:hover { color: var(--accent); }

.masthead nav { display: flex; gap: 2px; font-size: 14px; overflow-x: auto; }
.masthead nav a {
  padding: 7px 11px; border-radius: var(--radius-sm);
  color: var(--ink-soft); text-decoration: none; font-weight: 500; white-space: nowrap;
}
.masthead nav a:hover { color: var(--accent); background: var(--wash); }
/* Where you are, marked twice: `aria-current` for a screen reader, and colour
 * plus a rule for everyone else. Colour alone would be one signal. */
.masthead nav a[aria-current="page"] {
  color: var(--accent); background: var(--accent-wash);
  box-shadow: inset 0 -2px 0 var(--accent-line);
}

.masthead-right { display: flex; align-items: center; gap: 8px; }

.icon-button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: none; color: var(--ink-soft); cursor: pointer;
}
.icon-button:hover { background: var(--wash); color: var(--accent); }
.icon-button svg { width: 18px; height: 18px; fill: currentColor; }
/* One button, two icons: the script shows the one for the theme a click would
 * move to, so the button is a statement about what it does. */
:root[data-theme="dark"] .icon-sun { display: none; }
:root:not([data-theme="dark"]) .icon-moon { display: none; }

.gh-pill {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: var(--radius-sm);
  background: var(--ink); color: var(--canvas);
  font-size: 14px; font-weight: 500; text-decoration: none; white-space: nowrap;
}
.gh-pill:hover { background: var(--ink-soft); color: var(--canvas); }
.gh-pill svg { width: 16px; height: 16px; fill: currentColor; }

/* ----------------------------------------------------------------- copy --- */

main { padding: 40px 0 72px; }

h1 { font-size: 32px; line-height: 1.15; letter-spacing: -0.025em; font-weight: 700; margin: 0 0 16px; }
h2 {
  font-size: 24px; line-height: 1.25; letter-spacing: -0.02em; font-weight: 700;
  margin: 52px 0 12px;
}
h3 { font-size: 17px; letter-spacing: -0.01em; font-weight: 600; margin: 28px 0 8px; }

/* The organisation site's section label: small, uppercase, wide-tracked, teal,
 * above the heading it belongs to. */
.eyebrow {
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--accent); margin: 0 0 10px;
}
/* The label belongs to the heading under it, so it sits 10px above it and not
 * the 52 an `h2` opens with -- which put the label nearer the section it had
 * just left than the one it was announcing. `h1` already opens at 0. */
.eyebrow + h2 { margin-top: 0; }

main p { max-width: var(--measure); color: var(--ink-soft); }
main p b, main p strong { color: var(--ink); font-weight: 600; }

.lede { font-size: 18px; line-height: 1.6; color: var(--ink-soft); max-width: var(--measure); }

.pending {
  border-left: 3px solid var(--rule);
  padding: 2px 0 2px 16px;
  font-size: 15px;
}

.fine { font-size: 13.5px; color: var(--ink-faint); }

/* -------------------------------------------------------------- summary --- */

.summary { margin: 28px 0 8px; }
.summary ul {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  background: var(--rule); border: 1px solid var(--rule);
  border-radius: var(--radius); overflow: hidden;
}
.summary li { background: var(--paper); padding: 14px 16px; font-size: 14px; color: var(--ink-soft); }
.summary li b { display: block; font-size: 26px; line-height: 1.1; color: var(--accent); margin-bottom: 4px; }

/* ------------------------------------------------------------- controls --- */

/* The table ships its controls hidden and `assets/catalogue.js` unhides them, so
 * the attribute has to beat the display below rather than lose to it. */
.controls[hidden] { display: none; }
.controls {
  display: flex; flex-direction: column; gap: 14px; margin: 22px 0 14px;
  align-items: stretch;
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 16px 18px;
}
.search-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.search-row label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em; color: var(--ink-faint);
  font-weight: 600;
}
/* The drawer these open into.
 *
 * The six groups of checkboxes are the tallest thing in this panel and the
 * least often reached for -- most readers sort a column, type into the search,
 * or take a quick view -- and at full height they pushed the table itself below
 * the fold. So they ship closed. What stays on show is the state: the quick
 * views, a chip per condition, and the count of rows.
 *
 * The button says how many boxes are ticked, because a closed drawer can be
 * narrowing the table and the reader is owed that from outside it. The caret
 * turns rather than swapping glyph, so nothing beside it shifts. */
.drawer-toggle .drawer-caret {
  width: 0; height: 0;
  border-left: 4.5px solid transparent; border-right: 4.5px solid transparent;
  border-top: 5.5px solid currentColor;
  transition: transform 0.15s ease;
}
.drawer-toggle[aria-expanded="true"] .drawer-caret { transform: rotate(180deg); }
.drawer-toggle[aria-expanded="true"] {
  border-color: var(--accent-line); color: var(--accent);
}
.drawer-toggle[hidden] { display: none; }
.drawer-count {
  font-size: 11px; font-weight: 700; line-height: 1.65; padding: 0 7px;
  border-radius: 999px; font-variant-numeric: tabular-nums;
  background: var(--accent-wash-strong); color: var(--accent-on-wash);
}
/* `#facets` is a grid, and a grid beats the `display: none` that `hidden` is. */
#facets[hidden] { display: none; }

/* The facets: one group of checkboxes per column the table can be narrowed by,
 * six of them.
 *
 * They were bordered `fieldset`s in a flex row, which is the browser's own look
 * and the reason they read as awkward: sunken boxes of six different heights,
 * ragged along the bottom, each one a box drawn inside a card that is already a
 * box and filled a step darker than it, so a group read as a hole in the panel
 * rather than as a heading over a list. What is wanted is a rail -- a small
 * heading, a rule, a column of options -- laid on a grid, so the six headings
 * line up and the options under them share a left edge. The border around a
 * group was doing a job the heading and the space between groups already do.
 *
 * The `fieldset` and the `legend` stay. A set of related checkboxes is what they
 * are for, and they are why a screen reader says "Species, group" before reading
 * the first option. What changes is only that they stop looking like a form. */
#facets {
  display: grid; gap: 18px 22px; align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(238px, 1fr));
}

/* The tick, as an image rather than as generated content: Firefox draws no
 * `::before` or `::after` on an `<input>`, and a checkbox whose mark is missing
 * in one browser is a checkbox that browser cannot state its own condition in.
 * Two of them rather than one, because a mark on a fill has to clear 3:1 to be a
 * mark, and no single lightness does that on both the accent and the Fail red.
 *
 * On both boxes that use them: the facets, which choose rows, and the column
 * picker, which chooses columns. */
#facets, .picker-list {
  --tick-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23111827' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round' d='M3.6 8.4l2.9 2.9 5.9-6'/%3E%3C/svg%3E");
  --tick-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23ffffff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round' d='M3.6 8.4l2.9 2.9 5.9-6'/%3E%3C/svg%3E");
}
.controls fieldset.facet {
  border: none; margin: 0; padding: 0; background: none; min-width: 0;
}
.controls .facet legend {
  padding: 0 9px; margin: 0;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em;
  font-weight: 600; color: var(--ink-faint);
}
/* Species has seventeen values, and a group that grows to fit them pushes the
 * table off the screen, so the long ones scroll. The cap is eight options, which
 * is one more than the longest facet that is not species: a list that scrolls by
 * half a row is worse than one that does not scroll at all, so the number is set
 * where it clears the six groups that fit and stops only the one that does not.
 *
 * The cap is on this box rather than on the fieldset so that the heading sits
 * outside what moves. A scrolled list whose own heading has scrolled away is a
 * column of species names with nothing left on screen saying they are species. */
.controls .facet-list {
  max-height: 224px; overflow-y: auto;
  margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--rule);
  scrollbar-width: thin; scrollbar-color: var(--rule-strong) transparent;
}

.controls .facet-list label {
  display: flex; align-items: center; gap: 9px;
  padding: 4px 9px; margin-bottom: 1px; border-radius: var(--radius-sm);
  font-size: 13.5px; line-height: 1.35; color: var(--ink-soft); cursor: pointer;
}
/* The whole row answers the pointer, not just the fifteen pixels of the box. */
.controls .facet-list label:hover { background: var(--wash); color: var(--ink); }
/* A ticked option also takes the page's full ink, so which filters are on reads
 * down the column rather than box by box. `:has()` because the value has no
 * element of its own to hang it on; where it is unsupported the tick still says
 * so, and no weight changes, so nothing reflows either way. */
.controls .facet-list label:has(input:checked) { color: var(--ink); }

/* The box itself, drawn rather than the platform's. Its border is --ink-faint
 * and not --rule-strong: a rule divides two things that are both still there,
 * but this outline *is* the control when the control is empty, and an empty
 * checkbox at 1.5:1 is one a reader has to hunt for. */
.controls .facet-list input[type="checkbox"],
.picker-list input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  flex: none; width: 15px; height: 15px; margin: 0;
  border: 1.5px solid var(--ink-faint); border-radius: 4px;
  background: var(--paper) no-repeat center / 100% 100%;
  cursor: pointer;
}
.controls .facet-list input[type="checkbox"]:checked,
.picker-list input[type="checkbox"]:checked {
  background-color: var(--accent-line); border-color: var(--accent-line);
  background-image: var(--tick-dark);
}
.controls .facet-list input[type="checkbox"]:focus-visible,
.picker-list input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent-line); outline-offset: 2px;
}

/* The rollup flag filters take the ramp the rest of the site draws that flag in,
 * so the control and the column it narrows read as one key rather than as two.
 * Fail is the dark end of the ramp and takes the light tick, the other two are
 * light fills and take the dark one -- the pairing `--flag-ink-on-light` and
 * `--flag-ink-on-dark` already name for the chips. */
#facets input[data-field="overall_verdict"][value="Pass"]:checked {
  background-color: var(--flag-fill-pass); border-color: var(--flag-fill-pass);
}
#facets input[data-field="overall_verdict"][value="Warning"]:checked {
  background-color: var(--flag-fill-warning); border-color: var(--flag-fill-warning);
}
#facets input[data-field="overall_verdict"][value="Fail"]:checked {
  background-color: var(--flag-fill-fail); border-color: var(--flag-fill-fail);
  background-image: var(--tick-light);
}
#search {
  font: inherit; font-size: 14px; padding: 7px 11px; width: 260px;
  border: 1px solid var(--rule-strong); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink);
}
#search::placeholder { color: var(--ink-faint); }
#search:focus { outline: 2px solid var(--accent-line); outline-offset: 0; border-color: var(--accent-line); }
.count { margin: 0; font-size: 13px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }

/* A saved view, as a button. Four of them, because four questions account for
 * most of why anyone opens this table. */
.presets { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.presets .presets-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em; font-weight: 600;
  color: var(--ink-faint);
}
.preset {
  font: inherit; font-size: 13px; padding: 5px 11px;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  background: var(--paper); color: var(--ink-soft); cursor: pointer;
}
.preset:hover { border-color: var(--accent-line); color: var(--accent); }
.preset[aria-pressed="true"] {
  background: var(--accent-wash); border-color: var(--accent-line); color: var(--accent-on-wash);
  font-weight: 600;
}

/* What is currently filtering the table, one chip per condition, each removable.
 * A filter a reader cannot see is a row count they cannot explain. */
.chips { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.chips:empty { display: none; }
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; padding: 4px 5px 4px 11px; border-radius: 999px;
  background: var(--accent-wash); color: var(--accent-on-wash);
  border: 1px solid var(--accent-wash-strong);
}
.chip .chip-field { color: var(--ink-faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; }
.chip button {
  font: inherit; line-height: 1; font-size: 15px; width: 20px; height: 20px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 999px; cursor: pointer;
  background: transparent; color: var(--accent-on-wash);
}
.chip button:hover { background: var(--accent-wash-strong); }

/* ----------------------------------------------------------- table tools --- */

/* Above the table and outside `.controls`, because neither of these narrows it.
 * The picker chooses what is on screen and the arrows move along it, and a
 * reader looking for why a row went missing should not find them among the
 * things that could have removed it. */
.table-tools {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 10px 24px; margin: 0 0 10px;
}
.picker[hidden], .scroller[hidden] { display: none; }

.picker { border: none; margin: 0; padding: 0; min-width: 0; }
.picker legend {
  padding: 0; margin: 0 0 4px;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em;
  font-weight: 600; color: var(--ink-faint);
}
.picker-body { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 4px; }
/* The list is not a box of its own. Its labels are flex items of the row above,
 * so they and the reset button wrap as one line of controls rather than as a
 * block with a button set beside it. */
.picker-list { display: contents; }
.picker-list label {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  padding: 4px 9px; border-radius: var(--radius-sm);
  font-size: 13px; line-height: 1.35; color: var(--ink-soft); cursor: pointer;
}
.picker-list label:hover { background: var(--wash); color: var(--ink); }
/* A column that is on takes the page's full ink, so which of the thirteen are
 * on the table reads across the row rather than box by box. */
.picker-list label:has(input:checked) { color: var(--ink); }
#picker-reset { font-size: 12.5px; padding: 4px 10px; margin-left: 6px; }
#picker-reset[hidden] { display: none; }

/* The way sideways. Held to the right-hand end of the tools row, which is the
 * end of the table it is pointing at. */
.scroller { display: flex; align-items: center; gap: 2px; }
.scroller-label { font-size: 13px; color: var(--ink-soft); margin-right: 8px; }
.scroller button {
  font: inherit; width: 30px; height: 30px; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: none; color: var(--ink-soft);
}
.scroller button:hover:not(:disabled) { background: var(--accent-wash); color: var(--accent); }
.scroller button:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 1px; }
/* At either end the button stays where it is and stops answering, rather than
 * leaving: a control that disappears at the moment it is being aimed at moves
 * the one next to it under the pointer. */
.scroller button:disabled { color: var(--rule); cursor: default; }
.scroller button svg {
  width: 18px; height: 18px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* ---------------------------------------------------------------- table --- */

.catalogue-table {
  border: 1px solid var(--rule); border-radius: var(--radius); overflow: hidden;
  background: var(--paper); box-shadow: var(--shadow);
}

.tabulator { background: var(--paper); font-size: 14px; border: none; color: var(--ink); }
.tabulator .tabulator-header { border-bottom: 1px solid var(--rule); background: var(--paper); color: var(--ink); }
.tabulator .tabulator-header .tabulator-col {
  background: var(--paper); border-right: none;
  font-weight: 600; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-faint);
}
/* Headers and the wide text columns wrap rather than truncating. The selector is
 * this long because Tabulator's own rule for the title is, and a shorter one
 * loses to it. */
.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title {
  white-space: normal; text-overflow: clip; line-height: 1.25;
}
.tabulator-row .tabulator-cell.wrap {
  white-space: normal; text-overflow: clip; line-height: 1.35;
  /* `overflow-wrap` as well, because a dataset name is one unbroken token:
   * `genomic-benchmarks:demo_coding_vs_intergenomic_seqs` offers no space to
   * wrap at, so permission to wrap alone leaves it overflowing. */
  overflow-wrap: anywhere;
}
/* Every surface the vendored stylesheet paints, repainted.
 *
 * Tabulator ships a light theme in hard-coded hexes -- `#fff` on the row and on
 * the table holder, `#333` on its text -- and this file used to re-colour only
 * the *even* rows. In the light theme that reads as intended, because white on
 * white is white. In the dark theme it was half a table: the even rows took
 * `--paper`, the odd rows kept the vendor's white, and `--ink` on white is
 * unreadable. So each of these surfaces is claimed explicitly, and none of them
 * is left to whichever rule the vendor happens to have written for it. */
.tabulator .tabulator-tableholder { background: var(--paper); }
.tabulator .tabulator-tableholder .tabulator-table { background: var(--paper); color: var(--ink); }
.tabulator-row { background: var(--paper); border-bottom: 1px solid var(--rule); color: var(--ink); }
/* The zebra is a step from the row's own colour, not from the hover colour, so
 * the three states stay ordered: row, alternate row, hovered row. */
.tabulator-row.tabulator-row-even { background: var(--row-alt); }
.tabulator-row:hover { background: var(--wash) !important; }
.tabulator-row .tabulator-cell { border-right: none; padding: 8px 10px; }
.tabulator .tabulator-row.tabulator-selectable:hover { cursor: pointer; }
.tabulator .tabulator-placeholder { background: var(--paper); }
.tabulator .tabulator-placeholder .tabulator-placeholder-contents { color: var(--ink-faint); }

/* The header's own hover and its sort arrows, for the same reason: `#cdcdcd`
 * behind a column title and `#666` on an arrow are a light theme's values, and
 * in the dark theme they were a grey slab and an invisible arrow. */
.tabulator .tabulator-header .tabulator-col.tabulator-sortable:hover {
  background: var(--header-hover);
}
/* And the title sharpens rather than washing out. A heading sits at --ink-faint
 * so the values below it read first; under the pointer it is the thing being
 * pointed at, so it takes the page's full ink. */
.tabulator .tabulator-header .tabulator-col.tabulator-sortable:hover
  .tabulator-col-content .tabulator-col-title {
  color: var(--ink);
}
.tabulator .tabulator-header .tabulator-col .tabulator-col-sorter .tabulator-arrow {
  border-bottom-color: var(--rule-strong); border-top-color: var(--rule-strong);
}
.tabulator .tabulator-header .tabulator-col[aria-sort="ascending"] .tabulator-arrow,
.tabulator .tabulator-header .tabulator-col[aria-sort="descending"] .tabulator-arrow {
  border-bottom-color: var(--accent); border-top-color: var(--accent);
}
/* The arrow under the pointer. Tabulator writes this one at #555 behind seven
 * class selectors, so it needs eight to answer: in the dark theme a #555 arrow
 * on a hovered heading is an arrow that disappears at the moment it is being
 * aimed at. */
.tabulator .tabulator-header .tabulator-col.tabulator-sortable
  .tabulator-col-content .tabulator-col-sorter .tabulator-arrow:hover {
  border-bottom-color: var(--accent); border-top-color: var(--accent);
}

/* The column help. Every heading on this table carries a `headerTooltip` and the
 * two wide text columns carry a cell tooltip, and Tabulator draws all of them in
 * one popup it paints `#fff` and does not set a text colour on -- so in the dark
 * theme the help text was `--ink` on white. */
.tabulator-popup-container {
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule-strong); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lift);
}
.tabulator-tooltip { max-width: 42ch; padding: 7px 10px; line-height: 1.45; }

/* ------------------------------------------------------- the check grid --- */

/* One column per check, drawn as `gb_audit/matrix.py` draws the same grid on the
 * overview: a fill, not a word. Ten words of Pass and Fail across a row are ten
 * things to read; ten fills are one shape. The flag is still carried in the
 * tooltip and to a screen reader, and the fills are `--flag-fill-*`, whose
 * lightness orders the severity -- so the ordering survives colour vision
 * deficiency and colour is never the only signal. */
.tabulator-row .tabulator-cell.check-cell { padding: 6px 4px; }
.cflag { display: block; height: 18px; border-radius: 2px; }
.cflag-Pass { background: var(--flag-fill-pass); }
.cflag-Warning { background: var(--flag-fill-warning); }
.cflag-Fail { background: var(--flag-fill-fail); }
/* Unknown is not a fourth degree of severity, so it is not a fourth fill on the
 * ramp: it is the outline of a cell that was scored and could not be. */
.cflag-Unknown {
  height: 16px; border: 1px solid var(--flag-fill-unknown); background: none;
}
/* And a check that had nothing to run on is neither. The grid on the overview
 * leaves this one blank, because its cells sit in a lattice of rules and an
 * empty box there is visibly a box. These do not, so the box is drawn -- an
 * absence with no outline at all is indistinguishable from a column that failed
 * to render, which is a different statement. */
.cflag-blank {
  height: 16px; border: 1px dashed var(--rule-strong); background: none;
}

/* The heading, two short lines of it. Not the uppercase the other columns take:
 * these are the manuscript's own abbreviations, and `Per position / from 3'`
 * shouted is a heading that reads as an acronym. */
.ch-line {
  display: block; font-size: 9px; line-height: 1.3;
  text-transform: none; letter-spacing: 0;
}
/* The band over each family. The check columns are the only groups this site
 * has, which is why these rules can be written on the group rather than on a
 * class of their own -- and why they can reach the ten headings under it, which
 * `cssClass` does not. */
.tabulator .tabulator-header .tabulator-col.tabulator-col-group
  > .tabulator-col-content .tabulator-col-title {
  font-size: 9px; font-weight: 500; letter-spacing: 0.05em; text-align: center;
}
/* A band is as wide as the columns under it, and no wider.
 *
 * Tabulator does not give a group a width: the element is `inline-flex`, so it
 * takes its widest content, and one of its two children is the band's own title.
 * `leakage scan` over the one column in that family is 73 pixels of title over a
 * 66-pixel column, so the group came out 81 wide -- the band's rule ran fifteen
 * pixels past the column it was drawn for, and the title sat off-centre over it
 * by half of that. Taking the title out of flow takes it out of that
 * measurement, and the group is left measuring the only thing it should.
 *
 * Out of flow it can no longer set the row's height either, so the row is given
 * one: two lines, which is what the longest of the three band names needs at the
 * width of one column. The title sits at the foot of it, so a name on one line
 * and a name on two both end on the rule under the band. */
.tabulator .tabulator-header .tabulator-col.tabulator-col-group
  > .tabulator-col-content {
  position: relative; height: 31px; padding: 0;
}
.tabulator .tabulator-header .tabulator-col.tabulator-col-group
  > .tabulator-col-content .tabulator-col-title-holder {
  position: absolute; left: 2px; right: 2px; bottom: 4px;
}
/* The rule under a band is the vendor's `#aaa`, which is a light theme's value
 * and twice the weight of every other rule on this page. */
.tabulator .tabulator-header .tabulator-col-group .tabulator-col-group-cols {
  border-top: 1px solid var(--rule);
}
/* Tabulator keeps 25 pixels at the right of a sortable heading for its sort
 * arrow. On a column 66 pixels wide that is a third of the heading spent holding
 * a mark 12 pixels across, and `Dinucleotide` came apart into three lines to pay
 * for it. The arrow goes under the two lines instead, where the width it wants
 * is width the heading was not using: eleven pixels of the column's own padding,
 * under the last line of every heading.
 *
 * The arrow is placed against the title rather than against the column, because
 * that is what it is positioned in -- Tabulator puts the sorter inside
 * `.tabulator-col-title-holder`, and the vendor's `top: 0; bottom: 0` on it is
 * written with five classes, so it reached this file's `bottom: 2px` and won.
 * What that produced was an arrow centred on the heading: a grey triangle drawn
 * through the middle of `Per position nucleotide`, on all ten at once. */
.tabulator .tabulator-header .tabulator-col-group-cols .tabulator-col-content {
  padding: 4px 2px 11px;
}
.tabulator .tabulator-header .tabulator-col-group-cols
  .tabulator-col.tabulator-sortable .tabulator-col-title { padding-right: 0; }
.tabulator .tabulator-header .tabulator-col-group-cols .tabulator-col
  .tabulator-col-content .tabulator-col-sorter {
  top: calc(100% + 3px); bottom: auto; left: 0; right: 0; justify-content: center;
}
/* And the columns with no band over them sit on the same line as the ten that
 * have. `columnHeaderVertAlign: "bottom"` in `assets/catalogue.js` drops every
 * heading to the foot of a header three rows deep -- without it `Dataset` floats
 * at the top, level with the band titles and reading as though it were one. That
 * leaves one difference: a check keeps eleven pixels under its last line for the
 * sort arrow that goes there, and a column with its arrow at the right does not,
 * so it would sit those eleven pixels lower. It takes the same space. */
.tabulator .tabulator-header .tabulator-headers
  > .tabulator-col:not(.tabulator-col-group) > .tabulator-col-content {
  padding-bottom: 11px;
}

/* The disclosure and the name stay while the checks scroll past them. Tabulator
 * pins them with `position: sticky` and paints them `background-color: inherit`,
 * which is what keeps the zebra and the hover running under a frozen cell; what
 * it also ships is a 2px `#aaa` rule at the seam, which is a light theme's value
 * and twice this site's weight. */
.tabulator .tabulator-header .tabulator-frozen { background: var(--paper); }
.tabulator .tabulator-frozen-left { border-right: 1px solid var(--rule); }

.tabulator .tabulator-row.tabulator-group {
  background: var(--accent-wash); border-bottom: 1px solid var(--rule);
  font-weight: 600; color: var(--accent-on-wash); padding: 7px 10px;
}
.tabulator .tabulator-row.tabulator-group span { color: var(--ink-faint); font-weight: 400; }

.dataset { color: var(--ink); }
/* Not scoped to `.dataset`: the collection prefix is also the quiet half of the
 * landing page's links and of a benchmark page's heading, and it was rendering at
 * full strength in both. */
.collection-part { color: var(--ink-faint); }

/* The disclosure that opens a row's panel. A real button rather than a click
 * handler on the row alone: the panel was reachable with a mouse and by nothing
 * else, and a table of 93 rows whose detail is keyboard-unreachable is a table
 * with a third of its content behind a pointer. */
.row-toggle {
  font: inherit; width: 24px; height: 24px; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: none; color: var(--ink-faint);
}
.row-toggle:hover { background: var(--accent-wash); color: var(--accent); }
.row-toggle svg { width: 13px; height: 13px; fill: currentColor; transition: transform 0.15s ease; }
.row-toggle[aria-expanded="true"] svg { transform: rotate(90deg); }
.row-toggle[aria-expanded="true"] { color: var(--accent); }

.tag {
  display: inline-block; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase;
  font-weight: 600;
  padding: 2px 8px; border-radius: 999px;
  background: var(--accent-wash-strong); color: var(--accent-on-wash);
  white-space: nowrap;
}

/* A flag, wherever it is written as a value rather than as a sentence.
 *
 * The same fill the grid on the landing page uses, with the word still on it.
 * It used to be a coloured word in `--pass`, `--warning` and `--fail` -- the
 * inks -- which meant the two halves of one key were two palettes: the grid
 * called Pass a leaf green and the table beside it called Pass a teal. Reading
 * the ink was never the problem; reading it as *the same statement* as the cell
 * above it was. So the chip takes the fill, and the ink becomes whichever of the
 * two the fill can carry -- 8.6:1 on Pass, 7.6:1 on Warning, 6.5:1 on Fail.
 *
 * Both of those hold in either theme, which is why nothing here is restated in
 * the dark block: a flag fill is a figure's colour, and figures on this site
 * keep their palette when the page inverts.
 *
 * Unknown stays outside the ramp, as it is in every figure. A fourth fill on the
 * same three-step lightness order would read as a mild Pass, so Unknown is an
 * outline and a blank is still only a dash. */
.flag {
  display: inline-block; font-weight: 600; font-size: 12px; line-height: 1.5;
  padding: 1px 9px; border-radius: 999px; border: 1px solid transparent;
  white-space: nowrap; vertical-align: baseline;
}
.flag-Pass { background: var(--flag-fill-pass); color: var(--flag-ink-on-light); }
.flag-Warning { background: var(--flag-fill-warning); color: var(--flag-ink-on-light); }
.flag-Fail { background: var(--flag-fill-fail); color: var(--flag-ink-on-dark); }
.flag-Unknown {
  border-color: var(--flag-fill-unknown); color: var(--unknown);
  font-weight: 500; font-style: italic;
}
.flag-blank { padding: 1px 0; color: var(--unknown); font-weight: 400; }

.num { font-variant-numeric: tabular-nums; }
.absent { color: var(--unknown); font-style: italic; }

/* ---------------------------------------------------------------- panel --- */

.panel {
  display: none;
  /* Reset explicitly: Tabulator sets `white-space: nowrap` on the row, and the
   * panel is a child of the row, so every sentence in it inherits nowrap and
   * runs off the right edge instead of wrapping. */
  white-space: normal;
  padding: 16px 18px 18px;
  background: var(--canvas);
  border-top: 1px solid var(--rule);
  font-size: 14px;
  color: var(--ink-soft);
  cursor: default;
}
/* The panel is a child of its row, so it is as wide as every column put
 * together -- and at any scroll position but the first it opens off the left of
 * the screen. Pinned to the left edge instead, at the width of what the reader
 * can see: `--table-view` is what `assets/catalogue.js` measures the scrolling
 * box at, and 100% is what it is before that measurement or without scripting to
 * take it. */
.tabulator-row.panel-open .panel {
  display: block; position: sticky; left: 0;
  width: var(--table-view, 100%); box-sizing: border-box;
}

/* On a benchmark page the panel is the page's own content rather than a row's
 * expanded body, so it is always open and needs a frame of its own -- inside a
 * table row the row's borders were the frame. */
.panel.standing {
  display: block; border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 18px 20px 20px; margin: 18px 0 8px; background: var(--paper);
}

.panel .headline { font-size: 15px; color: var(--ink); margin: 0 0 4px; }
.panel .headline b { color: var(--ink); }
.panel .caveat { margin: 0 0 14px; font-size: 13px; color: var(--ink-faint); max-width: 78ch; }

/* Two columns, because the ten checks ask two questions: nine of them about the
 * classes inside one split, the tenth about what two splits have in common.
 *
 * Not two equal ones. The left column's longest row is "Per position reversed
 * nucleotide content" and carries an AUROC and a flag after it; the right
 * column's longest is a pair of split names. Equal tracks wrapped every check
 * name onto two lines while the column beside it ran out of things to hold.
 *
 * `minmax(0, …)` rather than `minmax(260px, …)`: a grid item's default minimum
 * is its content's width, so the checks table would refuse to shrink and paint
 * over the column beside it instead. */
.panel-grid {
  display: grid; gap: 26px;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  align-items: start;
}
.panel-grid > div { min-width: 0; }
.panel .shares li { overflow-wrap: anywhere; }
.panel h3, .panel h4 {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--ink-faint); margin: 0 0 6px; font-weight: 600;
}
.panel h4 { margin-top: 16px; }
.panel table { border-collapse: collapse; width: 100%; }
.panel td { padding: 3px 12px 3px 0; vertical-align: baseline; }
.panel td.right { text-align: right; }

/* The kind of check is a section heading rather than a cell on every row. Said
 * once over six probes it is a heading; said six times beside six names that
 * already are the probes, it was six repetitions charged to the width of the
 * column holding the names.
 *
 * The heading row is also the header row, which is why it is a `th`: the AUROC
 * column is the only one here that cannot name itself, and this puts its label
 * where it belongs without a band of headers over a column of check names and a
 * column of chips that each already say what they are. */
.panel .checks .group-head th {
  text-align: left; font-weight: 600; font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.09em; color: var(--ink-faint);
  padding: 0 12px 4px 0; border-bottom: 1px solid var(--rule);
}
.panel .checks .group-head th.right { text-align: right; }
.panel .checks tbody + tbody .group-head th { padding-top: 16px; }
.panel .checks .group-head + tr td { padding-top: 6px; }
/* The flag column is the last thing before the gap between the two columns, and
 * a gap of 26px does not need 12 more added to it. */
.panel .checks td:last-child, .panel .checks th:last-child { padding-right: 0; }

.panel .shares { list-style: none; margin: 0; padding: 0; }
.panel .shares li { margin-bottom: 2px; }

/* One comparison, then its two figures. Both ways round, because the share of
 * the held-out split found in train and the share of train found in the held-out
 * split are two facts and a small split inside a large one makes them differ by
 * an order of magnitude. */
.panel .pairs { list-style: none; margin: 0; padding: 0; }
.panel .pairs > li { margin-bottom: 12px; }
.panel .pairs > li:last-child { margin-bottom: 0; }
.panel .pair-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px;
  margin-bottom: 3px;
}
.panel .pair-nums { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.panel .pair-nums li { margin-bottom: 1px; color: var(--ink-faint); }
.panel .pair-nums b { color: var(--ink); font-variant-numeric: tabular-nums; }
/* Quiet mono here rather than the washed pill a `code` span gets everywhere
 * else. Two splits named twice a comparison and twice a direction is six pills
 * on four lines, which turned two plain sentences into a row of buttons. The
 * line above is where these two are named as identifiers; down here they are
 * being talked about. */
.panel .pair-nums code {
  background: none; padding: 0; color: var(--ink-soft);
}

/* The way out of the panel, under both columns rather than at the foot of
 * whichever one happened to be third. */
.panel-more { margin: 16px 0 0; font-size: 14px; }
.panel .note { font-size: 13px; color: var(--ink-faint); max-width: 70ch; }

/* -------------------------------------------------- static data tables --- */

/* The landing page's Core Set list and the ranking tables. Not Tabulator: ten
 * rows a reader can see all of at once need no virtual DOM, and a landing page
 * that renders with scripting off is worth more than sorting one. The header
 * styling deliberately matches the catalogue's so that the two pages read as one
 * site rather than as two tables that happen to be next to each other. */

.table-card {
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow); margin: 18px 0 8px;
}
.table-card .listing { margin: 0; }
.table-card > .listing tbody tr:last-child th,
.table-card > .listing tbody tr:last-child td { border-bottom: none; }

.listing { width: 100%; border-collapse: collapse; font-size: 14px; margin: 18px 0 8px; }
.listing caption {
  text-align: left; font-size: 13px; color: var(--ink-faint);
  padding: 12px 14px; border-bottom: 1px solid var(--rule);
}
.listing thead th {
  text-align: left; vertical-align: bottom;
  font-weight: 600; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-faint);
  padding: 10px 14px 8px; border-bottom: 1px solid var(--rule);
}
/* A row header is a name, not a column label. Scoped to `thead` above because
 * the unscoped rule was setting every `<th scope="row">` in upper case, which
 * turned `GUE_v2:transcription_factor_prediction_mouse_2` into a different
 * string from the one the catalogue and the URL use. An identifier a reader
 * cannot copy off the page is an identifier the page has not given them. */
.listing tbody th {
  text-align: left; vertical-align: baseline; font-weight: 500;
  color: var(--ink); padding: 10px 14px; border-bottom: 1px solid var(--rule);
}
.listing tbody th.wrap { overflow-wrap: anywhere; }
.listing td { padding: 10px 14px; border-bottom: 1px solid var(--rule); vertical-align: baseline; color: var(--ink-soft); }
.listing tbody tr:hover { background: var(--wash); }
/* A dataset name is one unbroken token, so permission to wrap is not enough. */
.listing td.wrap { overflow-wrap: anywhere; }
.listing th.right, .listing td.right { text-align: right; }
.listing a { color: var(--ink); text-decoration-color: var(--rule-strong); }
.listing a:hover { color: var(--accent); text-decoration-color: currentColor; }
.listing .fine { font-size: 12px; }

/* A count that is also a link into the catalogue, filtered to the rows it
 * counts. Underlined only on hover, so a column of them still reads as numbers. */
.listing a.count-link {
  color: var(--ink); text-decoration: none; font-variant-numeric: tabular-nums;
  border-bottom: 1px dotted var(--rule-strong);
}
.listing a.count-link:hover { color: var(--accent); border-bottom-color: currentColor; }
.listing .zero { color: var(--ink-faint); }

.crumb {
  font-size: 13px; color: var(--ink-faint); margin: 0 0 14px;
  display: flex; flex-wrap: wrap; gap: 7px; align-items: baseline;
}
.crumb a { color: var(--ink-faint); }
.crumb a:hover { color: var(--accent); }
.crumb .here { color: var(--ink-soft); overflow-wrap: anywhere; }

a.tag { text-decoration: none; }
a.tag:hover { background: var(--accent-line); color: var(--paper); }

/* ------------------------------------------------------------- colophon --- */

.colophon {
  border-top: 1px solid var(--rule); background: var(--paper);
  padding: 40px 0 48px; margin-top: 40px;
}

/* Where else to go, from the bottom of any page. The site had no link out to the
 * project it is part of, to the tool that produced every number on it, or to its
 * own source -- three links a reader of an archived measurement wants and had to
 * guess at. */
.site-links {
  display: grid; gap: 24px 40px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  margin: 0;
}
.site-links h2 {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em; font-weight: 600;
  color: var(--ink-faint); margin: 0 0 10px;
}
.site-links ul { list-style: none; margin: 0; padding: 0; }
.site-links li { margin-bottom: 7px; font-size: 14px; }
.site-links a { color: var(--ink-soft); text-decoration: none; }
.site-links a:hover { color: var(--accent); text-decoration: underline; }

.colophon .licence { margin: 28px 0 0; }
.colophon .licence a { color: var(--ink-soft); }

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

@media (max-width: 720px) {
  h1 { font-size: 25px; }
  h2 { font-size: 21px; }
  .controls fieldset { flex: 1 1 100%; }
  #search { width: 100%; }
  .masthead nav { gap: 0; }
  .masthead nav a { padding: 7px 8px; }
}

/* ============================================================== the audit === */

/* --------------------------------------------------------------- chrome --- */

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--paper); color: var(--accent); padding: 10px 16px; z-index: 40;
  border: 1px solid var(--accent-line); border-radius: 0 0 4px 0;
}
.skip:focus { left: 0; }

/* Read out, never drawn. The flag matrix puts the flag in every cell this way:
 * the fill is for the eye and the word is for everything else. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Back to the masthead from the bottom of a dataset page, which is long. Hidden
 * until the page has been scrolled, and never shown to a reader who has asked
 * for less motion to have something appear under their thumb. */
.to-top {
  position: fixed; right: 20px; bottom: 20px; z-index: 30;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 13px; border-radius: 999px;
  background: var(--paper); color: var(--ink-soft);
  border: 1px solid var(--rule-strong); box-shadow: var(--shadow-lift);
  font-size: 13px; text-decoration: none;
  opacity: 0; visibility: hidden; transition: opacity 0.2s ease;
}
.to-top.shown { opacity: 1; visibility: visible; }
.to-top:hover { color: var(--accent); border-color: var(--accent-line); }

.page-head { margin: 8px 0 8px; }
.page-head h1 { margin-bottom: 8px; }

.hero { margin: 22px 0 10px; max-width: var(--measure); }
.hero h1 { font-size: 40px; line-height: 1.12; letter-spacing: -0.03em; margin: 0 0 16px; }

.note {
  font-size: 14px; color: var(--ink-soft);
  background: var(--wash); border-left: 3px solid var(--rule-strong);
  padding: 12px 16px; margin: 16px 0; max-width: var(--measure);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.note.warn { border-left-color: var(--warning); }

/* ------------------------------------------------------ headline numbers --- */

/* The organisation site's headline panel: one hairline grid, cells on paper,
 * the whole thing rounded and bordered. Same component, same numbers. */
.stat-grid {
  list-style: none; padding: 0; margin: 24px 0 8px;
  display: grid; gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  background: var(--rule); border: 1px solid var(--rule);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
}
.stat-grid li { background: var(--paper); padding: 20px 22px; min-width: 0; }
.stat {
  display: block; font-size: 36px; line-height: 1.05; letter-spacing: -0.03em;
  font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums;
}
.stat-label { display: block; font-size: 14px; color: var(--ink-soft); margin: 10px 0 6px; line-height: 1.45; }
.stat-grid .fine { display: block; font-size: 13px; }

/* The same panel on a dataset page, where the four cells are that dataset's own
 * figures and each one is a word rather than a count. */
.glance .stat { font-size: 26px; }
/* The one categorical headline among four numeric ones. It keeps the chip, at a
 * line height tighter than the default so the cell is not taller than the three
 * beside it by the height of two paddings. */
.glance .stat .flag { font-size: 21px; font-weight: 600; line-height: 1.25; padding: 3px 15px; }
.glance .stat-label { margin-top: 8px; }
.glance li a { font-size: 13px; }

/* The whole card is the link, not the heading inside it. A card that looks
 * clickable and is only clickable across the two words at the top is a card a
 * reader has to aim at; the padding moves onto the `<a>` so its hit area is the
 * box that lifts on hover. `<a>` takes flow content, so the description sits
 * inside it and needs no second target. */
.cards {
  list-style: none; padding: 0; margin: 20px 0 8px;
  display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(235px, 1fr));
}
.cards li {
  display: flex;
  border: 1px solid var(--rule); border-radius: var(--radius);
  min-width: 0; background: var(--paper); box-shadow: var(--shadow);
}
.cards a {
  display: block; width: 100%; padding: 20px 22px;
  text-decoration: none; border-radius: inherit;
}
.cards a strong { font-size: 16px; font-weight: 600; }
.cards a:hover strong { text-decoration: underline; }
.cards p { font-size: 14px; color: var(--ink-soft); margin: 6px 0 0; }
.cards li:hover, .cards li:focus-within {
  border-color: var(--accent-line); box-shadow: var(--shadow-lift);
}
/* Inset, because the ring is drawn on the link and the border it would sit
 * outside of belongs to the `<li>`. */
.cards a:focus-visible { outline: 2px solid var(--accent-line); outline-offset: -3px; }

/* The organisation site's arrow list, for a short list of what is on a page. */
.arrows { list-style: none; padding: 0; margin: 14px 0; max-width: var(--measure); }
.arrows li {
  display: flex; gap: 12px; font-size: 15px; color: var(--ink-soft);
  margin-bottom: 10px; line-height: 1.5;
}
.arrows li::before { content: "\2192"; color: var(--accent); flex: none; }

/* -------------------------------------------------------------- figures --- */

/* A figure is never the only statement of its numbers. Every one of them carries
 * a table of the same values in a `<details>` underneath, because a chart is a
 * picture of a measurement and a reader who wants the measurement should not have
 * to read it off a bar. That is also what makes the figures usable with a screen
 * reader, and what makes a number quotable from this site. */

.figures { margin: 34px 0 8px; }
.figures > p { max-width: var(--measure); }

.fig {
  margin: 20px 0 6px; padding: 18px 20px 14px;
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
/* The chart keeps its own light canvas whatever the theme -- see the note on
 * `--figure-canvas` at the top of this file. In the light theme it is the card's
 * own colour, so this shows only in the dark one. */
.fig .chart {
  display: block; max-width: 100%; height: auto; overflow: visible;
  background: var(--figure-canvas); border-radius: var(--radius-sm);
}
.fig figcaption { margin: 10px 0 0; }
.fig .fig-caption, .fig .fig-note {
  font-size: 13px; color: var(--ink-faint); max-width: var(--measure-fine); margin: 4px 0 0;
}
.fig figcaption b { color: var(--ink-soft); font-weight: 600; }

.fig-table { margin: 10px 0 0; font-size: 13px; }
.fig-table summary {
  cursor: pointer; color: var(--ink-faint); font-size: 13px;
  padding: 2px 0; width: max-content;
}
.fig-table summary:hover { color: var(--accent); }
.fig-table table { border-collapse: collapse; margin: 8px 0 4px; font-size: 13px; }
.fig-table th, .fig-table td {
  padding: 4px 12px 4px 0; text-align: left; vertical-align: baseline;
  border-bottom: 1px solid var(--rule); color: var(--ink-soft);
}
.fig-table td.right, .fig-table th.right { text-align: right; font-variant-numeric: tabular-nums; }
.fig-table thead th { color: var(--ink-faint); font-weight: 600; }

/* The chart's own type scale. Set here rather than in the SVG so that one file
 * governs the site's typography, and so a figure inherits the page's font stack
 * instead of naming one of its own. These fills are not themed: they are ink on
 * the figure's light canvas, which does not change. */
.chart { font-family: inherit; }
.chart text { fill: #1c2321; }
.chart .lab { font-size: 11px; }
.chart .rowlab { font-size: 10.5px; fill: #2c3634; }
.chart .colhead { font-size: 9px; fill: #4a5654; }
.chart .band {
  font-size: 8.5px; fill: #6d7a77; letter-spacing: 0.05em; text-transform: uppercase;
}
.chart .group { font-size: 11px; font-weight: 600; }
.chart .tick { font-size: 10px; fill: #6d7a77; }
.chart .axis { font-size: 10px; fill: #4a5654; }
.chart .val { font-size: 10.5px; fill: #2c3634; font-variant-numeric: tabular-nums; }
.chart .leg { font-size: 10.5px; fill: #4a5654; }
.chart .sub { font-size: 9px; fill: #6d7a77; }

/* A mark that can be selected, and a mark that can be opened. Both say so before
 * they are pressed: the pointer changes, and the mark lifts out of the row it
 * sits in. `paint-order` puts the halo behind the fill, so a dot in a dense strip
 * separates from the ones under it without changing colour -- the colour is the
 * flag and is not free to carry a second meaning. */
.chart .hit, .chart .dot, .chart .median { cursor: pointer; }
.chart .hit:hover, .chart .hit:focus-visible { stroke: #1c2321; stroke-width: 1.5; }
.chart .dot { paint-order: stroke; transition: r 0.1s ease; }
.chart a:hover .dot, .chart a:focus-visible .dot { r: 5; stroke: #1c2321; stroke-width: 1.2; }

/* What a figure says when its filters have left it nothing to draw. Stated
 * rather than drawn empty: an axis with no marks on it reads as a measurement
 * that came back zero. */
.fig-empty { margin: 8px 0; font-size: 14px; color: var(--ink-faint); }

/* The two live figures sit in the same card as every other figure, and are given
 * a minimum height so the page does not jump as a filter changes how many rows
 * their tallies are drawn from. */
#explore .fig { margin: 18px 0; }

/* ------------------------------------------------------------- readout --- */

/* What a mark says when it is pointed at or focused.
 *
 * One element for the whole document rather than one per figure, positioned in
 * page coordinates and hidden on scroll -- a readout placed against the viewport
 * is wrong the moment the viewport moves. It is `position: absolute` and not
 * `fixed` so that it scrolls out with its mark rather than hanging over the page.
 *
 * It takes the page's surface in either theme, unlike the figure it sits over:
 * this is a sentence, and a sentence is chrome. */
.readout {
  position: absolute; z-index: 60; max-width: 40ch; pointer-events: none;
  font-size: 12.5px; line-height: 1.45; padding: 7px 10px;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule-strong); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lift);
}
.readout[hidden] { display: none; }

/* --------------------------------------------------------- flag matrix --- */

/* The one figure that is a table, and the site's way into itself.
 *
 * Rendered by `gb_audit/matrix.py` as real rows and cells rather than as SVG,
 * because every mark in it is a link and every filter here is a hidden row. The
 * palette is the same one `charts.py` validated, and for the same reason the SVG
 * figures keep a light canvas in both themes, so does this grid: the flag ramp was
 * chosen for a light background and ordered by lightness, and inverting the
 * surface under it would spend that work. The controls above it sit on the card
 * and do theme, because they are chrome and not the figure.
 */

.mx { padding: 14px 16px 12px; }
.mx-controls[hidden] { display: none; }
.mx-controls {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  margin: 0 0 12px;
}
.mx-group { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.mx-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em;
  font-weight: 600; color: var(--ink-faint); margin-right: 2px;
}
.mx-chip {
  font: inherit; font-size: 12.5px; padding: 4px 9px;
  display: inline-flex; align-items: baseline; gap: 6px;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  background: var(--paper); color: var(--ink-soft); cursor: pointer;
}
.mx-chip:hover { border-color: var(--accent-line); color: var(--accent); }
.mx-chip[aria-pressed="true"] {
  background: var(--accent-wash); border-color: var(--accent-line);
  color: var(--accent-on-wash); font-weight: 600;
}
.mx-n { font-size: 11px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.mx-chip[aria-pressed="true"] .mx-n { color: var(--accent-on-wash); }
.mx-status { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.mx-status .ghost { font-size: 12.5px; padding: 4px 10px; }
.mx-status .ghost[hidden] { display: none; }

/* The grid is not boxed. 93 rows is about 1,900 pixels, and a scrollbox inside
 * the page hides the one thing the figure is for: that the corpus is 93 rows
 * long. Capped at 780 pixels it looked like whatever fitted in 780 pixels. So
 * the page scrolls and the whole grid is on it, with the headings following --
 * sticky to the viewport, offset by the masthead they would slide under.
 *
 * Narrow viewports are the exception, below. There the grid scrolls sideways
 * under a name column that stays, which is the one arrangement where a cell keeps
 * a label a reader can see. */
.mx-scroll {
  background: var(--figure-canvas);
  border: 1px solid #e6eae9; border-radius: var(--radius-sm);
}
.mx-scroll:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; }

.mx-grid {
  border-collapse: separate; border-spacing: 0; width: 100%;
  color: #1c2321; font-variant-numeric: tabular-nums;
  /* The band row's height, given rather than measured. Both heading rows stick,
   * one under the other, and the second one's offset is the first one's height:
   * left as two independent numbers, a millimetre of disagreement is a sliver of
   * the page showing between them as the grid scrolls past. */
  --mx-band: 21px;
}
.mx-grid a { color: inherit; text-decoration: none; }
.mx-grid a:hover { color: #0f766e; text-decoration: underline; }

.mx-bands th {
  position: sticky; top: var(--masthead-height); z-index: 3;
  background: var(--figure-canvas);
  font-size: 8.5px; font-weight: 500; color: #6d7a77;
  letter-spacing: 0.05em; text-transform: uppercase; text-align: center;
  /* 12 of line, 8 of padding, 1 of rule: the 21 above, spent. The rule is drawn
   * by the pseudo-element below and the border only holds the space, so that the
   * band row's height stays the 21 the sticky offset is written against. */
  line-height: 12px; height: var(--mx-band);
  padding: 6px 2px 2px; border-bottom: 1px solid transparent;
}
/* Each family's rule stops six pixels short at both ends, so the three run as
 * three brackets with a gap at every boundary rather than as one line under all
 * ten columns. Which six columns are the probe checks is the only thing this row
 * is for, and a continuous rule was answering a different question. */
.mx-bands th::after {
  content: ""; position: absolute; left: 6px; right: 6px; bottom: -1px;
  height: 1px; background: #cfd6d4;
}
.mx-bands td {
  position: sticky; top: var(--masthead-height); left: 0; z-index: 5;
  height: var(--mx-band); background: var(--figure-canvas);
}
.mx-heads th {
  position: sticky; top: calc(var(--masthead-height) + var(--mx-band)); z-index: 3;
  background: var(--figure-canvas);
  font-size: 9px; font-weight: 500; color: #4a5654; line-height: 1.25;
  text-align: center; vertical-align: bottom;
  padding: 4px 3px 6px; border-bottom: 1px solid #cfd6d4;
}
.mx-heads .mx-corner {
  left: 0; z-index: 5; text-align: left; padding-left: 8px;
  font-size: 9px; letter-spacing: 0.06em; text-transform: uppercase;
}
.mx-heads th a:hover { color: #0f766e; }

/* One `<tbody>` per collection, its heading spanning the grid. The heading is a
 * link into the catalogue: a reader who has found their collection here almost
 * always wants its rows with the numbers attached. */
.mx-groupline[hidden] { display: none; }
.mx-groupline th {
  text-align: left; font-size: 11px; font-weight: 600;
  padding: 12px 8px 4px; border-bottom: 1px solid #e6eae9;
  background: var(--figure-canvas);
}
.mx-groupline th a { border-bottom: 1px solid transparent; }
.mx-groupline th a:hover { color: #0f766e; }
.mx-groupline .mx-n { margin-left: 7px; }

.mx-grid tr[data-collection] th.mx-name {
  position: sticky; left: 0; z-index: 2;
  background: var(--figure-canvas);
  text-align: left; font-weight: 400; font-size: 10.5px; color: #2c3634;
  padding: 0 10px 0 8px; max-width: 230px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border-right: 1px solid #e6eae9;
}
.mx-grid tr[data-collection]:hover th.mx-name { background: #f2f6f5; }
.mx-grid tr[data-collection]:hover .mx-cell { background: #f2f6f5; }

/* The cell is the gap and the link is the mark, so the grid reads as a lattice
 * rather than as a solid block, and a check with nothing to run on is an empty
 * box rather than a hole in the drawing. */
.mx-cell { padding: 1px; border-right: 1px solid #eef1f0; }
.mx-cell a {
  display: block; min-width: 46px; height: 15px; border-radius: 2px;
}
/* Sized as a cell, not as a mark: `mx-blank` is on the `<td>` itself, and the
 * legend reuses the class on a swatch. Keeping the width here and off the class
 * is what lets the swatch be 12 pixels square like the other three. */
td.mx-blank { min-width: 46px; height: 15px; }
.mx-cell a:focus-visible { outline: 2px solid #0f766e; outline-offset: 1px; }
.mx-cell a:hover { outline: 2px solid #0f766e; outline-offset: 0; }
.mx-Pass a { background: var(--flag-fill-pass); }
.mx-Warning a { background: var(--flag-fill-warning); }
.mx-Fail a { background: var(--flag-fill-fail); }
.mx-Unknown a {
  background: #ffffff; border: 1px solid var(--flag-fill-unknown); height: 13px;
}

.mx-empty[hidden] { display: none; }
.mx-empty {
  margin: 12px 0 0; font-size: 14px; color: var(--ink-soft);
  background: var(--wash); border-left: 3px solid var(--rule-strong);
  padding: 12px 16px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.mx-legend {
  list-style: none; display: flex; flex-wrap: wrap; gap: 6px 18px;
  margin: 10px 0 6px; padding: 0; font-size: 12.5px; color: var(--ink-faint);
}
.mx-legend li { display: inline-flex; align-items: center; gap: 7px; }
.mx-swatch {
  width: 12px; height: 12px; border-radius: 2px; flex: none;
  border: 1px solid rgb(28 35 33 / 0.12);
}
.mx-swatch.mx-Pass { background: var(--flag-fill-pass); }
.mx-swatch.mx-Warning { background: var(--flag-fill-warning); }
.mx-swatch.mx-Fail { background: var(--flag-fill-fail); }
.mx-swatch.mx-blank { background: #ffffff; border-color: #b9c2c0; }

/* The note under the grid runs the grid's own width, not the 44rem of fine print
 * a chart's caption gets. That measure is for a caption sitting under a drawing;
 * this one sits under a table 1,172 pixels wide, and a line that stops a third of
 * the way across reads as a stray column beside the thing it is describing. */
.mx figcaption .fig-caption { max-width: none; }

/* Ten columns and a name column need about 700px, so below 800 the grid gets a
 * scroll container of its own for the sideways axis. That container is also what
 * a sticky child resolves against, so the column headings stop tracking the
 * viewport here and the name column becomes the label that holds -- which is the
 * one that matters at this width, a row being unreadable without its dataset. */
@media (max-width: 800px) {
  .mx-scroll { overflow-x: auto; overscroll-behavior-x: contain; }
  .mx-bands th, .mx-bands td { top: 0; }
  .mx-heads th { top: var(--mx-band); }
}

@media (max-width: 720px) {
  .mx-grid tr[data-collection] th.mx-name { max-width: 130px; font-size: 10px; }
  .mx-cell a, td.mx-blank { min-width: 34px; }
  .mx-status { margin-left: 0; }
}

/* ---------------------------------------------------------------- flags --- */

/* A flag is a word before it is a colour. The chip carries both, and the two
 * absences are kept apart: `Unknown` is a check that ran and could not be scored,
 * a blank is a check that had nothing to run on, and neither is a Pass. */
.flag-blank { color: var(--ink-faint); font-weight: 400; cursor: help; }
.flag[title] { cursor: help; }

.kind {
  font-size: 12px; color: var(--ink-faint);
}

.badge-line { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 12px 0 16px; }
.badge {
  display: inline-block; font-size: 12px; letter-spacing: 0.03em;
  padding: 4px 10px; border-radius: 999px; background: var(--wash);
  color: var(--ink-soft); border: 1px solid var(--rule); white-space: nowrap;
}
.badge-core { background: var(--accent-wash); color: var(--accent-on-wash); border-color: var(--accent-wash-strong); }

.ghost {
  font: inherit; font-size: 13px; padding: 6px 12px;
  border: 1px solid var(--rule-strong); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink-soft); cursor: pointer; text-decoration: none;
  display: inline-flex; align-items: center; gap: 6px;
}
.ghost:hover { border-color: var(--accent-line); color: var(--accent); }

/* -------------------------------------------------------- dataset pages --- */

.facts {
  display: grid; grid-template-columns: max-content 1fr; gap: 6px 20px;
  font-size: 14px; margin: 16px 0 4px; max-width: 70ch;
}
.facts dt { color: var(--ink-faint); }
.facts dd { margin: 0; color: var(--ink-soft); }

.rollup { font-size: 16px; margin: 6px 0 10px; }
.rollup .flag { font-size: 17px; }

/* The identifier, with a button that puts it on the clipboard. It is the string
 * a reader needs in order to name this dataset anywhere else, it is 50
 * characters long, and selecting it by hand off a heading breaks on the `<wbr>`
 * the heading needs in order to wrap. */
.id-line { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 0 0 14px; }
.id-line code { font-size: 13px; overflow-wrap: anywhere; }
.copied { font-size: 12px; color: var(--pass); font-weight: 600; }

/* Previous and next inside this dataset's collection, either side of where in it
 * this one falls. A dataset page is one of 93 and had no way to the 92 others
 * except back through the catalogue. */
.pager {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between;
  margin: 20px 0 8px; padding: 14px 16px;
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius);
  font-size: 14px;
}
.pager a { text-decoration: none; display: inline-flex; gap: 7px; align-items: baseline; max-width: 42ch; }
.pager a:hover { text-decoration: underline; }
.pager .pager-dir { color: var(--ink-faint); font-size: 12px; text-transform: uppercase; letter-spacing: 0.07em; }
.pager .pager-where { color: var(--ink-faint); font-size: 13px; text-align: center; flex: 1 1 auto; }
.pager .pager-none { color: var(--ink-faint); }

.ref-mark {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--accent-on-wash); background: var(--accent-wash-strong);
  padding: 2px 7px; border-radius: 999px; margin-left: 6px; cursor: help;
}
.listing tr.is-reference { background: var(--accent-wash); }
.listing tr.is-reference:hover { background: var(--accent-wash); }

/* -------------------------------------------------------------- reports --- */

.reports { list-style: none; padding: 0; margin: 10px 0 4px; }
.reports li { padding: 4px 0; font-size: 14px; }
.reports .fine { margin-left: 8px; font-size: 12px; }
.report-leakage-scan a { color: var(--ink); }
.reports li[hidden] { display: none; }
.table-card[hidden] { display: none; }

/* The offer of a dataset's reports, in its page head.
 *
 * Filled rather than outlined, unlike every other button on this site. It is the
 * one thing in that head a reader can act on, it competes with a 50-character
 * identifier and a copy button beside it, and it used to be at the foot of the
 * page where nobody found it. */
.reports-cta { margin: 16px 0 0; }
.cta {
  display: inline-block; text-decoration: none; font-size: 13.5px; font-weight: 600;
  padding: 7px 14px; border-radius: 999px;
  background: var(--accent); color: var(--paper);
  border: 1px solid var(--accent);
}
.cta:hover {
  background: var(--accent-hover); border-color: var(--accent-hover);
  color: var(--paper); text-decoration: none;
}
.reports-cta .fine { margin: 0; }

.kinds { max-width: var(--measure); }
.kinds dt { font-weight: 600; margin-top: 14px; color: var(--ink); }
.kinds dd { margin: 4px 0 0; color: var(--ink-soft); font-size: 15px; }

/* The frame is tall on purpose: these reports are long documents, and a short
 * frame makes a reader scroll a scrollbar inside a scrollbar. `resize` lets them
 * make it taller still. The frame keeps a light background whatever the theme,
 * for the reason the figures do: the report was written against one. */
.report-frame {
  width: 100%; height: 78vh; min-height: 520px;
  border: 1px solid var(--rule); border-radius: var(--radius); background: var(--figure-canvas);
  margin: 8px 0 10px; resize: vertical;
}
.report-head { margin-bottom: 4px; }

@media (max-width: 720px) {
  .hero h1 { font-size: 28px; }
  .stat { font-size: 30px; }
  .report-frame { height: 68vh; }
  .to-top { right: 12px; bottom: 12px; }
}

/* A reader who has asked for less motion gets none of it: no smooth scroll, no
 * rotating chevron, no fading button. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .row-toggle svg, .to-top, .drawer-toggle .drawer-caret { transition: none; }
}

/* ------------------------------------------------------------------ jumpnav ---
   Where the reader is on a page long enough to get lost on. Sticky under the
   masthead, so it is reachable from anywhere down the page rather than only
   from the top -- which is where a reader who needs it least already is. */

.jumpnav {
  position: sticky;
  top: var(--masthead-height);
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  margin: 2rem 0;
  padding: 0.65rem 1rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.jumpnav-label {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.jumpnav ol {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.jumpnav a {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  font-size: 0.88rem;
  text-decoration: none;
  border-radius: 999px;
  border: 1px solid transparent;
  color: var(--ink-soft);
}

.jumpnav a:hover { background: var(--accent-wash); color: var(--accent-on-wash); }

/* Set by `site.js` as the reader passes each section. Never colour alone: the
   current item also carries a border, so it survives a greyscale print and a
   reader who cannot separate the two hues. */
.jumpnav a[aria-current="true"] {
  background: var(--accent-wash);
  border-color: var(--accent-line);
  color: var(--accent-on-wash);
  font-weight: 600;
}

/* --------------------------------------------------------------- thresholds ---
   The sliders over the grid. Boxed and set off from the page, because what is
   inside the box is the only thing on this site a reader can change. */

.thresholds {
  margin: 0 0 1.5rem;
  padding: 1.1rem 1.25rem;
  background: var(--wash);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

/* Moved off the shipped setting. The left rule is the second signal beside the
   banner: a reader who scrolled past the banner still has it on screen. */
.thresholds.is-moved {
  border-left: 4px solid var(--warning);
  background: var(--paper);
}

.thresholds .th-head h3 { margin: 0 0 0.25rem; font-size: 1rem; }
.thresholds .th-head p { margin: 0 0 0.9rem; max-width: var(--measure-fine); }

.th-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 1rem 1.5rem;
}

.th-control { display: grid; gap: 0.3rem; min-width: 14rem; flex: 1 1 14rem; }
.th-control label { font-size: 0.85rem; color: var(--ink-soft); }
.th-control output {
  font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.th-control input[type="range"] { width: 100%; accent-color: var(--accent-line); }

.th-summary {
  margin: 0.9rem 0 0;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* A cell whose flag is not the one the run published. Dashed outline rather than
   a different fill: the fill is the flag, and a second meaning on the same
   channel would make "which flag is this" and "did this move" the same
   question. */
.mx-cell.mx-moved { outline: 2px dashed var(--ink); outline-offset: -3px; }

/* --------------------------------------------------------------------- joint ---
   The one number on a dataset page the ten checks cannot produce between them. */

.joint-card {
  margin: 0 0 1rem;
  padding: 1rem 1.15rem;
  background: var(--wash);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--accent-line);
  border-radius: var(--radius);
}

.joint-card .joint-value { display: grid; gap: 0.15rem; margin: 0 0 0.75rem; }
.joint-card .joint-value .stat { font-size: 2.2rem; line-height: 1.1; }
.joint-card p:last-child { margin-bottom: 0; }

/* The lower-bound mark, beside a joint figure wherever one is shown. */
abbr.lb {
  margin-left: 0.15rem;
  border: 0;
  color: var(--ink-faint);
  cursor: help;
  text-decoration: none;
}

/* A finding rather than a caveat: this dataset is one no check flagged and the
   features recovered anyway. */
.note.flagged {
  border-left: 4px solid var(--warning);
  padding-left: 0.9rem;
}

/* The joint gate's own qualification, under the funnel step it qualifies. */
.gate-note td { padding-top: 0; border-top: 0; color: var(--ink-faint); }

/* ---------------------------------------------------------------- percentile ---
   Where one dataset's figures sit among the ones this run measured. */

.percentile { margin: 1.25rem 0 0; }
.percentile h3 {
  margin: 0 0 0.4rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.rank-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.6rem;
  margin: 0 0 0.4rem;
  padding: 0;
  list-style: none;
}

.rank-list li {
  padding: 0.25rem 0.7rem;
  font-size: 0.87rem;
  background: var(--wash);
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink-soft);
}

/* ------------------------------------------------------------ dataset nav ---
   A dataset page is two clicks from the overview and used to say nothing about
   where in the corpus it sat. The left column is that map: every dataset, under
   the collection it came from, with this one marked.

   Two columns above the fold width and one below it. On a narrow screen the nav
   goes above the page rather than beside it, collapsed, because 93 links pushing
   the dataset's own name off the screen is worse than a tap to open them. */

.with-sidebar {
  display: grid;
  gap: 2rem;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 60rem) {
  .with-sidebar { grid-template-columns: 15rem minmax(0, 1fr); }
  .dataset-nav {
    position: sticky;
    top: calc(var(--masthead-height) + 1rem);
    align-self: start;
    max-height: calc(100vh - var(--masthead-height) - 2rem);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

.sidebar-main { min-width: 0; }

.dataset-nav {
  padding: 0.9rem 1rem;
  font-size: 0.88rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.sb-head {
  margin: 0 0 0.3rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.sb-all { margin: 0 0 0.75rem; font-size: 0.85rem; }

.sb-group { border-top: 1px solid var(--rule); }
.sb-group:first-of-type { border-top: 0; }

.sb-group > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.45rem 0;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.sb-group > summary::-webkit-details-marker { display: none; }

/* The disclosure triangle, drawn rather than inherited, so it turns with the
   group and sits where the text starts. */
.sb-group > summary::before {
  content: "\25B8";
  margin-right: 0.35rem;
  color: var(--ink-faint);
  transition: transform 120ms ease;
}
.sb-group[open] > summary::before { transform: rotate(90deg); }

.sb-n {
  margin-left: auto;
  padding: 0 0.4rem;
  font-size: 0.75rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  background: var(--wash);
  border-radius: 999px;
}

.dataset-nav ul {
  margin: 0 0 0.5rem;
  padding: 0 0 0 0.75rem;
  list-style: none;
  border-left: 1px solid var(--rule);
}

.dataset-nav ul a {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.22rem 0.4rem;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
}

.dataset-nav ul a:hover { background: var(--accent-wash); color: var(--accent-on-wash); }

/* Where you are. A fill, a weight and a rule -- never the fill alone. */
.dataset-nav ul a[aria-current="page"] {
  background: var(--accent-wash);
  box-shadow: inset 3px 0 0 var(--accent-line);
  color: var(--accent-on-wash);
  font-weight: 600;
}

/* The dataset's rollup flag, as a dot. Decoration beside a name that is already
   the link's text, so it is hidden from the accessibility tree: the flag is
   stated in words on the page the link opens. */
.sb-flag {
  flex: 0 0 auto;
  width: 0.5rem;
  height: 0.5rem;
  margin-left: auto;
  border-radius: 50%;
  background: var(--flag-fill-unknown);
}
.sb-flag.flag-Pass { background: var(--flag-fill-pass); }
.sb-flag.flag-Warning { background: var(--flag-fill-warning); }
.sb-flag.flag-Fail { background: var(--flag-fill-fail); }
