/*
  Copyright (c) 2026 Jungseob Lee. All Rights Reserved.
  Shared stylesheet for the paper project pages.
*/

:root {
  color-scheme: light;

  --ink: #1f2328;
  --ink-soft: #4b5462;
  --ink-mute: #626c7a;
  --paper: #ffffff;
  --band: color-mix(in srgb, var(--accent-a) 5%, #fff);
  --rule: #dfe3e8;
  --rule-strong: #1f2328;
  --link: var(--accent-a);
  --link-hover: color-mix(in srgb, var(--accent-a) 75%, #000);
  --pill: var(--accent-a);
  --pill-hover: color-mix(in srgb, var(--accent-a) 80%, #000);
  --award: #c4262e;
  --gain: #1b5e20;
  --loss: #b71c1c;
  --mark: #fff3cd;
  --ours: color-mix(in srgb, var(--accent-a) 9%, #fff);

  /* Each page overrides these two with the colors of its own figures. */
  --accent-a: #1763c6;
  --accent-b: #1763c6;

  --font-display: "Google Sans Flex", "Google Sans", "Noto Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Noto Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "Google Sans Code", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --w-text: 44rem;
  --w-wide: 60rem;
  --gutter: clamp(1.1rem, 4vw, 1.75rem);
  --radius: 12px;
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 1rem;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

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

a:hover {
  color: var(--link-hover);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

:focus-visible {
  outline: 3px solid var(--link);
  outline-offset: 3px;
  border-radius: 4px;
}

sup {
  font-size: 0.68em;
  line-height: 0;
  vertical-align: super;
}

.skip {
  position: absolute;
  left: 0.75rem;
  top: -4rem;
  z-index: 10;
  padding: 0.5rem 0.9rem;
  border-radius: 8px;
  background: var(--pill);
  color: #fff;
  font-family: var(--font-display);
}

.skip:focus {
  top: 0.75rem;
  color: #fff;
}

/* ---------- Top bar ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  max-width: var(--w-wide);
  margin: 0 auto;
  padding: 0.35rem var(--gutter) 0;
  font-family: var(--font-display);
  font-size: 0.95rem;
}

.topbar a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--ink-soft);
}

.topbar a:hover {
  color: var(--ink);
}

.topbar .home {
  color: var(--ink);
  font-weight: 600;
}

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

.hero {
  padding: clamp(1.25rem, 4vw, 2.5rem) var(--gutter) clamp(1.75rem, 4vw, 2.5rem);
  text-align: center;
}

.hero-inner {
  max-width: var(--w-wide);
  margin: 0 auto;
}

.title {
  margin: 0 auto;
  max-width: 21em;
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 1.05rem + 3.3vw, 2.9rem);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: -0.012em;
  text-wrap: balance;
}

.title .name {
  background: linear-gradient(90deg, var(--accent-a), var(--accent-b));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  color: transparent;
}

.title-icon {
  display: inline-block;
  width: auto;
  height: 1.12em;
  margin-right: 0.2em;
  vertical-align: -0.2em;
}

.venue {
  margin: 0.8rem 0 0;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 1rem + 0.6vw, 1.35rem);
  font-weight: 700;
  color: var(--accent-a);
}

.venue .award {
  color: var(--award);
}

.authors {
  margin: 1.3rem auto 0;
  max-width: 50rem;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 0.98rem + 0.5vw, 1.22rem);
  line-height: 1.6;
}

.author {
  display: inline-block;
  margin: 0 0.3em;
  white-space: nowrap;
}

.affils {
  margin: 0.6rem auto 0;
  max-width: 50rem;
  font-family: var(--font-display);
  font-size: 1.02rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.affils span {
  display: inline-block;
  margin: 0 0.45em;
}

.notes {
  margin: 0.35rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-mute);
}

.notes span {
  display: inline-block;
  margin: 0 0.5em;
}

.links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  margin: 1.6rem 0 0;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0 1.2rem;
  border: 0;
  border-radius: 999px;
  background: var(--pill);
  color: #fff;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.btn:hover {
  background: var(--pill-hover);
  color: #fff;
  text-decoration: none;
}

.btn svg {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  fill: currentColor;
}

/* A resource that is announced but not public yet keeps its place in the
   row and reads as inactive. */
.btn.soon,
.btn.soon:hover {
  background: transparent;
  color: var(--pill);
  box-shadow: inset 0 0 0 1.5px currentColor;
  cursor: default;
}

/* ---------- Sections ---------- */

.section {
  padding: clamp(2.5rem, 6vw, 3.75rem) var(--gutter);
}

.band {
  background: var(--band);
}

.wrap {
  max-width: var(--w-wide);
  margin: 0 auto;
}

.section h2 {
  margin: 0 0 1.4rem;
  font-family: var(--font-display);
  font-size: clamp(1.55rem, 1.3rem + 1.1vw, 2rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.008em;
  text-align: center;
  text-wrap: balance;
}

.prose {
  max-width: var(--w-text);
  margin: 0 auto;
}

.prose p {
  margin: 0 0 1rem;
  text-wrap: pretty;
}

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

.prose strong {
  font-weight: 600;
}

.nw {
  white-space: nowrap;
}

.sc {
  font-variant-caps: small-caps;
  letter-spacing: 0.01em;
}

.tldr {
  max-width: 40rem;
  margin: 0 auto 1.75rem;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 1rem + 0.6vw, 1.3rem);
  font-weight: 500;
  line-height: 1.45;
  text-align: center;
  text-wrap: balance;
}

.teaser {
  padding: 0 var(--gutter) clamp(2.5rem, 6vw, 3.75rem);
}

/* ---------- Figures ---------- */

.fig {
  margin: 0 auto;
}

.fig + .prose,
.prose + .fig,
.prose + .table-block,
.table-block + .prose,
.steps + .prose,
.prose + .steps,
.fig + .fig {
  margin-top: 1.75rem;
}

.fig.narrow {
  max-width: 36rem;
}

.fig.mid {
  max-width: 46rem;
}

.plate {
  display: block;
  padding: clamp(0.5rem, 2vw, 1.1rem);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: #fff;
}

a.plate {
  cursor: zoom-in;
}

a.plate:hover {
  border-color: #b9c0ca;
}

.plate img {
  width: 100%;
}

figcaption,
.caption {
  max-width: var(--w-text);
  margin: 0.85rem auto 0;
  font-size: 0.94rem;
  line-height: 1.6;
  color: var(--ink-soft);
  text-align: center;
  text-wrap: pretty;
}

figcaption.long,
.caption.long {
  text-align: left;
}

.caption + .caption {
  margin-top: 0.45rem;
}

.fig-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem;
  align-items: start;
}

.fig-pair .fig {
  margin: 0;
}

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  gap: clamp(1.5rem, 4vw, 2.75rem);
  align-items: center;
}

.split .prose,
.split .fig,
.split .table-block {
  max-width: none;
  margin: 0;
}

/* A wide table inside the pair scrolls in its own frame instead of widening the column. */
.split > * {
  min-width: 0;
}

/* Between two runs of text the pair keeps the gap that a single figure has there. */
.prose + .split,
.split + .prose {
  margin-top: 1.75rem;
}

/* ---------- Method steps ---------- */

.steps.cols-3 {
  --cols: 3;
}

.steps {
  display: grid;
  grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr));
  gap: 1.1rem;
  margin: 0 auto;
  padding: 0;
  list-style: none;
}

.step {
  padding: 1.15rem 1.3rem 1.3rem;
  border: 1px solid var(--rule);
  border-top: 4px solid var(--step, var(--accent-a));
  border-radius: var(--radius);
  background: #fff;
  font-size: 1rem;
  line-height: 1.62;
}

.step-label {
  display: block;
  font-family: var(--font-display);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--step-ink, var(--ink-soft));
}

.step h3 {
  margin: 0.1rem 0 0.5rem;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.3;
  text-wrap: balance;
}

.step p {
  margin: 0;
}

.step p + p {
  margin-top: 0.6rem;
}

.step p.formula,
.formula {
  margin: 0.9rem 0;
  overflow-x: auto;
  overflow-y: hidden;
  text-align: center;
}

.formula .katex-display {
  margin: 0;
  padding: 0.15rem 0;
}

/* Typeset math sits next to a sans-serif body with a tall x-height,
   and a short inline formula should never break across lines. */
.katex {
  font-size: 1.1em;
  white-space: nowrap;
}

.tbl .katex {
  font-size: 1em;
}

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

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

.table-block {
  margin: 0 auto;
}

.table-block.mid {
  max-width: 48rem;
}

.table-block.narrow {
  max-width: 27rem;
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background:
    linear-gradient(to right, #fff 30%, rgba(255, 255, 255, 0)) left center / 2.5rem 100% no-repeat local,
    linear-gradient(to left, #fff 30%, rgba(255, 255, 255, 0)) right center / 2.5rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(31, 35, 40, 0.16), rgba(31, 35, 40, 0)) left center / 0.8rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(31, 35, 40, 0.16), rgba(31, 35, 40, 0)) right center / 0.8rem 100% no-repeat scroll,
    #fff;
  -webkit-overflow-scrolling: touch;
}

.tbl {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.95rem;
  line-height: 1.35;
  font-variant-numeric: tabular-nums lining-nums;
}

.tbl th,
.tbl td {
  padding: 0.5rem 0.8rem;
  text-align: right;
  white-space: nowrap;
}

.tbl th {
  font-family: var(--font-display);
  font-weight: 600;
}

.tbl thead th {
  vertical-align: bottom;
}

.tbl thead tr:last-child th,
.tbl thead th[rowspan] {
  border-bottom: 1.5px solid var(--rule-strong);
}

.tbl .l {
  text-align: left;
}

.tbl .c {
  text-align: center;
}

.tbl .grp {
  text-align: center;
}

/* Only the label wrapper gets the rule, so a typeset formula inside the label keeps its own spans. */
.tbl .grp > span {
  display: block;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--ink-mute);
}

.tbl tbody th {
  font-family: var(--font-body);
  font-weight: 400;
}

.tbl tbody tr.sep > * {
  border-top: 1px solid var(--rule);
}

.tbl tbody tr.group > th {
  padding-top: 0.85rem;
  padding-bottom: 0.3rem;
  border-top: 1px solid var(--rule);
  font-family: var(--font-display);
  font-size: 0.93rem;
  font-weight: 700;
  text-align: left;
}

.tbl tbody tr.group > th span {
  display: inline-block;
  position: sticky;
  left: 0.8rem;
}

.tbl tbody tr.group + tr > * {
  padding-top: 0.35rem;
}

.tbl tbody:last-of-type tr:last-child > * {
  padding-bottom: 0.7rem;
}

.tbl tbody:first-of-type tr.group:first-child > th {
  border-top: 0;
}

.tbl tbody tr.ours > * {
  background: var(--ours);
  font-weight: 700;
}

.tbl tbody tr.ours > .muted {
  font-weight: 400;
}

.tbl .hit {
  background: var(--mark);
}

.tbl b,
.tbl strong {
  font-weight: 700;
}

.tbl u {
  text-underline-offset: 0.2em;
}

.tbl .delta {
  display: inline-block;
  min-width: 3.4em;
  margin-left: 0.3em;
  font-size: 0.86em;
  font-weight: 400;
  text-align: left;
}

.tbl .pos,
.pos {
  color: var(--gain);
}

.tbl .neg,
.neg {
  color: var(--loss);
}

.tbl .muted {
  color: var(--ink-mute);
}

/* Wide comparison tables: tighter cells, deviation under the value,
   and a tint on the difference column that grows with the gain. */
.tbl.dense {
  min-width: 58rem;
  font-size: 0.84rem;
}

.tbl.dense th,
.tbl.dense td {
  padding: 0.38rem 0.3rem;
}

.tbl.dense thead th {
  font-size: 0.82rem;
  line-height: 1.2;
  white-space: normal;
}

.tbl.dense thead tr:last-child th {
  text-align: center;
  font-weight: 500;
}

.tbl.dense .l {
  padding-left: 0.8rem;
  padding-right: 0.6rem;
}

.tbl.dense td {
  text-align: center;
}

.tbl.dense td small {
  display: block;
  font-size: 0.8em;
  line-height: 1.25;
  color: var(--ink-mute);
}

.tbl.dense .g {
  border-left: 1px solid var(--rule);
}

.tbl.dense .d {
  font-weight: 700;
}

.tbl .h0 { background: rgba(214, 39, 40, 0.05); }
.tbl .h1 { background: rgba(214, 39, 40, 0.11); }
.tbl .h2 { background: rgba(214, 39, 40, 0.19); }
.tbl .h3 { background: rgba(214, 39, 40, 0.29); }
.tbl .h4 { background: rgba(214, 39, 40, 0.41); }
.tbl .h5 { background: rgba(214, 39, 40, 0.54); }
.tbl .hn { background: rgba(31, 119, 180, 0.22); }

.scroll-hint {
  display: none;
  margin: 0.5rem 0 0;
  font-size: 0.84rem;
  color: var(--ink-mute);
  text-align: center;
}

/* ---------- BibTeX ---------- */

.bib {
  position: relative;
  max-width: var(--w-wide);
  margin: 0 auto;
}

.bib pre {
  margin: 0;
  padding: 1.2rem 6.2rem 1.2rem 1.3rem;
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: #fff;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  line-height: 1.6;
  tab-size: 2;
}

.bib code {
  font-family: inherit;
}

.copy {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  min-height: 2.25rem;
  padding: 0 0.9rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: #fff;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 0.88rem;
  font-weight: 500;
  cursor: pointer;
}

.copy:hover {
  border-color: var(--ink-mute);
}

.copy.done {
  border-color: var(--gain);
  color: var(--gain);
}

/* ---------- Decoding replay ---------- */

/* The replay sits on the same white ground as the teaser above it, so the gap
   between them is one section padding, not two. */
.teaser + #race {
  padding-top: 0;
}

/* One plate, framed like a figure: a head strip, then one row per decoder.
   Rows run edge to edge, so the plate clips them to its rounded corners. */
.race {
  margin: 0 auto;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: #fff;
}

.prose + .race {
  margin-top: 1.75rem;
}

/* The prompt takes the room the controls leave. Where that would be less
   than a readable line, the controls drop to a row of their own. */
.race-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  padding: 0.8rem 1.3rem;
  border-bottom: 1px solid var(--rule);
}

.race-bar,
.race-tabs,
.race-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem;
}

.race-bar {
  justify-content: flex-end;
  gap: 0.45rem 1rem;
  margin-left: auto;
}

/* The controls follow the buttons under the title: pills in the accent
   color. The one that runs the replay is filled, the others are outlined. */
.race-bar button {
  min-height: 2.4rem;
  padding: 0 1.05rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--pill) 40%, #fff);
  color: var(--pill);
  font-family: var(--font-display);
  font-size: 0.92rem;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.15s ease, box-shadow 0.15s ease;
}

.race-bar button:hover {
  box-shadow: inset 0 0 0 1.5px var(--pill);
}

.race-bar button:focus-visible {
  border-radius: 999px;
}

.race-bar button[aria-pressed="true"] {
  background: color-mix(in srgb, var(--pill) 11%, #fff);
  box-shadow: inset 0 0 0 1.5px var(--pill);
}

/* The label of this button changes with the run. A fixed minimum width keeps
   the button next to it in place. */
.race-bar .race-replay {
  min-width: 6.2rem;
  background: var(--pill);
  box-shadow: none;
  color: #fff;
}

.race-bar .race-replay:hover {
  background: var(--pill-hover);
  box-shadow: none;
}

.race-prompt {
  display: flex;
  flex: 1 1 16rem;
  gap: 0.75rem;
  min-width: 0;
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.race-prompt b {
  flex: none;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
}

/* A long prompt is context, so it keeps to two lines and the lanes stay in
   view. A brief one is the whole question and is shown in full, and so is a
   long one on a page that replays a single example. */
.race-prompt > span {
  display: -webkit-box;
  min-width: 0;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow-wrap: anywhere;
}

.race-head.brief .race-prompt > span,
.race-head.full .race-prompt > span {
  display: block;
  overflow: visible;
}

/* Beside several lines of prompt the controls stay at the first line, and
   the text runs on under its label to use the whole width. */
.race-head.full {
  align-items: flex-start;
}

.race-head.full .race-prompt {
  display: block;
}

.race-head.full .race-prompt b {
  margin-right: 0.6rem;
}

.race-head.full .race-prompt > span {
  display: inline;
}

/* A prompt that comes with a picture shows it small beside the text, and a
   click opens it at full size. */
.race-image {
  display: block;
  flex: none;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: 6px;
  cursor: zoom-in;
}

.race-image img {
  display: block;
  width: auto;
  height: 5.25rem;
}

/* Beside a picture the question needs a longer line before the controls may
   share its row. */
.race-head.pictured .race-prompt {
  flex-basis: 22rem;
}

.race-lanes {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* A lane is kept shallow so that all of them and the prompt fit one screen:
   the label takes two rows, and the bar shares its row with its readings. */
.lane {
  position: relative;
  display: grid;
  grid-template-columns: 17rem minmax(0, 1fr);
  gap: 0.2rem 1.5rem;
  align-items: center;
  padding: 0.6rem 1.3rem 0.65rem;
}

/* The name, then the speedup with the two measured values beside it. */
.lane-id {
  display: grid;
  grid-template-columns: 8.6rem minmax(0, 1fr);
  align-items: center;
  column-gap: 0.5rem;
}

.lane + .lane {
  border-top: 1px solid var(--rule);
}

/* The proposed method is the one tinted row, with the title gradient running
   down its left edge. */
.lane.ours {
  background: var(--ours);
}

.lane.ours::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 4px;
  background: linear-gradient(180deg, var(--accent-a), var(--accent-b));
}

.lane-name {
  display: block;
  grid-column: 1 / -1;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.3;
}

.lane-name .muted {
  font-weight: 400;
  color: var(--ink-mute);
  white-space: nowrap;
}

/* The speedup may run past its column where no values sit beside it. */
.lane-x {
  display: block;
  grid-row: 2;
  grid-column: 1 / -1;
  white-space: nowrap;
  font-family: var(--font-display);
  font-size: 1.85rem;
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums lining-nums;
}

/* Where the result is the number of tokens, the running count is a second
   figure under the speedup, a step smaller, and the values go below both. */
.lane-id .lane-count {
  display: block;
  grid-row: 3;
  grid-column: 1 / -1;
  margin-top: 0.1rem;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums lining-nums;
}

.lane-x small,
.lane-id .lane-count small {
  margin-left: 0.45rem;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--ink-mute);
}

.lane.ours .lane-x b,
.lane.ours .lane-id .lane-count b {
  background: linear-gradient(90deg, var(--accent-a), var(--accent-b));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.lane-x b,
.lane-id .lane-count b {
  font-weight: inherit;
  color: var(--ink-soft);
}

/* Measured values are set in the code face, like readings on an instrument. */
.lane-meta {
  display: block;
  grid-row: 2;
  grid-column: 2;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums lining-nums;
}

.lane-meta span {
  display: block;
  white-space: nowrap;
}

.lane-id .lane-count ~ .lane-meta {
  grid-row: 4;
  grid-column: 1 / -1;
  margin-top: 0.25rem;
}

/* The readings keep one width, so every bar has the same length and the
   bars can be read against each other. */
.lane-run {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 13rem;
  align-items: center;
  gap: 0.4rem 1rem;
  min-width: 0;
}

.lane-track {
  position: relative;
  height: 0.625rem;
}

/* The baseline bars carry the comparison, so their grays are plain colors
   that every browser draws. */
.lane-rail {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 999px;
  background: #ededee;
}

/* All lanes share one token scale. A lane that writes less shows a rail of
   its own length, cut from the same scale. */
.lane-track.short .lane-rail {
  clip-path: inset(0 calc((1 - var(--n)) * 100%) 0 0 round 999px);
}

.lane.ours .lane-rail {
  background: color-mix(in srgb, var(--accent-a) 15%, #fff);
}

/* Hairline gaps at each quarter of the token budget give the bars a common
   scale to read against. */
.lane-rail::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(var(--gap, #fff), var(--gap, #fff)) 25% 0 / 1.5px 100% no-repeat,
    linear-gradient(var(--gap, #fff), var(--gap, #fff)) 50% 0 / 1.5px 100% no-repeat,
    linear-gradient(var(--gap, #fff), var(--gap, #fff)) 75% 0 / 1.5px 100% no-repeat;
}

.lane.ours .lane-rail::after {
  --gap: var(--ours);
}

.lane-fill {
  width: calc(var(--f, 0) * 100%);
  height: 100%;
  background: #939598;
}

.lane.ours .lane-fill {
  background: linear-gradient(90deg, var(--accent-a), var(--accent-b));
}

/* What a baseline writes after the proposed method has finished is hatched,
   so the finished picture still shows who was where at that moment. */
.lane-late {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--k, 0) * 100%);
  width: max(0%, calc((var(--f, 0) - var(--k, 0)) * 100%));
  background: repeating-linear-gradient(135deg, #bcbdbf 0, #bcbdbf 2.5px, #e0e0e1 2.5px, #e0e0e1 5px);
  opacity: 0;
}

.race.passed .lane-late {
  opacity: 1;
}

/* Where a baseline stood at the moment the proposed method finished. */
.lane-tick {
  position: absolute;
  top: -0.3rem;
  bottom: -0.3rem;
  left: calc(var(--k, 0) * 100%);
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--accent-a);
  opacity: 0;
}

.lane-tick::before {
  content: "";
  position: absolute;
  top: -3px;
  left: -2px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-a);
}

.race.passed .lane-tick {
  opacity: 1;
}

.lane-read {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums lining-nums;
}

.lane-time {
  margin-left: auto;
  font-weight: 500;
  color: var(--ink);
}

.lane.done.ours .lane-time {
  color: var(--accent-a);
}

/* A finished lane gets a check before its time. */
.lane.done .lane-time::before {
  content: "";
  display: inline-block;
  width: 0.36em;
  height: 0.68em;
  margin-right: 0.55em;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: translateY(-0.08em) rotate(45deg);
}

/* The output scrolls up from the bottom edge like a terminal, three lines
   deep, in a shallow inset of its own. The inset's margin is a transparent
   border, so the text is clipped inside it and never shows in the margin. */
.lane-text {
  --inset: color-mix(in srgb, var(--ink) 3.5%, #fff);
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  grid-column: 1 / -1;
  height: calc(4.5em + 0.7rem);
  margin: 0;
  overflow: hidden;
  border: solid transparent;
  border-width: 0.35rem 0.75rem;
  border-radius: 8px;
  background: var(--inset);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--ink-soft);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.lane.ours .lane-text {
  --inset: color-mix(in srgb, var(--ours) 30%, #fff);
}

.lane-text > span {
  display: block;
}

/* Older lines fade toward the top of the inset. */
.lane-text::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  z-index: 1;
  height: 0.7em;
  background: linear-gradient(to bottom, var(--inset), transparent);
  pointer-events: none;
}

.lane-text mark {
  border-radius: 2px;
  background: color-mix(in srgb, var(--ink) 12%, #fff);
  color: var(--ink);
}

.lane.ours .lane-text mark {
  background: color-mix(in srgb, var(--accent-b) 36%, #fff);
}

/* Where a second model writes a few segments of the output, those segments
   take the page's first accent: in the text, and as marks on the rail at
   their place in the output. The bar takes the second accent, the color of
   the model that writes the rest, and so does the marker of where a
   baseline stood. */
.race.sourced .lane.ours .lane-fill {
  background: var(--accent-b);
}

.race.sourced .lane.ours .lane-rail {
  background: color-mix(in srgb, var(--accent-b) 16%, #fff);
}

.race.sourced .lane-tick,
.race.sourced .lane-tick::before {
  background: var(--accent-b);
}

.lane-mark {
  position: absolute;
  top: -0.25rem;
  bottom: -0.25rem;
  left: calc(var(--at, 0) * 100%);
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--accent-a);
  opacity: 0;
}

.lane-mark.on {
  opacity: 1;
}

.lane-text .guest {
  border-radius: 2px;
  background: color-mix(in srgb, var(--accent-a) 16%, #fff);
  color: var(--accent-a);
  font-weight: 500;
}

/* The segment that has just landed is the one solid piece of the lane. */
.lane-text mark.guest,
.lane.ours .lane-text mark.guest {
  background: var(--accent-a);
  color: #fff;
}

.race.sourced .lane.ours .lane-meta span + span {
  font-weight: 500;
  color: var(--accent-a);
}

/* A lane with nothing to state beside its figure leaves that place empty. */
.lane-meta span:empty {
  display: none;
}

/* The clock of such a replay is only the pace of the picture. A lane reads
   its token count alone, and the check of a finished lane goes before it. */
.race.sourced .lane-time {
  display: none;
}

.race.sourced .lane-read {
  justify-content: flex-end;
}

.race.sourced .lane-read .lane-count {
  font-weight: 500;
  color: var(--ink);
}

.race.sourced .lane.done .lane-read .lane-count::before {
  content: "";
  display: inline-block;
  width: 0.36em;
  height: 0.68em;
  margin-right: 0.55em;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: translateY(-0.08em) rotate(45deg);
}

/* A question whose answer is known shows it under the question. Each lane
   then says whether its own answer is that one, in a word with a mark that
   reads without the word. */
.race-ask {
  display: grid;
  flex: 1 1 16rem;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.2rem 0.75rem;
  min-width: 0;
}

/* The two lines share the label column of the block where the browser can
   pass it down, and keep a label column of their own where it cannot. */
.race-ask > p {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-columns: subgrid;
  gap: 0 0.75rem;
}

.race-key {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
}

.race-key b,
.race-key span {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: lining-nums;
}

.lane-x small.hit,
.lane-x small.miss {
  font-weight: 600;
}

.lane-x small.hit,
.lane-result.hit {
  color: #1a7f37;
}

.lane-x small.miss,
.lane-result.miss {
  color: #c4352b;
}

.lane-x small.hit::before,
.lane-result.hit::before {
  content: "";
  display: inline-block;
  width: 0.38em;
  height: 0.74em;
  margin: 0 0.5em 0 0.15em;
  border: solid currentColor;
  border-width: 0 0.17em 0.17em 0;
  transform: translateY(-0.04em) rotate(45deg);
}

.lane-x small.miss::before,
.lane-result.miss::before {
  content: "\00d7";
  margin-right: 0.3em;
  font-size: 1.3em;
  font-weight: 700;
  line-height: 0;
}

/* The name of the proposed method may be set in the title gradient, with
   the picture from the title under it. */
.lane-name .blend {
  background: linear-gradient(90deg, var(--accent-a), var(--accent-b));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.lane-logo {
  display: block;
  grid-row: 2;
  grid-column: 1 / -1;
  align-self: start;
  width: auto;
  height: 2.75rem;
  margin: 0.2rem 0;
}

/* In the line under such a replay, the name of the second model takes its
   color, and the word for that color is set the way the text is marked. */
.caption .guest {
  font-weight: 500;
  color: var(--accent-a);
}

.caption .guest.chip {
  padding: 0.05em 0.35em;
  border-radius: 3px;
  background: color-mix(in srgb, var(--accent-a) 16%, #fff);
}

/* Where every lane writes only a short answer, the answer sits beside its
   bar in an inset one line deep, and a finished lane says next to it whether
   that is the answer in the head. Such a run is a few steps long, so its
   count and its clock are not drawn. */
.race.replied .lane-read {
  display: none;
}

.race.replied .lane-run {
  grid-template-columns: minmax(0, 1fr) 5.6rem 5.2rem;
}

.race.replied .lane-text {
  grid-column: auto;
  height: calc(1.5em + 0.5rem);
  border-width: 0.25rem 0.6rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
}

.race.replied .lane-text::before {
  content: none;
}

.lane-result {
  visibility: hidden;
  font-family: var(--font-display);
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

.lane.done .lane-result {
  visibility: visible;
}

/* A run of a few long steps has one gap at the end of each step in place of
   the quarters. */
.lane-track.stepped .lane-rail::after {
  background: repeating-linear-gradient(90deg,
    transparent 0, transparent calc(100% / var(--steps) - 1.5px),
    var(--gap, #fff) calc(100% / var(--steps) - 1.5px), var(--gap, #fff) calc(100% / var(--steps)));
}

/* What a long prompt leaves out is named in a quieter voice. */
.race-skip {
  font-size: 0.94em;
  font-style: italic;
  color: var(--ink-mute);
}

/* Beside a label that carries the headline count the lane is taller, and
   the inset takes that room: five lines. */
@media (min-width: 48rem) {
  .lane:has(> .lane-id > .lane-count) .lane-text {
    height: calc(7.5em + 0.7rem);
  }

  /* Under a picture the figure and the values go one row down. */
  .lane-id.badged .lane-x,
  .lane-id.badged .lane-meta {
    grid-row: 3;
  }
}

/* Without color-mix() the tints of the replay would have no color at all,
   so its controls, rails, output insets and marks take plain colors there. */
@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .race-bar button {
    box-shadow: inset 0 0 0 1.5px var(--pill);
  }

  .race-bar button[aria-pressed="true"] {
    background: #ededee;
  }

  .lane.ours .lane-rail {
    background: #ededee;
  }

  .lane-text,
  .lane.ours .lane-text {
    --inset: #f6f6f7;
  }

  .lane-text mark,
  .lane.ours .lane-text mark {
    background: #e0e0e1;
  }

  .race.sourced .lane.ours .lane-rail {
    background: #ededee;
  }

  .lane-text .guest {
    background: #e6e6e7;
  }

  .lane-text mark.guest,
  .lane.ours .lane-text mark.guest {
    background: var(--accent-a);
  }

  .caption .guest.chip {
    background: #e6e6e7;
  }
}

/* ---------- More projects and footer ---------- */

.more[hidden] {
  display: none;
}

.more-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.more-list a {
  display: block;
  height: 100%;
  padding: 1rem 1.15rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: #fff;
  color: var(--ink);
}

.more-list a:hover {
  border-color: var(--ink-mute);
  text-decoration: none;
}

.more-title {
  display: block;
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.35;
}

.more-venue {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.88rem;
  color: var(--ink-mute);
}

.footer {
  padding: 2rem var(--gutter) 2.5rem;
  border-top: 1px solid var(--rule);
  font-size: 0.9rem;
  color: var(--ink-mute);
  text-align: center;
}

.footer p {
  margin: 0;
}

.footer a {
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

/* ---------- Figure zoom ---------- */

html:has(dialog[open]) {
  overflow: hidden;
}

.lightbox {
  width: 100vw;
  max-width: 100vw;
  height: 100vh;
  height: 100dvh;
  max-height: 100dvh;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;
}

.lightbox::backdrop {
  background: rgba(18, 20, 23, 0.9);
}

.lightbox-stage {
  display: flex;
  width: 100%;
  height: 100%;
  padding: 3.5rem 1rem 1rem;
  overflow: auto;
  cursor: zoom-out;
}

.lightbox-stage img {
  margin: auto;
  max-width: 100%;
  max-height: 100%;
  border-radius: 8px;
  background: #fff;
  object-fit: contain;
}

.lightbox.actual .lightbox-stage img {
  max-width: none;
  max-height: none;
}

.lightbox-close {
  position: fixed;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  cursor: pointer;
}

.lightbox-close:hover {
  background: rgba(255, 255, 255, 0.26);
}

.lightbox-close:focus-visible {
  outline-color: #fff;
}

.lightbox-close svg {
  width: 1.3rem;
  height: 1.3rem;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  fill: none;
}

/* ---------- Wider screens ---------- */

@media (min-width: 44rem) {
  /* Justified like a paper abstract. Only long words may hyphenate,
     which keeps the word gaps even without chopping short words. */
  .prose.just p {
    text-align: justify;
    -webkit-hyphens: auto;
    hyphens: auto;
    -webkit-hyphenate-limit-before: 4;
    -webkit-hyphenate-limit-after: 4;
    hyphenate-limit-chars: 9 4 4;
  }

  .prose.just a,
  .prose.just .nw {
    -webkit-hyphens: manual;
    hyphens: manual;
  }
}

/* ---------- Medium screens ---------- */

@media (max-width: 61.99rem) {
  .steps.cols-3 {
    --cols: 1;
  }

  /* A table wider than the page keeps its row labels in view while it scrolls. */
  .table-block.wide .scroll-hint {
    display: block;
  }

  .table-block.wide .stick {
    position: sticky;
    left: 0;
    z-index: 1;
    background: #fff;
    box-shadow: 1px 0 0 var(--rule);
  }

  .table-block.wide tbody tr.ours > .stick {
    background: var(--ours);
  }

  /* The bar takes the full width of its column and its readings go under it. */
  .lane-run {
    display: block;
  }

  .lane-read {
    margin-top: 0.4rem;
  }

  .lane-text {
    margin-top: 0.45rem;
  }

  /* A short answer and its mark share the row under the bar. */
  .race.replied .lane-run {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 4.6rem;
    gap: 0 0.9rem;
  }

  .race.replied .lane-track {
    grid-column: 1 / -1;
  }
}

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

@media (max-width: 47.99rem) {
  /* The single column may be narrower than its widest formula or table,
     which then scrolls inside its own frame. */
  .steps {
    grid-template-columns: minmax(0, 1fr);
  }

  .fig-pair,
  .split {
    grid-template-columns: minmax(0, 1fr);
  }

  figcaption,
  .caption {
    text-align: left;
  }

  .tbl .stick {
    position: sticky;
    left: 0;
    z-index: 1;
    background: #fff;
    box-shadow: 1px 0 0 var(--rule);
  }

  .tbl tbody tr.ours > .stick {
    background: var(--ours);
  }

  .tbl:not(.dense) tbody tr.group > th span {
    left: 0.6rem;
  }

  .more-list {
    grid-template-columns: 1fr;
  }

  .scroll-hint {
    display: block;
  }

  .tbl {
    font-size: 0.9rem;
  }

  .tbl th,
  .tbl td {
    padding: 0.45rem 0.6rem;
  }

  .bib pre {
    padding: 3.3rem 1rem 1rem;
    font-size: 0.8rem;
  }

  /* The controls move under the prompt and keep to the right edge. */
  .race-head {
    padding: 0.8rem 0.95rem;
  }

  .race-prompt,
  .race-ask {
    flex-basis: 100%;
  }

  .race-head.full .race-prompt {
    font-size: 0.84rem;
  }

  /* With a picture, the controls sit beside it and the prompt takes the full
     width below, so the question itself stays in view. */
  .race-head.pictured {
    column-gap: 0.75rem;
  }

  .race-head.pictured .race-prompt {
    order: 1;
    flex-basis: 100%;
  }

  .race-image img {
    height: 3.5rem;
  }

  /* A lane becomes one column: its name and speedup share a line above the bar. */
  .lane {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.5rem;
    padding: 0.75rem 0.95rem 0.8rem;
  }

  .lane-id {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 0 0.75rem;
  }

  .lane-name {
    grid-column: 1;
  }

  .lane-x {
    grid-row: 1;
    grid-column: 2;
    font-size: 1.5rem;
    text-align: right;
  }

  .lane-id .lane-count {
    grid-row: auto;
    grid-column: 1 / -1;
    margin-top: 0;
    font-size: 1.3rem;
  }

  .lane-meta,
  .lane-id .lane-count ~ .lane-meta {
    grid-row: auto;
    grid-column: 1 / -1;
    margin-top: 0.15rem;
  }

  .lane-read {
    margin-top: 0.5rem;
  }

  /* Set on one line, the values may break between words. */
  .lane-meta span {
    display: inline;
    white-space: normal;
  }

  .lane-meta span + span::before {
    content: " \00b7\00a0";
  }

  .lane-text {
    margin-top: 0.5rem;
    border-width: 0.35rem 0.65rem;
  }

  .lane-logo {
    height: 2.25rem;
  }

  .race-bar button {
    padding: 0 0.85rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .btn,
  .race-bar button {
    transition: none;
  }
}

/* In a forced-color theme the bars keep their own colors, since they are the
   content, and the controls get a real outline in place of the drawn one. */
@media (forced-colors: active) {
  .lane-rail,
  .lane-rail::after,
  .lane-fill,
  .lane-late,
  .lane-tick,
  .lane-tick::before,
  .lane-mark,
  .lane-text .guest {
    forced-color-adjust: none;
  }

  .race-bar button {
    border: 1.5px solid ButtonText;
  }

  .lane-text {
    border-color: Canvas;
  }
}

/* ---------- Measured table overflow ---------- */

/* The width rules above are the fallback. Once the script has measured a
   table, its hint and its pinned first column follow what it really does. */
.table-block.fits .scroll-hint {
  display: none;
}

.table-block.scrolls .scroll-hint {
  display: block;
}

.table-block.scrolls .stick {
  position: sticky;
  left: 0;
  z-index: 1;
  background: #fff;
  box-shadow: 1px 0 0 var(--rule);
}

.table-block.scrolls tbody tr.ours > .stick {
  background: var(--ours);
}

@media print {
  .topbar,
  .links,
  .copy,
  .race-bar,
  .more,
  .footer,
  .scroll-hint,
  .table-block.wide .scroll-hint,
  .table-block.scrolls .scroll-hint {
    display: none;
  }

  .band {
    background: none;
  }

  .table-wrap {
    overflow: visible;
  }

  .tbl.dense {
    min-width: 0;
    font-size: 0.6rem;
  }

  .tbl.dense th,
  .tbl.dense td {
    padding-right: 0.16rem;
    padding-left: 0.16rem;
  }

  /* A wide table is set smaller on paper, so that its last column stays
     inside the frame and the sheet is not scaled down to hold it. */
  .table-block.wide .tbl:not(.dense) {
    font-size: 0.74rem;
  }

  .table-block.wide .tbl:not(.dense) th,
  .table-block.wide .tbl:not(.dense) td {
    padding-right: 0.3rem;
    padding-left: 0.3rem;
  }

  .title .name,
  .lane-name .blend,
  .lane.ours .lane-x b,
  .lane.ours .lane-id .lane-count b {
    background: none;
    color: var(--accent-a);
  }

  /* The bars are the content of the replay, so they print even when the
     reader leaves background graphics off. */
  .lane.ours,
  .lane.ours::before,
  .lane-rail,
  .lane-rail::after,
  .lane-fill,
  .lane-late,
  .lane-tick,
  .lane-tick::before,
  .lane-text,
  .lane-text::before,
  .lane-text mark,
  .lane-text .guest,
  .caption .guest.chip,
  .lane-mark {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* A section heading stays on the same sheet as the text it introduces. */
  .section h2 {
    break-after: avoid;
  }

  /* A card label and title stay on the same sheet as the card text. */
  .step-label,
  .step h3 {
    break-after: avoid;
  }

  /* A replay lane is one reading unit, a label with its bar, and the prompt
     strip stays on the sheet of the first lane. */
  .lane {
    break-inside: avoid;
  }

  .race-head {
    break-after: avoid;
  }
}
