/* =============================================================================
   site.css — layout and components.

   Consumes the tokens in theme.css and declares none of its own. If you find a
   literal colour or size in here, it is a bug: move it to theme.css.
   ============================================================================= */

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

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

strong,
b {
  font-weight: var(--w-strong);
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: var(--w-normal);
  line-height: var(--lh-tight);
  margin: 0;
}

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

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--c-focus);
  outline-offset: 2px;
  border-radius: var(--radius);
}

.wrap {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 var(--page-pad);
}

.measure {
  max-width: var(--measure);
}

/* -- banners --------------------------------------------------------------- */

.banner {
  background: var(--c-mock-bg);
  color: var(--c-mock-ink);
  border-bottom: 1px solid var(--c-mock-rule);
  font-size: var(--t-small);
  padding: var(--s-3) 0;
}

.banner strong {
  font-weight: var(--w-bold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: var(--t-tiny);
}

.banner[hidden] {
  display: none;
}

.banner--prelim {
  background: var(--c-prelim-bg);
  color: var(--c-prelim-ink);
  border-bottom-color: var(--c-prelim-rule);
}

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

.masthead {
  border-bottom: var(--border);
  background: var(--c-surface);
}

.masthead__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  align-items: baseline;
  justify-content: space-between;
  padding-top: var(--s-4);
  padding-bottom: var(--s-4);
}

.masthead__title {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  color: var(--c-ink);
  text-decoration: none;
}

.masthead__title span {
  color: var(--c-ink-faint);
}

.nav {
  display: flex;
  gap: var(--s-5);
  font-size: var(--t-small);
}

.nav a {
  color: var(--c-ink-soft);
  text-decoration: none;
}

.nav a:hover,
.nav a[aria-current="page"] {
  color: var(--c-accent);
}

/* -- hero ------------------------------------------------------------------ */

.hero {
  padding: var(--s-8) 0 var(--s-7);
}

.hero h1 {
  font-size: var(--t-hero);
  margin-bottom: var(--s-5);
}

.hero p {
  font-size: 1.06rem;
  color: var(--c-ink-soft);
  margin: 0 0 var(--s-4);
}

/* A third against two thirds, under a full-width headline. Used by the home
   page (intro | video) and the messages page (intro | the prompt). Collapses
   to one column before the narrow side gets too cramped to read. */
.split {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: var(--s-6);
  align-items: start;
  margin-top: var(--s-5);
}

.lede {
  font-size: var(--t-hero-intro);
  line-height: var(--lh-hero-intro);
  margin: var(--s-4) 0 var(--s-3);
}

/* The intro is shorter than the video beside it, and hanging it from the top
   edge left it looking dropped. Centring against the video is the same move as
   nudging it down, except it stays balanced if either side changes height —
   which the video already did once. Currently about 19px of offset. */
.hero-split {
  align-items: center;
}

.hero-split__intro p {
  margin: 0 0 var(--s-3);
  font-size: var(--t-hero-intro);
  line-height: var(--lh-hero-intro);
}

.hero-split__intro p:last-child {
  margin-bottom: 0;
}

/* Below ~1000px the third-width column gets narrow enough that its text runs
   taller than whatever sits beside it, so stack instead of leaving a ragged
   row. */
@media (max-width: 1000px) {
  .split {
    grid-template-columns: 1fr;
    gap: var(--s-5);
  }
}

.eyebrow {
  font-size: var(--t-tiny);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--c-ink-faint);
  margin: 0 0 var(--s-4);
  font-weight: var(--w-medium);
}

/* -- generic section ------------------------------------------------------- */

section {
  padding-bottom: var(--s-7);
}

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  border-top: var(--border);
  padding-top: var(--s-4);
  margin-bottom: var(--s-5);
}

.section-head h2 {
  font-size: var(--t-h2);
}

.section-head p {
  margin: 0;
  color: var(--c-ink-faint);
  font-size: var(--t-small);
}

/* -- buttons / links ------------------------------------------------------- */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-5);
}

/* Sitting under the tiles rather than under a column of text, so it centres
   on the page instead of hanging off the left edge. */
.actions--centred {
  justify-content: center;
  margin-top: var(--s-6);
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-5);
  border: var(--border);
  border-radius: var(--radius);
  background: var(--c-surface);
  color: var(--c-ink);
  text-decoration: none;
  font-size: var(--t-small);
  font-weight: var(--w-medium);
}

.btn:hover {
  border-color: var(--c-rule-strong);
}

.btn--primary {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-surface);
}

.btn--primary:hover {
  border-color: var(--c-accent);
}

.btn[aria-disabled="true"] {
  color: var(--c-ink-faint);
  background: var(--c-surface-sunk);
  pointer-events: none;
}

/* -- highlight tiles ------------------------------------------------------- */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--s-4);
}

.tile {
  background: var(--c-surface);
  border: var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.tile h3 {
  font-size: var(--t-h3);
}

.tile p {
  margin: 0;
  font-size: var(--t-small);
  color: var(--c-ink-soft);
}

.tile__figure {
  margin: var(--s-2) 0;
}

.tile__figure svg {
  display: block;
  width: 100%;
  height: auto;
}

/* the three big numbers inside the "key rates" tile */
/* Two by two. With four rates, an auto-fit row lands on three-plus-one, which
   reads as a mistake rather than as a grid. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-4) var(--s-4);
}

.stat {
  border-top: 2px solid var(--c-rule-strong);
  padding-top: var(--s-2);
}

.stat__link {
  text-decoration: none;
  color: inherit;
  display: block;
}

.stat__link:hover .stat__value {
  color: var(--c-accent);
}

.stat__value {
  font-family: var(--font-display);
  font-size: 1.7rem;
  line-height: 1.05;
  display: block;
}

.stat__label {
  font-size: var(--t-tiny);
  color: var(--c-ink-faint);
  display: block;
  margin-top: var(--s-1);
}

/* -- the swap diagram (index) ---------------------------------------------- */

.chip {
  fill: var(--c-chip-bg);
  stroke: var(--c-chip-rule);
  stroke-width: 1;
}

.chip--foreign {
  fill: var(--c-foreign-soft);
  stroke: var(--c-foreign);
  stroke-dasharray: 3 2;
}

.chip-num {
  fill: var(--c-chip-ink);
  font-family: var(--font-body);
  font-size: 13px;
  text-anchor: middle;
}

.chip-num--foreign {
  fill: var(--c-foreign);
  font-weight: var(--w-medium);
}

.chip-caption {
  fill: var(--c-ink-faint);
  font-family: var(--font-body);
  font-size: 10px;
}

.chip-caption--foreign {
  fill: var(--c-foreign);
}

/* -- video placeholder ----------------------------------------------------- */

.video-placeholder {
  aspect-ratio: 16 / 9;
  background: var(--c-surface-sunk);
  border: 1px dashed var(--c-rule-strong);
  border-radius: var(--radius-lg);
  display: grid;
  place-items: center;
  color: var(--c-ink-faint);
  font-size: var(--t-small);
}

.video-placeholder p {
  margin: 0;
}

/* A plain <video> element, no platform embed. Fills the wide side of the split
   at the same 16:9 the placeholder holds, so swapping one for the other does
   not move anything else on the page. */
.video-player {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--c-ink);
  border: var(--border);
  border-radius: var(--radius-lg);
}

/* -- directory ------------------------------------------------------------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--s-4);
  list-style: none;
  margin: 0;
  padding: 0;
}

.card {
  background: var(--c-surface);
  border: var(--border);
  border-radius: var(--radius-lg);
  display: flex;
}

.card a {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-5);
  text-decoration: none;
  color: inherit;
  width: 100%;
}

.card:hover {
  border-color: var(--c-rule-strong);
  box-shadow: var(--shadow);
}

.card--pending {
  background: var(--c-surface-sunk);
}

.card--pending:hover {
  box-shadow: none;
}

.card h3 {
  font-size: var(--t-h3);
}

/* Two lines' worth of space whether the title needs them or not, with a rule
   under it — so the rule sits at the same height on every card in a row and
   the numbers below it start on the same line. */
.cards .card h3 {
  min-height: calc(2.4em + var(--s-2) + 1px);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--c-rule);
}

.card p {
  margin: 0;
  font-size: var(--t-small);
  color: var(--c-ink-soft);
}

.card__value {
  font-family: var(--font-display);
  font-size: 2.1rem;
  line-height: 1;
  color: var(--c-ink);
}

.pill {
  align-self: flex-start;
  font-size: var(--t-tiny);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 2px var(--s-2);
  border-radius: 999px;
  background: var(--c-pending-bg);
  color: var(--c-pending-ink);
  border: 1px solid var(--c-pending-rule);
}

/* -- chart ----------------------------------------------------------------- */

.chart {
  background: var(--c-surface);
  border: var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-5);
  overflow-x: auto;
}

.chart svg {
  display: block;
  width: 100%;
  min-width: 620px;
  height: auto;
}

.chart .grid-line {
  stroke: var(--chart-grid);
  stroke-width: 1;
}

.chart .axis-line {
  stroke: var(--chart-axis);
  stroke-width: 1;
}

.chart .axis-label {
  fill: var(--c-ink-faint);
  font-family: var(--font-body);
  font-size: var(--chart-axis-size);
}

.chart .bar-value {
  fill: var(--c-ink);
  font-family: var(--font-body);
  font-size: var(--chart-value-size);
  font-weight: var(--w-medium);
  text-anchor: middle;
}

.chart .bar-label {
  fill: var(--c-ink-soft);
  font-family: var(--font-body);
  font-size: var(--chart-label-size);
  text-anchor: middle;
}

.chart .bar-label--total {
  fill: var(--c-ink);
  font-weight: var(--w-medium);
}

.chart .bar {
  rx: var(--chart-bar-radius);
  fill: var(--fam-unknown);
}

.chart .bar:hover {
  opacity: var(--chart-bar-hover);
}

.chart .bar--total {
  fill: var(--c-total);
}
.chart .bar--claude {
  fill: var(--fam-claude);
}
.chart .bar--gpt {
  fill: var(--fam-gpt);
}
.chart .bar--gemini {
  fill: var(--fam-gemini);
}
.chart .bar--kimi {
  fill: var(--fam-kimi);
}
.chart .bar--deepseek {
  fill: var(--fam-deepseek);
}

.chart .bar-track {
  fill: var(--c-surface-sunk);
}

.chart .divider {
  stroke: var(--c-rule-strong);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

.chart-note {
  font-size: var(--t-small);
  color: var(--c-ink-faint);
  margin: var(--s-3) 0 0;
}

/* -- result page ----------------------------------------------------------- */

.result-head {
  padding: var(--s-7) 0 var(--s-5);
}

.result-head h1 {
  font-size: var(--t-h1);
  margin-bottom: var(--s-4);
}

.result-head p {
  color: var(--c-ink-soft);
  margin: 0;
}

.headline {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  margin: var(--s-5) 0;
}

.headline__value {
  font-family: var(--font-display);
  font-size: var(--t-hero);
  line-height: 1;
}

.headline__detail {
  color: var(--c-ink-faint);
  font-size: var(--t-small);
}

.provenance {
  background: var(--c-surface-sunk);
  border: var(--border);
  border-radius: var(--radius);
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-small);
  color: var(--c-ink-soft);
  margin-top: var(--s-5);
}

.provenance code {
  font-family: var(--font-mono);
  font-size: 0.92em;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-small);
}

caption {
  text-align: left;
  color: var(--c-ink-faint);
  font-size: var(--t-small);
  padding-bottom: var(--s-2);
}

th,
td {
  text-align: right;
  padding: var(--s-2) var(--s-3);
  border-bottom: var(--border);
}

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

thead th {
  color: var(--c-ink-faint);
  font-weight: var(--w-medium);
  font-size: var(--t-tiny);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

tbody tr:last-child td {
  border-bottom: none;
}

.swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: var(--s-2);
  background: var(--fam-unknown);
}

.swatch--claude {
  background: var(--fam-claude);
}
.swatch--gpt {
  background: var(--fam-gpt);
}
.swatch--gemini {
  background: var(--fam-gemini);
}
.swatch--kimi {
  background: var(--fam-kimi);
}
.swatch--deepseek {
  background: var(--fam-deepseek);
}

/* -- qualitative ----------------------------------------------------------- */

.prose p {
  margin: 0 0 var(--s-4);
}

.prose h3,
.prose h4 {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  margin: var(--s-5) 0 var(--s-3);
}

.prose code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--c-surface-sunk);
  border-radius: 3px;
  padding: 0 3px;
}

/* Sits under every LLM-written summary. Quiet, but not hidden: it is the same
   caveat the paper makes, and a reader can land on a topic page directly. */
.disclaimer {
  margin: var(--s-5) 0 0;
  padding-top: var(--s-3);
  border-top: 1px solid var(--c-rule);
  font-size: var(--t-small);
  color: var(--c-ink-faint);
}

.notice-inline {
  background: var(--c-pending-bg);
  border-left: 3px solid var(--c-pending-rule);
  color: var(--c-pending-ink);
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-small);
  margin: var(--s-4) 0 0;
  max-width: var(--measure);
}

/* The headline share, and what the reader is being told that share agreed on. */
.card__stat {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  margin: var(--s-2) 0 0;
}

/* Number first, then the phrase that completes it. Both inside the heading. */
.card__headline {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

/* Two lines' worth whether the phrase needs them or not, so the rule under the
   heading lands at the same height on every card in a row. */
.card__phrase {
  display: block;
  min-height: 2.4em;
}

.card__definition {
  margin: 0;
  font-size: var(--t-small);
  color: var(--c-ink-soft);
}

.card__contrast {
  margin: 0;
  font-size: var(--t-small);
  color: var(--c-ink-faint);
}

/* Pinned to the foot of the card, so the call to action lines up across a row
   whatever length the definitions above it run to. */
.card__cta {
  margin-top: auto;
  padding-top: var(--s-3);
  font-size: var(--t-small);
  color: var(--c-accent);
}

.pill--quiet {
  background: transparent;
  color: var(--c-ink-faint);
  border-color: var(--c-rule);
}

/* horizontal bar rows carry their label on the left, not underneath */
.chart .bar-label--row {
  font-family: var(--font-mono);
  font-size: var(--t-code-chip);
}

.chart .bar-value--row {
  text-anchor: start;
}

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

.table-scroll table {
  min-width: 520px;
}

.table-scroll td:first-child {
  font-family: var(--font-mono);
  font-size: var(--t-code-chip);
}

/* -- "read against": other readings of the same result ---------------------- */

.context-list {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--s-4);
}

.context-item {
  border-top: 2px solid var(--c-rule-strong);
  padding-top: var(--s-3);
}

.context-item dt {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.context-item__value {
  font-family: var(--font-display);
  font-size: 1.35rem;
  line-height: 1.1;
}

.context-item__label {
  font-size: var(--t-small);
  color: var(--c-ink);
}

.context-item dd {
  margin: var(--s-2) 0 0;
  font-size: var(--t-small);
  color: var(--c-ink-faint);
}

/* -- quotes ---------------------------------------------------------------- */

.quotes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--s-4);
}

.quote {
  background: var(--c-surface);
  border: var(--border);
  border-left: 3px solid var(--c-quote-rule);
  border-radius: var(--radius-lg);
  padding: var(--s-4) var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.quote--claude {
  border-left-color: var(--fam-claude);
}
.quote--gpt {
  border-left-color: var(--fam-gpt);
}
.quote--gemini {
  border-left-color: var(--fam-gemini);
}
.quote--kimi {
  border-left-color: var(--fam-kimi);
}
.quote--deepseek {
  border-left-color: var(--fam-deepseek);
}

.quote__text {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.02rem;
  line-height: 1.5;
}

.quote__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  font-size: var(--t-tiny);
  color: var(--c-ink-faint);
  border-top: var(--border);
  padding-top: var(--s-2);
}

.quote__model {
  color: var(--c-ink);
  font-weight: var(--w-medium);
}

.quote__meta code {
  font-family: var(--font-mono);
}

.quote__flag {
  color: var(--c-accent);
}

.quote__codes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1);
}

.code-chip {
  font-family: var(--font-mono);
  font-size: var(--t-code-chip);
  background: var(--c-code-chip-bg);
  color: var(--c-code-chip-ink);
  border-radius: 3px;
  padding: 1px var(--s-2);
}

/* -- codebook -------------------------------------------------------------- */

.codebook-box {
  border: var(--border);
  border-radius: var(--radius-lg);
  background: var(--c-surface);
  padding: var(--s-4) var(--s-5);
  margin-top: var(--s-5);
}

.codebook-box summary {
  cursor: pointer;
  font-weight: var(--w-medium);
  font-size: var(--t-small);
}

.codebook {
  margin: var(--s-4) 0 0;
  font-size: var(--t-small);
}

.codebook dt {
  font-family: var(--font-mono);
  font-size: var(--t-code-chip);
  color: var(--c-ink);
  margin-top: var(--s-3);
}

.codebook dd {
  margin: var(--s-1) 0 0;
  color: var(--c-ink-soft);
}

.codebook__rules-head {
  font-family: var(--font-body);
  font-size: var(--t-small);
  font-weight: var(--w-medium);
  margin: var(--s-5) 0 var(--s-2);
}

/* -- pending state --------------------------------------------------------- */

.pending {
  background: var(--c-pending-bg);
  border: 1px solid var(--c-pending-rule);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
  text-align: center;
  color: var(--c-pending-ink);
}

.pending h3 {
  font-size: var(--t-h3);
  margin-bottom: var(--s-2);
}

.pending p {
  margin: 0 auto;
  max-width: 46ch;
  font-size: var(--t-small);
}

/* -- messages -------------------------------------------------------------- */

/* -- message filters ------------------------------------------------------- */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-bottom: var(--s-5);
}

.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-4);
  border: var(--border);
  border-radius: 999px;
  background: var(--c-surface);
  color: var(--c-ink-soft);
  font-family: var(--font-body);
  font-size: var(--t-small);
  line-height: 1.2;
  cursor: pointer;
}

.filter-pill:hover {
  border-color: var(--c-rule-strong);
  color: var(--c-ink);
}

.filter-pill[aria-pressed="true"] {
  background: var(--c-ink);
  border-color: var(--c-ink);
  color: var(--c-bg);
}

.filter-pill__count {
  color: var(--c-ink-faint);
  font-variant-numeric: tabular-nums;
}

.filter-pill[aria-pressed="true"] .filter-pill__count {
  color: var(--c-rule-strong);
}

.bubble[hidden] {
  display: none;
}

.bubbles {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  list-style: none;
  padding: 0;
  margin: 0;
}

.bubble {
  max-width: 46rem;
  border: var(--border);
  border-left: 3px solid var(--fam-unknown);
  border-radius: var(--radius-lg);
  background: var(--c-surface);
  padding: var(--s-4) var(--s-5);
}

.bubble--claude {
  border-left-color: var(--fam-claude);
}
.bubble--gpt {
  border-left-color: var(--fam-gpt);
}
.bubble--gemini {
  border-left-color: var(--fam-gemini);
}
.bubble--kimi {
  border-left-color: var(--fam-kimi);
}
.bubble--deepseek {
  border-left-color: var(--fam-deepseek);
}

/* Alternate the alignment so the page reads as a conversation, not a list.
   Driven by a class rather than :nth-child, because filtering hides bubbles
   without removing them and nth-child would keep counting the hidden ones. */
.bubble.is-right {
  margin-left: auto;
}

/* Replies are rendered from Markdown into real blocks, so the spacing lives on
   the children rather than on a pre-wrap block. */
.bubble__text {
  font-size: var(--t-message);
}

.bubble__text > :first-child {
  margin-top: 0;
}

.bubble__text > :last-child {
  margin-bottom: 0;
}

.bubble__text p {
  margin: 0 0 var(--s-3);
}

.msg-heading {
  margin-top: var(--s-4);
}

.msg-list {
  margin: 0 0 var(--s-3);
  padding-left: var(--s-5);
}

.msg-list li {
  margin-bottom: var(--s-2);
}

.bubble__text code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  background: var(--c-surface-sunk);
  border-radius: 3px;
  padding: 0 3px;
}

/* Folded, never truncated: the whole reply is in the DOM either way. */
.bubble__text.is-clamped {
  max-height: var(--msg-clamp);
  overflow: hidden;
  position: relative;
}

.bubble__text.is-clamped::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 4em;
  background: linear-gradient(to bottom, transparent, var(--c-surface));
  pointer-events: none;
}

.bubble__more {
  margin: var(--s-3) 0 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--c-accent);
  font-family: var(--font-body);
  font-size: var(--t-small);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.bubble__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  font-size: var(--t-tiny);
  color: var(--c-ink-faint);
  border-top: var(--border);
  padding-top: var(--s-2);
}

.bubble__model {
  color: var(--c-ink);
  font-weight: var(--w-medium);
}

.bubble__meta code {
  font-family: var(--font-mono);
}

.prompt-quote {
  margin: 0;
  padding: var(--s-4) var(--s-5);
  border-left: 3px solid var(--c-rule-strong);
  background: var(--c-surface);
  color: var(--c-ink-soft);
  font-size: var(--t-small);
  white-space: pre-wrap;
}

/* -- prev / next ----------------------------------------------------------- */

.pager {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  border-top: var(--border);
  padding-top: var(--s-4);
  font-size: var(--t-small);
}

/* -- footer ---------------------------------------------------------------- */

.foot {
  border-top: var(--border);
  margin-top: var(--s-7);
  padding: var(--s-5) 0 var(--s-7);
  font-size: var(--t-small);
  color: var(--c-ink-faint);
}

.foot p {
  margin: 0 0 var(--s-2);
}

/* -- utilities ------------------------------------------------------------- */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.loading {
  color: var(--c-ink-faint);
  font-size: var(--t-small);
  padding: var(--s-6) 0;
}

.error {
  background: var(--c-accent-soft);
  border: 1px solid var(--c-accent);
  color: var(--c-accent);
  border-radius: var(--radius);
  padding: var(--s-4) var(--s-5);
  font-size: var(--t-small);
}

.error code {
  font-family: var(--font-mono);
}

@media (max-width: 560px) {
  .stat-row {
    grid-template-columns: 1fr;
  }
  .bubble.is-right {
    margin-left: 0;
  }
}
