/*
 * The site's one stylesheet: design tokens, page layout, and the components every page uses.
 *
 * Colours are tokens on :root, redefined for dark mode. Chart series colours
 * are the eight series slots; a chart assigns them in order and never
 * cycles. Components are named after what they are, not where they sit.
 */

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Crimson+Text:wght@600;700&display=swap");

/* ---------- Tokens ---------- */

/*
 * The light scheme is Open Data's: a warm paper, white cards, a warm ink and the Harvard crimson. The dark scheme below
 * turns the same inks over. tests/palette_contrast.test.js reads both blocks and checks every colour's contrast.
 */
:root {
  color-scheme: light;

  --font-sans: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-serif: "Crimson Text", Georgia, Cambria, "Times New Roman", serif;
  --font-mono: ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
  --font-size-smallest: 0.8125rem; /* 14.6 px at the 18 px base: no caption, label, cell or tick is set smaller */

  --color-accent: #a51c30;
  --color-accent-strong: #7f1425; /* the accent under the pointer: darker in light, lighter in dark */
  --color-accent-wash: #fbf0f2;
  --color-on-accent: #ffffff; /* text on a field of the accent, such as the primary button */

  --color-text: #1c1917;
  --color-text-muted: #49423e;
  --color-text-faint: #716965;
  --color-background: #f8f7f5;
  --color-surface: #ffffff;
  --color-surface-raised: #f1efec;
  --color-border: #e4dfdb;

  --shadow-subtle: 0 1px 2px rgb(28 25 23 / 0.06);
  --shadow-card: 0 1px 2px rgb(28 25 23 / 0.04), 0 12px 32px -20px rgb(28 25 23 / 0.22);
  --radius: 0.9rem;
  --radius-small: 0.375rem;
  --radius-button: 0.65rem;
  --page-width: 76rem; /* Open Data's width: the header's links fit one row in it, and the header, page and footer align */
  --header-height: 4.5rem; /* the sticky header's height on one row, or a little more where its links wrap below */
  --loading-card-height: 26rem; /* about a drawn figure card's height, so a loading card holds the place of one */
  --gutter: clamp(1rem, 4vw, 3.5rem); /* Open Data's gutter, with the phone's 1rem kept so 360 px still fits */

  /* Chart ink: recessive grid and axes, muted labels. */
  --chart-grid: #e4dfdb;
  --chart-axis: #c4bcb7;
  --chart-label: var(--color-text-faint);

  /*
   * Categorical series, in the fixed order charts assign them. A ninth series folds into "Other".
   * Eight OKLCH hues, the same in both schemes: blue 255°, orange 50°, green 143°, amber 81°, magenta 340°, teal 192°,
   * violet 293° and red 18°. They are not evenly spread, because the paper's four (blue, orange, green and red) are
   * fixed, and its red and orange stand only 26° apart; 30° is the floor between any two, and the other four fill
   * the wheel around them. In light most slots are the lightest colour of their hue that keeps 3.3:1 on the white
   * card, at the most chroma sRGB holds there (capped at 0.19, short of neon). Five are set apart in lightness so
   * that a reader with red-green colour blindness can still tell every pair apart: blue, teal, red and amber deeper
   * (3.8 to 4:1), and green deeper still (4.4:1), where it would otherwise merge with amber and red. Amber leans
   * towards orange (81°) so that it reads golden rather than olive.
   */
  --series-1: #1a82f2;
  --series-2: #df6d19;
  --series-3: #0a8d12;
  --series-4: #a67700;
  --series-5: #dd5db9;
  --series-6: #19918e;
  --series-7: #9a76fa;
  --series-8: #ed3d57;
  --series-other: #938a86;

  /* The four parts of a session's time as the paper colours them: prefill blue, decode orange, tool green, user red. */
  --part-prefill: var(--series-1);
  --part-decode: var(--series-2);
  --part-tool: var(--series-3);
  --part-user: var(--series-8);

  /* The three parts of a request's tokens, the same everywhere they are drawn, in slots no part of a session's time
     uses: cached input teal, uncached input amber, output magenta. A stacked chart of tokens and one of time never
     show one hue with two meanings. */
  --token-cached: var(--series-6);
  --token-uncached: var(--series-4);
  --token-output: var(--series-5);

  /* What a wait before a request waited for, the same everywhere it is drawn: a tool and the user in their parts'
     colours, a subagent violet, the slot no part of a session's time uses, and an ask-user tool amber. */
  --cause-tool: var(--part-tool);
  --cause-ask-user: var(--series-4);
  --cause-user: var(--part-user);
  --cause-subagent: var(--series-7);

  /* A wait on the Session page's Timeline is a pale tint of its part's colour, since nothing ran: the colour mixed
     towards the card in light and towards the text ink in dark, so it is lighter than the card in both schemes. */
  --wait-tint-base: var(--color-surface);
  --wait-tool: color-mix(in srgb, var(--part-tool) 45%, var(--wait-tint-base));
  --wait-user: color-mix(in srgb, var(--part-user) 45%, var(--wait-tint-base));
  --wait-subagent: color-mix(in srgb, var(--cause-subagent) 45%, var(--wait-tint-base));

  /* The roles of a request's input, in slots no token part uses, since the Context view splits one area either way:
     system violet, and the three others in the colour of the part of a session's time they come from, the user's
     red, the assistant's (what the model decoded) orange and tool results green; tool definitions grey. */
  --role-system: var(--series-7);
  --role-user: var(--part-user);
  --role-assistant: var(--part-decode);
  --role-tool-results: var(--part-tool);
  --role-tool-definitions: var(--series-other);

  /* How a request's context changed from the one before it: appended to, or rewritten. */
  --transition-append: var(--series-3);
  --transition-mutation: var(--series-8);

  /* The eight tool groups of the tool mix along a turn: Read blue, Search amber, Write/Edit violet, Execute green,
     Build/Test teal, Git/VCS red, Browser/Web magenta and Other grey. Every tool category takes its group's colour
     (`toolCategoryColours` in theme/colours.js), so a colour names one group on every card. */
  --tool-group-read: var(--series-1);
  --tool-group-search: var(--series-4);
  --tool-group-write-edit: var(--series-7);
  --tool-group-execute: var(--series-3);
  --tool-group-build-test: var(--series-6);
  --tool-group-git-vcs: var(--series-8);
  --tool-group-browser-web: var(--series-5);
  --tool-group-other: var(--series-other);

  /* The six gap bins, shortest gap lightest: the first series' blue (OKLCH hue 255°) from 64% to 32% lightness in even
     steps, so the lightest keeps 3:1 on the card and the darkest stays blue. */
  --gap-bin-1: #2a8bf9;
  --gap-bin-2: #1477e0;
  --gap-bin-3: #1065bf;
  --gap-bin-4: #0b53a0;
  --gap-bin-5: #074281;
  --gap-bin-6: #043264;

  /* A highlighted row, step or bar: a wash of the amber slot's hue, its bright dark-scheme tone, in both schemes. */
  --color-highlight: rgb(233 172 19 / 0.25);
}

/*
 * The dark scheme: Open Data's ink as the paper, each surface one step lighter, the inks turned over with the same
 * warmth, and the crimson lifted to keep its contrast. The series keep their light hues; most are the darkest colour of
 * their hue that keeps 5.5:1 on the dark card, blue and teal a step darker (4.8:1) and amber much lighter (8:1), so
 * every pair stays apart for a red-green colour-blind reader here too.
 */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --color-accent: #f07a9a; /* crimson turned pink, so that it is never taken for the red series */
    --color-accent-strong: #f6a3bb;
    --color-accent-wash: rgb(240 122 154 / 0.14);
    --color-on-accent: #1c1917;

    --color-text: #f1efec;
    --color-text-muted: #cfc7c2;
    --color-text-faint: #a69d98;
    --color-background: #1c1917;
    --color-surface: #262220;
    --color-surface-raised: #302b28;
    --color-border: #3d3633;

    --shadow-subtle: 0 1px 2px rgb(0 0 0 / 0.4);
    --shadow-card: 0 1px 2px rgb(0 0 0 / 0.3), 0 12px 32px -20px rgb(0 0 0 / 0.6);

    --chart-grid: #3d3633;
    --chart-axis: #5b534f;

    --series-1: #338ffa;
    --series-2: #f1761c;
    --series-3: #38af38;
    --series-4: #e9ac13;
    --series-5: #eb6ac5;
    --series-6: #1d9e9a;
    --series-7: #a386fa;
    --series-8: #fb6874;
    --series-other: #8c8480;

    /* The gap bins on the dark card: the same blue from 90% to 62% lightness, so the darkest keeps 3:1 on it. */
    --gap-bin-1: #cae0fd;
    --gap-bin-2: #abcffd;
    --gap-bin-3: #8cbdfc;
    --gap-bin-4: #6cabfb;
    --gap-bin-5: #4798fa;
    --gap-bin-6: #1d84f5;

    --wait-tint-base: var(--color-text);
  }
}

/* ---------- Base ---------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The base type size. Every size in rem is a multiple of it, so the headings keep their ratios to the text. */
html {
  font-family: var(--font-sans);
  font-size: 18px;
  line-height: 1.65;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  color: var(--color-text);
  background: var(--color-background);
}

/* Headings in the display serif, set close and balanced over their lines, as Open Data sets them. */
h1,
h2,
h3 {
  font-family: var(--font-serif);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.08;
  text-wrap: balance;
  margin: 0 0 0.5rem;
}

h1 {
  font-size: 2.25rem;
}

h2 {
  font-size: 1.5rem;
}

h3 {
  font-size: 1.125rem;
}

p {
  margin: 0 0 0.75rem;
}

a {
  color: var(--color-accent);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* Monospace runs a little smaller than the text around it, but not under the smallest size. */
code,
.mono {
  font-family: var(--font-mono);
  font-size: max(0.875em, var(--font-size-smallest));
}

/* A short label above a heading: monospace, upper case and spaced out, in the faint ink. */
.eyebrow {
  margin: 0 0 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  font-weight: 600;
  letter-spacing: 0.13em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--color-text-faint);
}

/* A link drawn as a button: a white card with the rule, lifting a little under the pointer. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-button);
  background: var(--color-surface);
  box-shadow: var(--shadow-card);
  font-family: var(--font-mono);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--color-text);
  transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
}

.button:hover {
  text-decoration: none;
  border-color: var(--color-accent);
  color: var(--color-accent-strong);
  transform: translateY(-1px);
}

.button:active {
  transform: translateY(0);
}

/* The one button that leads: filled with the accent. */
.button--primary {
  border-color: var(--color-accent);
  background: var(--color-accent);
  color: var(--color-on-accent);
}

.button--primary:hover {
  border-color: var(--color-accent-strong);
  background: var(--color-accent-strong);
  color: var(--color-on-accent);
}

/* A band of the page: a rule above it and generous room around it. */
.section {
  border-top: 1px solid var(--color-border);
  padding: clamp(3rem, 8vw, 5.75rem) 0;
}

/* ---------- Header and footer ---------- */

/* The header stays at the top of the window, over the page as it scrolls: translucent paper, blurred behind. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  border-bottom: 1px solid color-mix(in srgb, var(--color-border) 84%, transparent);
  background: color-mix(in srgb, var(--color-background) 88%, transparent);
  backdrop-filter: blur(14px) saturate(1.4);
}

/* A hairline of the accent riding the header's bottom edge, fading out to the right. */
.site-header::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px;
  height: 1px;
  background: linear-gradient(
    90deg,
    var(--color-accent) 0,
    color-mix(in srgb, var(--color-accent) 45%, transparent) 22%,
    transparent 55%
  );
}

.header-inner {
  max-width: var(--page-width);
  min-height: var(--header-height);
  margin: 0 auto;
  padding-inline: var(--gutter);
  display: flex;
  flex-wrap: wrap; /* were the links ever wider than the row, they wrap rather than widen the page */
  align-items: center;
  gap: 1.2rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  color: var(--color-text);
  white-space: nowrap;
}

.brand:hover {
  text-decoration: none;
}

.brand em {
  font-style: normal;
  color: var(--color-accent);
}

/* The brand's mark: a crimson square with a pale one offset behind it, which darkens under the pointer. */
.brand-mark {
  flex-shrink: 0;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 2px;
  background: var(--color-accent);
  box-shadow: 0.32rem 0.32rem 0 color-mix(in srgb, var(--color-accent) 22%, transparent);
  transition: box-shadow 220ms ease;
}

.brand:hover .brand-mark {
  box-shadow: 0.32rem 0.32rem 0 color-mix(in srgb, var(--color-accent) 40%, transparent);
}

/* The affiliation pushes the nav to the right edge. */
.affiliation {
  margin-right: auto;
  font-family: var(--font-serif);
  font-size: 1rem;
  color: var(--color-text-faint);
  white-space: nowrap;
}

.affiliation:hover {
  text-decoration: none;
  color: var(--color-accent);
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 0.8rem;
}

.nav-link {
  position: relative;
  padding-block: 0.15rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  letter-spacing: 0.04em;
  line-height: 1.4;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-text-faint);
  transition: color 160ms ease;
}

/* An underline in the accent grows from the left under the pointer, and stays under the current page's link. */
.nav-link::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 200ms ease;
}

.nav-link:hover {
  text-decoration: none;
  color: var(--color-accent-strong);
}

.nav-link.is-active {
  color: var(--color-accent);
}

.nav-link:hover::after,
.nav-link.is-active::after {
  transform: scaleX(1);
}

/* Parts the links to the Explore page's sections from the links off the site. */
.nav-divider {
  flex-shrink: 0;
  width: 1px;
  height: 1.05rem;
  background: var(--color-border);
}

.site-footer {
  margin-top: 4rem;
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
}

/* The brand and its line, then two lists of links. */
.footer-inner {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: clamp(2.25rem, 5vw, 3rem) var(--gutter);
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(9rem, 0.6fr));
  align-items: start;
  gap: 2rem clamp(1.5rem, 4vw, 3.5rem);
}

.footer-brand p {
  max-width: 24rem;
  margin: 0.55rem 0 0;
  font-size: 0.875rem;
  color: var(--color-text-faint);
}

.footer-nav h2 {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  font-weight: 700;
  letter-spacing: 0.13em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.footer-links {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  margin-top: 0.9rem;
}

.footer-links .footer-link {
  width: fit-content;
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  transition: color 160ms ease;
}

.footer-links .footer-link:hover {
  text-decoration: none;
  color: var(--color-accent-strong);
}

/* Below this width the header's links take a second row of their own, under the brand and the affiliation: the one row
   needs about 1,120 px besides the gutters. */
@media (max-width: 78rem) {
  :root {
    --header-height: 7.5rem;
  }

  .header-inner {
    min-height: 0;
    padding-top: 0.85rem;
  }

  .site-nav {
    width: 100%;
    flex-wrap: wrap;
    row-gap: 0.55rem;
    margin-top: 0.85rem;
    padding-block: 0.7rem;
    border-top: 1px solid var(--color-border);
  }
}

/*
 * On a narrow screen the header is one row: the brand and the four links to the page's sections, which scroll sideways
 * under a fade at the right edge while more lie beyond it. The links off the site are left out, since the hero and the
 * footer carry them. The footer's link lists sit side by side under the brand.
 */
@media (max-width: 46rem) {
  :root {
    --header-height: 3.25rem;
  }

  .header-inner {
    flex-wrap: nowrap;
    gap: 0.9rem;
    min-height: var(--header-height);
    padding-top: 0;
  }

  .affiliation,
  .nav-divider,
  .nav-link.is-external {
    display: none;
  }

  .site-nav {
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: nowrap;
    width: auto;
    margin-top: 0;
    padding-block: 0.4rem;
    border-top: none;
    overflow-x: auto;
    scrollbar-width: none;
  }

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

  .footer-brand {
    grid-column: 1 / -1;
  }
}

/* On the narrowest screens the header's brand is the name alone, its "Agentic Dataset" kept in the footer's, so that
   the first links show beside it and the fade at the row's edge reads as more to scroll to. */
@media (max-width: 30rem) {
  .site-header .brand em {
    display: none;
  }
}

/* Every anchored section lands below the sticky header, with a little room above it. */
section[id] {
  scroll-margin-top: calc(var(--header-height) + 1rem);
}

@media (prefers-reduced-motion: reduce) {
  .brand-mark,
  .nav-link,
  .nav-link::after,
  .footer-link {
    transition: none;
  }
}

/* ---------- Hero ---------- */

/* The page's opening: the title, lede and buttons on the left, the stats strip on the right. */
.hero {
  position: relative;
  isolation: isolate;
  padding: clamp(1rem, 4vw, 3rem) 0 clamp(1rem, 3vw, 2rem);
}

/* A soft crimson wash behind the stats strip, so the opening reads warmer than the page. It fades out before the
   hero's sides, so it shows no edge where the page is narrower than the screen. */
.hero::before {
  content: "";
  position: absolute;
  inset: -6rem 0 0;
  z-index: -1;
  background: radial-gradient(30% 75% at 75% 10%, color-mix(in srgb, var(--color-accent) 10%, transparent), transparent 70%);
  pointer-events: none;
}

/* The copy takes seven parts to the stats strip's four, wide enough at 1280 px for the title's first phrase on one line. */
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(21rem, 4fr);
  align-items: center;
  gap: clamp(2rem, 5vw, 3.5rem);
}

/* The eyebrow's crimson square, as the brand's mark. */
.eyebrow-mark {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.55rem;
  border-radius: 2px;
  background: var(--color-accent);
}

.hero h1 {
  margin-top: 0;
  font-size: clamp(2rem, 1.25rem + 2.7vw, 3.1rem);
  letter-spacing: -0.035em;
}

/* The title's accent phrase never breaks inside: where the name does not fit one line, the phrase takes the second. */
.hero h1 em {
  font-style: normal;
  white-space: nowrap;
  color: var(--color-accent);
}

.hero-lede {
  max-width: 40rem;
  margin: 1.25rem 0 0;
  font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  color: var(--color-text-muted);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-top: 1.75rem;
}

/* The stats strip: a white card of six numbers parted by hairlines, with no frame of their own inside the card's, and
   the line of dates under them. */
.stats-card {
  padding: clamp(1rem, 2vw, 1.25rem);
  border: 1px solid var(--color-border);
  border-radius: 1rem;
  background: var(--color-surface);
  box-shadow: 0 2px 3px rgb(28 25 23 / 0.04), 0 24px 60px -36px color-mix(in srgb, var(--color-accent) 36%, transparent);
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  overflow: hidden;
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--color-border);
}

.stats-grid li {
  min-width: 0;
  padding: 0.75rem 0.6rem;
  background: var(--color-surface);
}

.stats-grid strong,
.stats-grid span {
  display: block;
}

.stats-grid strong {
  font-family: var(--font-serif);
  font-size: 1.75rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
  line-height: 1.1;
  color: var(--color-accent);
}

.stats-grid span {
  margin-top: 0.2rem;
  font-size: var(--font-size-smallest);
  color: var(--color-text-faint);
}

.stats-dates {
  margin: 0.9rem 0 0;
  font-size: var(--font-size-smallest);
  color: var(--color-text-muted);
}

/* The stats strip goes under the copy where the two no longer fit side by side, and keeps two numbers a row on a phone. */
@media (max-width: 62rem) {
  .hero-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .stats-card {
    max-width: 40rem;
  }
}

@media (max-width: 30rem) {
  .stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* The four buttons two by two, each as wide as its column, rather than in ragged rows. */
  .hero-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---------- Overview donuts ---------- */

/* The Overview: the two donuts side by side, then the three trends. */
.overview {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

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

/* A donut card: the title and caption across the top, the donut with its legend beside it, the Definition below. */
.donut-card .figure {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "title title"
    "caption caption"
    "body legend"
    "definition definition";
  align-items: center;
  gap: 0.375rem 1.5rem;
}

.donut-card .figure-title {
  grid-area: title;
}

.donut-card .figure-caption {
  grid-area: caption;
}

.donut-card .figure-body {
  grid-area: body;
  min-height: 0;
  margin: 0.75rem 0;
}

/* The legend beside the donut lists its slices one under another, in rows close enough that nine end level with the
   donut, and in two columns where it goes under the donut. */
.donut-card .figure-legend {
  grid-area: legend;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0 1rem;
}

.donut-card .legend-button {
  min-height: 0;
  padding-block: 0.0625rem;
  line-height: 1.35;
  text-align: left;
}

.donut-card .figure-definition {
  grid-area: definition;
}

/* A fixed size, so the centre's text keeps its size on every screen. */
.donut {
  display: block;
  width: 13rem;
  height: 13rem;
}

/* The even-odd rule makes the inner circle of a whole ring, a donut of one slice, a hole. */
.donut-slice {
  fill-rule: evenodd;
  stroke: var(--color-surface);
  stroke-width: 1.5;
}

.donut-total,
.donut-unit {
  text-anchor: middle;
  dominant-baseline: middle;
}

.donut-total {
  font-family: var(--font-serif);
  font-size: 28px; /* in the donut's own units, 200 across: about 32 px on the page */
  font-weight: 700;
  fill: var(--color-text);
}

.donut-unit {
  font-size: 13px; /* about 15 px on the page */
  fill: var(--color-text-faint);
}

/* Where two cards share a row too narrow for a donut and its legend side by side, the legend goes under the donut;
   one card a row (below 50rem) keeps it so too, for one layout on every narrow screen. */
@media (max-width: 68rem) {
  .donut-card .figure {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "title"
      "caption"
      "body"
      "legend"
      "definition";
  }

  .donut-card .figure-body {
    justify-self: center;
  }

  .donut-card .figure-legend {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-bottom: 0.75rem;
  }
}

/* ---------- Cite and Team ---------- */

/* The Cite section: its heading on the left, the sentence and the BibTeX on the right, wide enough for the BibTeX's
   longest line at 1280 px; one column on a narrow screen. */
.cite {
  display: grid;
  grid-template-columns: minmax(0, 0.6fr) minmax(20rem, 1.4fr);
  gap: clamp(1.5rem, 6vw, 5rem);
}

/* A part of the page opens as Open Data's sections do: a large serif heading, with room above. */
.section-heading {
  margin-top: clamp(1.5rem, 4vw, 3rem);
}

.section-heading h2,
.cite h2,
.team h2 {
  margin-top: 0;
  font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.5rem);
  letter-spacing: -0.02em;
}

/* The Team's heading sits under its eyebrow. */
.team h2 {
  margin-top: 0.5rem;
}

.cite-copy-column p {
  color: var(--color-text-muted);
}

.cite-block {
  overflow: hidden;
  margin: 1.25rem 0 0;
  border: 1px solid var(--color-border);
  border-radius: 0.7rem;
  background: var(--color-surface);
}

/* The block's caption bar: what the block holds, and the copy button, which the page shows only where it can copy. */
.cite-block figcaption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 1rem;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface-raised);
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-text-faint);
}

.cite-copy {
  padding: 0.2rem 0.7rem;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text-muted);
  font: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.cite-copy:hover {
  border-color: var(--color-accent);
  color: var(--color-accent-strong);
}

/* A long line scrolls inside the block rather than widening the page. */
.cite-block pre {
  overflow-x: auto;
  margin: 0;
  padding: 1rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  line-height: 1.6;
  color: var(--color-text);
}

/* The Team section: its heading with the lab beside it on the heading's baseline, the authors in a row between two
   rules, then the About. The section lies on a band of the accent's wash, the page's one tinted rest before the
   footer; the band reaches the window's edges while the content keeps the page's width. */
.team {
  --team-band: color-mix(in srgb, var(--color-accent) 6%, var(--color-background));
  background: var(--team-band);
  box-shadow: 0 0 0 100vmax var(--team-band);
  clip-path: inset(0 -100vmax);
}

.team-heading {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: last baseline;
  gap: 1rem 3rem;
}

.team-heading > p {
  margin: 0;
  color: var(--color-text-muted);
}

/* The authors on a grid of five columns, each name over its affiliation, so they share one row and one left edge. */
.team-list {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0 1.2rem;
  margin: 1.5rem 0 0;
  padding: 0.85rem 0;
  list-style: none;
  border-block: 1px solid var(--color-border);
}

.team-list li {
  display: flex;
  flex-direction: column;
}

.team-list a {
  color: var(--color-text);
}

.team-list span {
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  letter-spacing: 0.03em;
  color: var(--color-text-faint);
}

.team-about {
  max-width: 44rem;
  margin-top: 2rem;
}

.team-about p:not(.eyebrow) {
  color: var(--color-text-muted);
}

/* On a narrow screen the heading goes above the copy, and each author takes a line of their own. */
@media (max-width: 58rem) {
  .cite,
  .team-heading {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 64rem) {
  .team-list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    row-gap: 0.85rem;
  }
}

@media (max-width: 46rem) {
  .team-list {
    grid-template-columns: minmax(0, 1fr);
    padding: 0;
  }

  .team-list li {
    padding: 0.7rem 0;
    border-bottom: 1px solid var(--color-border);
  }

  .team-list li:last-child {
    border-bottom: 0;
  }
}

/* ---------- Page layout ---------- */

.page {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: 2rem var(--gutter) 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.page-title .lede {
  font-size: 1.0625rem;
  color: var(--color-text-muted);
  max-width: 44rem;
}

.breadcrumb {
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 1.25rem;
}

/* Two figures side by side, one under the other on a narrower screen (below). No gap between rows: a card spans five
   rows of its grid (see below), and a row gap would open between its parts; a card's own margin parts it from the card
   below. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 1.5rem;
}

/* The weekly trends: three charts side by side on a wide screen, one above the other on a narrow one. */
.trend-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 1.5rem;
}

/*
 * A figure card in a grid lays its parts on its row's tracks, so the charts of a row start at one height whatever the
 * length of their insights, captions and legends: a trend's five (title, caption, legend, chart, Definition), an
 * insight's six (title, insight, legend, chart, caption, Definition).
 */
.card-grid > .card,
.trend-grid > .card {
  display: grid;
  grid-row: span 5;
  grid-template-rows: subgrid;
  grid-template-columns: minmax(0, 1fr); /* a part wider than the card, such as a table, scrolls inside it */
  row-gap: 0;
  min-width: 0;
  margin-bottom: 1.5rem;
}

.card-grid > .card {
  grid-row: span 6;
}

.card-grid > .card > .figure,
.trend-grid > .card > .figure {
  display: contents;
}

/* A card without a legend draws its chart where the legend would be, so it keeps no empty band above the chart. */
.card-grid > .card .figure-legend:empty {
  display: none;
}

.card-grid > .card .figure-legend:empty + .figure-body {
  grid-row: span 2;
}

/* The parts are spaced by their own margins, not the rows' gap, so a legend place that is empty in every card of a
   row takes no room at all. */
.card-grid > .card .figure-title,
.card-grid > .card .figure-insight,
.card-grid > .card .figure-caption,
.card-grid > .card .figure-legend:not(:empty),
.card-grid > .card .figure-body,
.trend-grid > .card .figure-title,
.trend-grid > .card .figure-caption,
.trend-grid > .card .figure-legend:not(:empty),
.trend-grid > .card .figure-body {
  margin-bottom: 0.5rem;
}

/* A figure that needs the room, or would be left alone in its row, takes the whole width of its section. */
.card-grid > .card.is-wide {
  grid-column: 1 / -1;
}

.figure-section {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* The figure sections, one after the other, spaced as the page spaces its parts. */
.figure-sections {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* A topic's number before its heading, in the eyebrow's monospace and the accent: "01 Session structure". */
.topic-number {
  margin-right: 0.6rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  font-weight: 600;
  letter-spacing: 0.13em;
  vertical-align: 0.3em;
  color: var(--color-accent);
}

/* A topic's takeaway under its heading: one sentence in the muted ink at the lede's size, close to the heading it
   belongs to. */
.topic-takeaway {
  margin: -0.75rem 0 0;
  font-size: 1.0625rem;
  line-height: 1.5;
  color: var(--color-text-muted);
}

/* On a phone the takeaway steps down to the body's size, so a twenty-word sentence takes three lines, not four. */
@media (max-width: 40rem) {
  .topic-takeaway {
    font-size: 1rem;
  }
}

/* A figure's card may shrink below its content, so a wide chart scrolls inside the card, not the page. */
.figure-section .card {
  min-width: 0;
}

/* A figure card not yet drawn is about as tall as a drawn one, so the cards below it start out of view. */
.figure-section .card-grid > .card:empty,
.figure-section .card-grid > .card:has(.loading) {
  min-height: var(--loading-card-height);
}

/* ---------- Figures and cards ---------- */

.figure {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.figure-title {
  font-size: 1.25rem;
  margin: 0;
}

/* A figure's point, under its title: one sentence in the body's size and ink, a rule in the accent on its left. It
   keeps to its own lines when a neighbour's insight takes more. */
.figure-insight {
  align-self: start;
  margin: 0;
  padding-left: 0.75rem;
  border-left: 3px solid var(--color-accent);
  font-size: 1rem;
  line-height: 1.45;
  color: var(--color-text);
}

/* The one short line of what a figure draws: under its chart where the card has an insight, else under its title. */
.figure-caption {
  font-size: 0.875rem;
  color: var(--color-text-muted);
  margin: 0;
}

.figure-legend:empty {
  min-height: 0;
}

.figure-body {
  min-height: 12rem;
}

/* The Definition control of every figure, at the foot of a card or above the Requests view's list: a muted line that
   opens on the definition and the rows. */
.figure-definition {
  font-size: var(--font-size-smallest);
  color: var(--color-text-muted);
}

.figure-definition summary {
  width: fit-content;
  cursor: pointer;
  color: var(--color-text-muted);
}

.figure-definition summary:hover {
  color: var(--color-text);
}

.figure-definition p {
  margin: 0.375rem 0 0;
}

.figure-rows {
  font-variant-numeric: tabular-nums;
}

/* A chart a click acts on, such as a trend bar that selects its week. */
.figure-body.is-clickable {
  cursor: pointer;
}

/*
 * Plot paints its tooltip and text halos in --plot-background; give it the card's surface in both modes.
 * Plot sets its text at 10 px; the ticks, axis titles and tooltips take the smallest size instead.
 */
.figure-body svg {
  max-width: 100%;
  height: auto;
  font-size: var(--font-size-smallest);
  --plot-background: var(--color-surface);
}

.legend {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 0.25rem 1rem;
  margin: 0;
  font-size: var(--font-size-smallest);
  color: var(--chart-label);
}

.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}

.legend-dash {
  width: 1.125rem;
  height: 0.5rem;
}

/* A Session legend's swatch drawn as its mark is: a line, a dot, or a dotted rule in the swatch's colour. */
.legend-dash.is-line {
  height: 2px;
}

.legend-dash.is-dot {
  width: 0.5rem;
  border-radius: 50%;
}

.legend-dash.is-dotted {
  height: 0;
  border-top: 2px dotted currentColor;
}

/* A legend entry that hides or shows its series: a plain button in the legend's ink, struck through while hidden. */
.legend-button {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: var(--font-size-smallest);
  font-weight: 400;
  color: var(--chart-label);
  background: transparent;
  border: none;
  padding: 0.125rem 0;
}

.legend-button:hover {
  color: var(--color-text);
  background: transparent;
}

.legend-button[aria-pressed="false"] {
  text-decoration: line-through;
}

.legend-button[aria-pressed="false"] .legend-swatch {
  opacity: 0.3;
}

.legend-swatch {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 2px;
}

/* A line chart's series is a short line in its legend, as it is drawn. */
.legend-swatch.is-line {
  width: 1rem;
  height: 2px;
  border-radius: 0;
}

/* A line of counts above or below a table, such as the sessions it lists. */
.table-count {
  font-size: var(--font-size-smallest);
  color: var(--color-text-muted);
  margin: 0.25rem 0 0.75rem;
  font-variant-numeric: tabular-nums;
}

.note {
  font-size: 0.875rem;
  color: var(--color-text-muted);
  padding: 0.75rem 1rem;
  border-radius: var(--radius-small);
  background: var(--color-surface-raised);
}

.note.is-error {
  color: var(--color-accent-strong);
  background: var(--color-accent-wash);
}

.loading {
  color: var(--color-text-faint);
  font-size: 0.875rem;
}

.loading::after {
  content: "…";
}

/* ---------- Controls ---------- */

.controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

.control-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
}

.control-label {
  font-size: var(--font-size-smallest);
  font-weight: 500;
  color: var(--color-text-muted);
}

.pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.25rem 0.75rem;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  font-size: var(--font-size-smallest);
  font-weight: 500;
  color: var(--color-text-muted);
  cursor: pointer;
  user-select: none;
}

.pill:hover {
  color: var(--color-text);
  background: var(--color-surface-raised);
}

/* A chosen pill is filled in a neutral ink, as the Context view's chosen part is; its checkbox is not drawn but keeps
   the keyboard, and the pill shows its focus. */
.pill.is-selected {
  color: var(--color-text);
  border-color: var(--color-text-faint);
  background: var(--color-surface-raised);
}

/* A half-chosen pill, such as a month with some of its weeks picked, keeps the chosen ink on a dashed border, since its
   checkbox, which says so, is not drawn. */
.pill:has(input:indeterminate) {
  color: var(--color-text);
  border-style: dashed;
  border-color: var(--color-text-faint);
}

.pill input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}

.pill:has(input:focus-visible) {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* A choice made at once, such as "All months" or "Every harness": text in the accent, with no box. */
.text-button {
  border: none;
  padding: 0.25rem 0.25rem;
  background: transparent;
  color: var(--color-accent);
  font-size: var(--font-size-smallest);
}

.text-button:hover {
  color: var(--color-accent-strong);
  background: transparent;
  text-decoration: underline;
}

/* What a pill's choice is besides its name, such as the benchmark harness's "benchmark replay". */
.pill-mark {
  font-size: var(--font-size-smallest);
  font-weight: 400;
  color: var(--color-text-faint);
}

/* The selection section: the week picker, the harness picker and the notes under them, one above the other. */
.selection {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.selection .note {
  margin: 0;
}

/* A page whose figures are frozen hides the selection section, which its display rule would otherwise keep shown. */
.selection[hidden] {
  display: none;
}

/* The sessions table's row of controls: each a field under its name in small monospace capitals, wrapping on a phone. */
.table-controls {
  align-items: flex-end;
  margin-bottom: 0.75rem;
}

/* The fields share the row equally, the search twice as wide; on a phone two fields a row and the search alone. */
.control-field {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 0;
}

.control-field.is-search {
  flex-grow: 2;
}

@media (max-width: 40rem) {
  .control-field {
    flex-basis: calc(50% - 0.5rem);
  }

  /* A drop-down's text a step smaller and closer to its edge, so "All harnesses" fits half the row. */
  .control-field select {
    padding-inline: 0.375rem;
    font-size: var(--font-size-smallest);
  }

  .control-field.is-search {
    flex-basis: 100%;
  }
}

.control-field select {
  width: 100%;
}

/* What a month holds, under the session list's controls. */
.table-month-note {
  margin: 0 0 0.75rem;
  font-size: var(--font-size-smallest);
  color: var(--color-text-faint);
}

.control-field-name {
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-faint);
}

/* A drop-down and a text box draw at different heights by default; one height lines the row up. */
.control-field select,
.control-field input {
  box-sizing: border-box;
  height: 2.375rem;
}

/* A text box starts narrow, so the five fields share one row at desktop width, and fills its field once the row is
   shared out. */
.control-field input {
  width: 8rem;
  min-width: 100%;
}

/* The note naming the months and harnesses a link named that the data do not hold. */
.table-note .note {
  margin: 0 0 0.75rem;
}

/* The last month or harness ticked cannot be unticked. */
.pill:has(input:disabled) {
  cursor: default;
}

select,
input[type="text"],
input[type="search"],
input[type="number"] {
  font: inherit;
  font-size: 0.875rem;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-small);
  padding: 0.375rem 0.625rem;
}

button {
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-small);
  padding: 0.375rem 0.75rem;
  cursor: pointer;
}

button:hover {
  color: var(--color-text);
  background: var(--color-surface-raised);
}

button:disabled {
  opacity: 0.5;
  cursor: default;
}

button:disabled:hover {
  color: var(--color-text-muted);
  background: var(--color-surface);
}

/* ---------- Tables ---------- */

.table-wrap {
  overflow-x: auto;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.data-table th,
.data-table td {
  padding: 0.5rem;
  text-align: left;
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}

/* Headers in sentence case, as every table on the site writes them: shorter than upper case, and calmer. A header of
   two words may wrap, so a column is as wide as its values. */
.data-table th {
  white-space: normal;
  vertical-align: bottom;
  font-size: var(--font-size-smallest);
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
  user-select: none;
}

.data-table th.is-sorted {
  color: var(--color-accent);
}

.data-table td.is-number,
.data-table th.is-number {
  text-align: right;
}

/* Numbers line up by their digits; names and dates keep the font's own spacing. */
.data-table td.is-number {
  font-variant-numeric: tabular-nums;
}

/* On a phone the session list's cells are a step smaller and closer, so its first four columns fit the card. */
@media (max-width: 40rem) {
  #sessions-table .data-table {
    font-size: var(--font-size-smallest);
  }

  #sessions-table .data-table th,
  #sessions-table .data-table td {
    padding-inline: 0.25rem;
  }
}

/* A table, or the header's row of links, with more beyond its right edge fades that edge, to say it scrolls sideways
   (`markMoreBeyondEdge` in js/shared/table.js). */
.has-more-beyond-edge {
  mask-image: linear-gradient(90deg, #000 calc(100% - 2.5rem), transparent);
}

/* The session list's page scrolls, not its card: on a screen wide enough for its nine columns (about 950 px of card)
   the wrap clips nothing and the header row sticks under the site header as the page scrolls. Collapsed borders
   scroll with the rows, so the header's rule is a shadow that stays with it. */
@media (min-width: 69rem) {
  #sessions-table .table-wrap {
    overflow-x: visible;
  }

  #sessions-table .data-table th {
    position: sticky;
    top: var(--header-height);
    z-index: 1;
    background: var(--color-surface);
    border-bottom: none;
    box-shadow: inset 0 -1px 0 var(--color-border);
  }
}

/* The benchmark replay's chip after its harness, as Open Data marks a released dataset. */
.table-chip {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: var(--font-size-smallest);
  font-weight: 600;
  letter-spacing: 0.06em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--color-text-muted);
  background: var(--color-surface-raised);
  cursor: help;
}

/* The pager under a table: right-aligned, a row's gap below the table. */
.pager {
  justify-content: flex-end;
  margin-top: 0.75rem;
}

.pager .control-label {
  font-size: 0.875rem;
}

.data-table tbody tr.is-clickable {
  cursor: pointer;
}

.data-table tbody tr:hover {
  background: var(--color-surface-raised);
}

.data-table tbody tr.is-highlighted {
  background: var(--color-highlight);
}

/* The mutation table is not sorted: its headers take no click. The causes of a mutation are set under a muted "of
   which" line, indented. Its cells are narrower and its names wrap, so its four columns fit a phone's width. */
.mutation-table th {
  cursor: default;
}

.mutation-table th,
.mutation-table td {
  padding-inline: 0.1875rem;
}

.mutation-table td:first-child {
  white-space: normal;
}

.mutation-table .is-of-which td {
  padding-block: 0.25rem 0;
  border-bottom: none;
  font-size: var(--font-size-smallest);
  font-style: italic;
  color: var(--color-text-faint);
}

/* On a phone the table's text is a step smaller, so its four columns, percentages and all, fit the card. */
@media (max-width: 40rem) {
  .mutation-table {
    font-size: var(--font-size-smallest);
  }
}

.mutation-table .is-cause td:first-child {
  padding-left: 1.125rem;
}

/* ---------- Session views ---------- */

/* The full id under a session's title, secondary to it: long and unbroken, so it may wrap anywhere. */
.session-id {
  margin: 0;
  font-size: 0.875rem;
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

.view-tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--color-border);
}

.view-tab {
  padding: 0.5rem 0.875rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text-muted);
}

.view-tab:hover {
  text-decoration: none;
  color: var(--color-text);
}

.view-tab.is-active {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

/* A model or tool-call pill: its name after a small dot in its colour, as a legend marks a series. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.0625rem 0.5rem;
  border-radius: 999px;
  font-size: var(--font-size-smallest);
  font-weight: 500;
  color: var(--color-text);
  background: var(--color-surface-raised);
}

.chip::before {
  content: "";
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--chip-color, var(--series-other));
}

/* ---------- Requests view ---------- */

.request-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.request-toolbar:empty {
  display: none;
}

.legend-title {
  font-weight: 600;
}

/* A view's legend of several titled lines, one above the other. */
.legend-lines {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

/* A choice of two or three views of one chart: neutral buttons joined into one control, the chosen one filled. */
.segmented {
  display: inline-flex;
  align-self: flex-start;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-small);
  overflow: hidden;
}

.segmented button {
  border: 0;
  border-radius: 0;
  background: transparent;
}

.segmented button + button {
  border-left: 1px solid var(--color-border);
}

.segmented button[aria-pressed="true"] {
  color: var(--color-text);
  background: var(--color-surface-raised);
}

/*
 * The list of request rows; with overlap brackets, its left padding is the gutter they are drawn in.
 * --bar-track is the width of a full bar: fixed, not a share of the row, so a token count is drawn the same
 * length in every row however deep its subagent group is indented.
 */
.request-list {
  --bar-track: 14rem; /* most bars are short beside the largest, so a narrower track leaves less blank before the chips */
  position: relative;
  margin-top: 0.75rem;
}

.request-list.has-brackets {
  padding-left: 2.75rem;
}

.bracket-gutter {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2.75rem;
}

/* A bracket joins the middles of its first and last row: a vertical stroke with a short tick at each end. */
.bracket {
  position: absolute;
  width: 0.375rem;
  border: 2px solid var(--series-other);
  border-right: 0;
  border-radius: 2px 0 0 2px;
}

/*
 * One request: label, elapsed time, token bar and tool-call chips on one line; a button, so a key opens it too.
 * The chips take what the indent leaves; the label, elapsed time and bar columns are fixed.
 */
.request-row {
  display: grid;
  grid-template-columns: 6rem 8rem var(--bar-track) minmax(0, 1fr);
  align-items: center;
  gap: 0.25rem 0.75rem;
  width: 100%;
  padding: 0.25rem 0.5rem;
  border: 0;
  border-radius: var(--radius-small);
  background: transparent;
  color: var(--color-text);
  font-size: var(--font-size-smallest);
  font-weight: 400;
  text-align: left;
  transition: background-color 0.4s;
}

.request-row:hover {
  color: var(--color-text);
  background: var(--color-surface-raised);
}

.request-row[aria-expanded="true"] {
  background: var(--color-surface-raised);
}

.request-row.is-highlighted {
  background: var(--color-highlight);
}

.request-label {
  font-weight: 500;
  white-space: nowrap;
}

.request-elapsed {
  color: var(--color-text-muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* The bar's parts are sized in percent of the largest request, with a 2px gap between them. */
.request-bar {
  display: flex;
  gap: 2px;
  height: 0.75rem;
}

.bar-part {
  height: 100%;
  min-width: 1px;
  border-radius: 2px;
}

.request-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

/* A subagent's group: a header that toggles it, and its rows indented below. */
.group-header {
  display: block;
  width: 100%;
  padding: 0.25rem 0.5rem;
  border: 0;
  background: transparent;
  color: var(--color-accent);
  font-size: var(--font-size-smallest);
  text-align: left;
}

.group-header::before {
  content: "▸ ";
}

.group-header[aria-expanded="true"]::before {
  content: "▾ ";
}

.group-header:hover {
  color: var(--color-accent-strong);
  background: var(--color-accent-wash);
}

.group-rows {
  margin-left: 1rem;
  padding-left: 0.5rem;
  border-left: 1px solid var(--color-border);
}

/* A request's details, opened under its row. */
.details {
  margin: 0.25rem 0 0.75rem 0.5rem;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-small);
  background: var(--color-surface-raised);
  font-size: var(--font-size-smallest);
}

.details dl {
  display: grid;
  /* A column is 14rem, or the whole panel when the panel is narrower, as it is deep in a group on a phone. */
  grid-template-columns: repeat(auto-fill, minmax(min(14rem, 100%), 1fr));
  gap: 0.25rem 1.5rem;
  margin: 0 0 0.75rem;
}

.details dt {
  font-size: var(--font-size-smallest);
  color: var(--color-text-faint);
}

.details dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.details .data-table {
  font-size: var(--font-size-smallest);
}

/* A call's row and the line of its arguments skeleton under it read as one entry. */
.details .call-row td {
  border-bottom: none;
}

/* A command can be long, so the skeleton wraps inside the table instead of widening it. */
.details .call-skeleton {
  padding-top: 0;
  white-space: normal;
  overflow-wrap: anywhere;
  color: var(--color-text-muted);
}

/*
 * Below the width the one-line row needs, a row's label and elapsed time share a line and the bar and chips go
 * below. The bar track narrows to fit a depth-4 row on a 360px screen; max-width only guards a deeper one.
 */
@media (max-width: 58rem) {
  .request-list {
    --bar-track: 12rem;
  }

  .request-row {
    grid-template-columns: auto 1fr;
  }

  .request-bar {
    grid-column: 1 / -1;
    width: var(--bar-track);
    max-width: 100%;
  }

  .request-chips {
    grid-column: 1 / -1;
  }
}

/* ---------- Context and Timeline views ---------- */

/* A chart wider than the screen scrolls sideways at its own size, rather than shrinking its text away. */
.chart-scroll {
  overflow-x: auto;
}

/* The Timeline's chart with its tooltip, which is placed against this frame and may reach past the scroll box. */
.chart-frame {
  position: relative;
}

.chart-frame.is-pointing {
  cursor: pointer;
}

.chart-tip {
  position: absolute;
  z-index: 1;
  max-width: 18rem;
  padding: 0.375rem 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-small);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--font-size-smallest);
  line-height: 1.4;
  white-space: pre-line;
  pointer-events: none;
  box-shadow: var(--shadow-subtle);
}

.figure-body .chart-scroll svg,
.figure-body .chart-scroll figure {
  max-width: none;
}

/* ---------- Narrower screens ---------- */

@media (max-width: 50rem) {
  .trend-grid,
  .card-grid,
  .donut-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---------- Small screens ---------- */

@media (max-width: 40rem) {
  h1 {
    font-size: 1.75rem;
  }

  .page {
    padding-top: 1.25rem;
  }

  .card {
    padding: 1rem;
  }

  /* Nested groups indent less, so a depth-4 subagent still has room for a full bar. */
  .group-rows {
    margin-left: 0.25rem;
    padding-left: 0.25rem;
  }

  .details {
    margin-left: 0;
    padding: 0.75rem;
  }
}

/* ---------- Session facts ---------- */

/* The Session page's title beside its facts card on a wide screen; the card under the title on a narrow one. */
.session-heading {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 42rem);
  gap: 1.5rem;
  align-items: start;
}

/* The facts card: labelled fields in three columns, one on a phone. */
.facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.5rem 1.25rem;
  margin: 0;
}

.fact dt {
  font-size: var(--font-size-smallest);
  font-weight: 500;
  color: var(--color-text-faint);
}

.fact dd {
  margin: 0;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.fact-line {
  display: block;
}

/* A model's name never breaks, at its hyphens or anywhere else. */
.fact-name {
  white-space: nowrap;
}

.fact-detail {
  font-size: var(--font-size-smallest);
  font-weight: 400;
  color: var(--color-text-muted);
}

.fact dd > .fact-detail {
  display: block;
}

@media (max-width: 62rem) {
  .session-heading {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 40rem) {
  .facts {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---------- Range slider ---------- */

/* Under the Context and Timeline charts: a thin bar for the session's time, the chosen range marked between two
   handles. Its left margin and width are set to the chart's plot area when the chart is drawn. */
.range-slider {
  max-width: 100%;
  margin-top: 0.5rem;
}

/* The track is the paper; the chosen range on it is the accent's wash, edged in the accent, as a brush strip. */
.range-track {
  position: relative;
  height: 0.75rem;
  margin: 0.75rem 0;
  border-radius: var(--radius-small);
  background: var(--color-background);
  box-shadow: inset 0 0 0 1px var(--color-border);
}

.range-selection {
  position: absolute;
  top: 0;
  bottom: 0;
  border: 2px solid var(--color-accent);
  border-radius: var(--radius-small);
  background: var(--color-accent-wash);
}

/* A handle sits outside the range at its end, so the two never cover one another however narrow the range; a pointer
   drags it without scrolling the page or selecting text. */
.range-handle {
  position: absolute;
  top: 50%;
  width: 0.75rem;
  height: 1.375rem;
  transform: translate(-100%, -50%);
  border: 1px solid var(--color-text-faint);
  border-radius: var(--radius-small);
  background: var(--color-surface);
  box-shadow: var(--shadow-subtle);
  cursor: ew-resize;
  touch-action: none;
  user-select: none;
}

.range-handle.is-end {
  transform: translate(0, -50%);
}

.range-handle:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.range-readout {
  margin: 0;
  font-size: var(--font-size-smallest);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 40rem) {
  .range-readout-name {
    display: none;
  }
}
