/* CurveCodec 2 project page. Same language as the demo Space, scaled for reading:
   Type scale (px):    11 label (uppercase, +.1em) / 13 small, captions / 15 body / 20 section title / 40 page title
   Spacing scale (px): 4 / 8 / 12 / 16 / 24 / 32 / 48 / 72 / 112
   Widths: --w-text 72ch prose column, --w-page 1080px figures, --w-wide 1440px spare (the live demo sits on
   the page column).
   Motion: 150-250 ms, ease-out, transform + opacity only; prefers-reduced-motion removes movement. */

:root { --w-text: 72ch; --w-page: 1080px; --w-wide: 1440px; --gutter: 32px; }
@media (max-width: 720px) { :root { --gutter: 16px; } }

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 64px; }
body {
  margin: 0; background: var(--page); color: var(--ink);
  font: 15px/1.7 var(--font); letter-spacing: 0;
  font-feature-settings: "calt" 0;                      /* no code ligatures in prose: "->", "//", "..." stay literal */
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility;
  transition: background-color .2s ease-out, color .2s ease-out;
}
img, svg, video, iframe { display: block; max-width: 100%; }
a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px;
    text-decoration-color: var(--rule-strong); transition: text-decoration-color .15s ease-out; }
a:hover { text-decoration-color: currentColor; }
:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }
::selection { background: var(--ours); color: var(--page); }
b, strong { font-weight: 500; }
em { font-style: italic; }
code { font: inherit; font-size: .93em; padding: 0 var(--s1); background: var(--tile); }
.ours { color: var(--ours); } .acl { color: var(--acl); }

.wrap { width: 100%; max-width: calc(var(--w-page) + 2 * var(--gutter)); margin: 0 auto; padding-inline: var(--gutter); }
.wrap.wide { max-width: calc(var(--w-wide) + 2 * var(--gutter)); }
.prose { max-width: var(--w-text); }
.prose p { margin: 0 0 var(--s4); text-wrap: pretty; }
.prose p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------------------ top bar: name left, anchors + theme toggle right */
.bar {
  position: sticky; top: 0; z-index: 10; background: color-mix(in srgb, var(--page) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(8px); -webkit-backdrop-filter: saturate(1.4) blur(8px);
  border-bottom: 1px solid var(--rule);
}
.bar .wrap { display: flex; align-items: center; gap: var(--s5); height: 48px; }
.bar .name { font-size: 13px; font-weight: 500; letter-spacing: -0.02em; text-decoration: none; white-space: nowrap; }
.bar nav { margin-left: auto; display: flex; gap: var(--s4); font-size: 12px; letter-spacing: .02em; overflow-x: auto; scrollbar-width: none; }
.bar nav a { color: var(--muted); text-decoration: none; white-space: nowrap; transition: color .15s ease-out; }
.bar nav a:hover, .bar nav a.on { color: var(--ink); }
.theme {
  flex: none; width: 28px; height: 28px; display: grid; place-items: center; padding: 0; cursor: pointer;
  background: transparent; color: var(--muted); border: 1px solid var(--rule-strong); border-radius: 2px;
  transition: color .15s ease-out, border-color .15s ease-out;
}
.theme:hover { color: var(--ink); border-color: var(--ink); }
.theme svg { width: 14px; height: 14px; }
@media (max-width: 720px) { .bar nav { display: none; } .theme { margin-left: auto; } }

/* ------------------------------------------------------------------ floating contents
   Fixed in the left margin when there is room for it beside the page column (>= 1400px); the top-bar section links
   hide then, so the page has one set. Active item: ink + a 1px bar on the rail, like the Space's list groups. */
.toc { display: none; }
@media (min-width: 1400px) {
  .toc {
    display: block; position: fixed; z-index: 5; top: 96px; width: 128px;
    left: max(var(--gutter), calc(50% - var(--w-page) / 2 - 128px - 48px));
  }
  .bar nav { display: none; }
  .bar .theme { margin-left: auto; }
}
.toc p { margin: 0 0 var(--s3); font-size: 11px; font-weight: 500; line-height: 16px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.toc nav { display: flex; flex-direction: column; border-left: 1px solid var(--rule); }
.toc a {
  position: relative; padding: var(--s1) 0 var(--s1) var(--s3); font-size: 12px; line-height: 20px; letter-spacing: .02em;
  color: var(--muted); text-decoration: none; transition: color .15s ease-out;
}
.toc a::before {
  content: ""; position: absolute; left: -1px; top: 0; bottom: 0; width: 1px; background: var(--ink);
  transform: scaleY(0); transition: transform .2s var(--ease);
}
.toc a:hover, .toc a.on { color: var(--ink); }
.toc a.on::before { transform: scaleY(1); }
.toc a.sub { padding: 2px 0 2px calc(var(--s3) + var(--s3)); font-size: 11px; line-height: 16px; color: var(--faint); }
.toc a.sub:hover, .toc a.sub.on { color: var(--ink); }

/* ------------------------------------------------------------------ hero */
.hero { padding-top: var(--s8); padding-bottom: var(--s7); }
.hero + .wide { scroll-margin-top: 64px; }
.venue { margin: 0 0 var(--s4); font-size: 11px; font-weight: 500; line-height: 16px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
h1 { margin: 0; max-width: 24ch; font-size: 40px; line-height: 48px; font-weight: 500; letter-spacing: -0.045em; text-wrap: balance; }
/* version tag at the title's bottom-right, on its baseline (as in the demo Space) */
h1 .ver { margin-left: var(--s2); font-size: 13px; line-height: 1; letter-spacing: 0; font-weight: 400; color: var(--faint); }
h1 .sub { display: block; margin-top: var(--s3); max-width: 40ch; font-size: 20px; line-height: 28px; letter-spacing: -0.03em; color: var(--muted); font-weight: 400; }
@media (max-width: 720px) { h1 { font-size: 28px; line-height: 34px; } h1 .sub { font-size: 16px; line-height: 24px; } }

.authors { margin: var(--s6) 0 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: var(--s1) var(--s5); font-size: 15px; }
.authors sup { font-size: 10px; color: var(--faint); margin-left: 2px; }
.affils { margin: var(--s2) 0 0; font-size: 13px; color: var(--muted); }
.affils sup { font-size: 9px; margin-right: 2px; }

.links { margin: var(--s5) 0 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.btn {
  display: inline-flex; align-items: center; gap: var(--s2); min-height: 36px; padding: 0 var(--s4);
  font: 500 13px/20px var(--font); color: var(--ink); text-decoration: none; cursor: pointer;
  background: transparent; border: 1px solid var(--rule-strong); border-radius: 2px;
  transition: background-color .15s ease-out, border-color .15s ease-out, color .15s ease-out;
}
.btn:hover { border-color: var(--ink); background: var(--hover); }
.btn.primary { background: var(--ink); border-color: var(--ink); color: var(--page); }
.btn.primary:hover { background: var(--ink-2); border-color: var(--ink-2); }
.btn.soon { color: var(--faint); border-style: dashed; cursor: default; }
.btn.soon:hover { background: transparent; border-color: var(--rule-strong); }
.btn .arr { color: var(--faint); }
.btn.primary .arr { color: inherit; opacity: .6; }

/* ------------------------------------------------------------------ sections */
section { padding-top: var(--s8); }
.label {
  display: flex; align-items: baseline; gap: var(--s3); margin: 0 0 var(--s5); padding-top: var(--s3); border-top: 1px solid var(--rule);
  font-size: 11px; font-weight: 500; line-height: 16px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}
.label .n { color: var(--faint); font-variant-numeric: tabular-nums; }
.label .aside { margin-left: auto; text-transform: none; letter-spacing: .02em; font-weight: 400; }
h2 { margin: 0 0 var(--s4); max-width: 36ch; font-size: 20px; line-height: 28px; font-weight: 500; letter-spacing: -0.03em; text-wrap: balance; }

/* ------------------------------------------------------------------ questions: Q + answer bullets, then the letter popover
   The letter opens on hover or keyboard focus (CSS), and stays open when clicked (js toggles .pinned) - the panel is
   inside .letter, so moving the pointer onto it keeps it open for scrolling. Esc or a click outside unpins it.
   Each time it opens, js picks the side with more room (below by default) and caps its height to that room. */
.qa { max-width: var(--w-text); }
.qa + .qa { margin-top: var(--s7); }
h3 { display: flex; align-items: baseline; gap: var(--s3); margin: 0 0 var(--s4); font-size: 20px; line-height: 28px; font-weight: 500; letter-spacing: -0.03em; }
h3 .q { flex: none; font-size: 11px; font-weight: 500; line-height: 16px; letter-spacing: .1em; color: var(--faint); }
.qa > ul { margin: 0; padding: 0; list-style: none; }
.qa > ul > li { position: relative; padding-left: var(--s5); text-wrap: pretty; }
.qa > ul > li + li { margin-top: var(--s4); }
.qa > ul > li::before { content: ""; position: absolute; left: 0; top: .85em; width: 12px; height: 1px; background: var(--rule-strong); }

.letter { position: relative; margin-top: var(--s6); }
.letter-btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--s1); padding: var(--s3) var(--s4); cursor: pointer;
  font: 400 13px/20px var(--font); color: var(--ink); text-align: left;
  background: transparent; border: 1px solid var(--rule-strong); border-radius: 2px;
  transition: border-color .15s ease-out, background-color .15s ease-out;
}
.letter-btn .k { font-size: 11px; font-weight: 500; line-height: 16px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.letter-btn::after { content: "Hover to read · click to keep open"; font-size: 11px; line-height: 16px; color: var(--faint); }
.letter:hover .letter-btn, .letter.pinned .letter-btn { border-color: var(--ink); background: var(--hover); }
.letter-pop {
  position: absolute; z-index: 20; left: 0; top: calc(100% + var(--s2)); width: min(680px, calc(100vw - 2 * var(--gutter)));
  max-height: min(64vh, 640px); overflow-y: auto; overscroll-behavior: contain; padding: var(--s5) var(--s5) var(--s4);
  background: var(--page); border: 1px solid var(--rule-strong); box-shadow: 0 12px 32px rgba(0, 0, 0, .12);
  font-size: 13px; line-height: 21px; color: var(--ink-2);
  opacity: 0; visibility: hidden; transform: translateY(4px);
  transition: opacity .15s ease-out, transform .15s var(--ease), visibility 0s linear .15s;
}
.letter-pop::before { content: ""; position: absolute; left: 0; right: 0; top: calc(-1 * var(--s2) - 1px); height: var(--s2); }  /* hover bridge */
.letter:hover .letter-pop, .letter:focus-within .letter-pop, .letter.pinned .letter-pop {
  opacity: 1; visibility: visible; transform: none; transition: opacity .15s ease-out, transform .15s var(--ease), visibility 0s;
}
/* low on the screen: js adds .up and the panel opens above the button instead (bridge moves to its bottom edge) */
.letter.up .letter-pop { top: auto; bottom: calc(100% + var(--s2)); transform: translateY(-4px); }
.letter.up .letter-pop::before { top: auto; bottom: calc(-1 * var(--s2) - 1px); }
.letter.up:hover .letter-pop, .letter.up:focus-within .letter-pop, .letter.up.pinned .letter-pop { transform: none; }
.letter-pop p { margin: 0 0 var(--s3); text-wrap: pretty; }
.letter-pop ul { margin: 0 0 var(--s3); padding-left: var(--s5); }
.letter-pop li { margin-bottom: var(--s2); }
.letter-pop .letter-meta { padding-bottom: var(--s3); border-bottom: 1px solid var(--rule); font-size: 12px; line-height: 18px; color: var(--muted); }

/* ------------------------------------------------------------------ core equations (method): equation | one-paragraph reading */
.eqs { list-style: none; margin: var(--s6) 0 0; padding: 0; counter-reset: eq; }
.eqs li { counter-increment: eq; display: grid; grid-template-columns: minmax(0, 11fr) minmax(0, 9fr); gap: var(--s3) var(--s6); align-items: center; padding: var(--s5) 0; border-top: 1px solid var(--rule); }
.eqs li:last-child { border-bottom: 1px solid var(--rule); }
.eqs .eq { position: relative; padding-left: var(--s7); overflow-x: auto; overflow-y: hidden; font-size: 15px; color: var(--ink); }
.eqs .eq::before { content: "(" counter(eq) ")"; position: absolute; left: 0; top: 50%; transform: translateY(-50%); font-size: 12px; color: var(--faint); font-variant-numeric: tabular-nums; }
.eqs .eq .katex-display { margin: 0; text-align: left; }
.eqs .eq .katex-display > .katex { text-align: left; font-size: 1.1em; }
.eqs p { margin: 0; font-size: 13px; line-height: 20px; color: var(--muted); text-wrap: pretty; }
.eqs p b { color: var(--ink); }
@media (max-width: 860px) { .eqs li { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------ analysis: per-dataset dot plot | findings
   Precision is ordinal, so its three marks are one hue, light -> dark with tightening p (--pd1 0.01 cm is the strongest).
   Hovering a finding highlights its datasets in the plot (js: .pd-plot.focus + .hl rows). */
:root { --pd1: #134e4a; --pd2: #0d9488; --pd3: #6cc3b8; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --pd1: #8fe3d6; --pd2: #14b8a6; --pd3: #0f6f66; } }
:root[data-theme="dark"] { --pd1: #8fe3d6; --pd2: #14b8a6; --pd3: #0f6f66; }

.ana { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); gap: var(--s6) 64px; align-items: start; }
@media (max-width: 960px) { .ana { grid-template-columns: 1fr; } }
.pd { padding-top: var(--s3); border-top: 1px solid var(--rule); }
.pd-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2) var(--s4); }
.pd-head b { font-size: 13px; }
.legend.pd-legend li::before { width: 8px; height: 8px; border-radius: 50%; }
.pd-legend .p1::before { background: var(--pd1); } .pd-legend .p2::before { background: var(--pd2); } .pd-legend .p3::before { background: var(--pd3); }
.pd-plot { position: relative; margin-top: var(--s3); }
.pd-plot svg { display: block; width: 100%; overflow: visible; font: 11px var(--font); }
.pd-plot .grid line { stroke: var(--rule); }
.pd-plot .axis text { fill: var(--muted); }
.pd-plot .row .name { fill: var(--ink-2); font-size: 11px; }
.pd-plot .row .span { stroke: var(--rule-strong); stroke-width: 2; stroke-linecap: round; }
.pd-plot .row circle { stroke: var(--page); stroke-width: 1.5; }
.pd-plot .row .d1 { fill: var(--pd1); } .pd-plot .row .d2 { fill: var(--pd2); } .pd-plot .row .d3 { fill: var(--pd3); }
.pd-plot .row .band { fill: transparent; }
.pd-plot .row.on .band { fill: var(--hover); }
.pd-plot .row.on .name { fill: var(--ink); }
.pd-plot .row { transition: opacity .15s ease-out; }
.pd-plot.focus .row:not(.hl) { opacity: .22; }
.pd-plot.focus .row.hl .name { fill: var(--ink); font-weight: 500; }

.findings { list-style: none; margin: 0; padding: 0; counter-reset: fd; }
.x-read .findings li:first-child { border-top: 0; padding-top: var(--s1); }
.x-read .findings li:first-child::before { top: var(--s1); }
.findings li { counter-increment: fd; position: relative; padding: var(--s4) 0 var(--s4) var(--s6); border-top: 1px solid var(--rule); font-size: 13px; line-height: 20px; color: var(--muted); text-wrap: pretty; cursor: default; transition: color .15s ease-out; }
.findings li:last-child { border-bottom: 1px solid var(--rule); }
.findings li::before { content: counter(fd, decimal-leading-zero); position: absolute; left: 0; top: var(--s4); font-size: 11px; line-height: 20px; color: var(--faint); font-variant-numeric: tabular-nums; }
.findings b { display: block; margin-bottom: var(--s1); color: var(--ink); }
.findings li:hover { color: var(--ink-2); }

/* ------------------------------------------------------------------ extra analysis blocks (web/build_analysis.py)
   chart(s) | reading. Charts are .ch hosts drawn by js from the JSON spec beside them. --c-alt (violet) is the second
   categorical colour, validated with the ours teal in both themes. */
:root { --c-alt: #6d5ed6; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --c-alt: #9085e9; } }
:root[data-theme="dark"] { --c-alt: #9085e9; }
.x-ana { margin-top: var(--s8); }
.x-figs { display: grid; gap: var(--s6); }
.x-read { padding-top: var(--s3); border-top: 1px solid var(--rule); }
.x-read h3 { margin: 0 0 var(--s3); font-size: 17px; line-height: 24px; }
.x-read p { margin: 0 0 var(--s3); font-size: 13px; line-height: 20px; color: var(--ink-2); text-wrap: pretty; }
.x-read .x-note { margin-top: var(--s4); font-size: 12px; line-height: 18px; color: var(--faint); }
.ch { position: relative; margin-top: var(--s3); }
.ch svg { display: block; width: 100%; overflow: visible; font: 11px var(--font); }
.ch .grid line { stroke: var(--rule); }
.ch .axis text { fill: var(--muted); }
.ch .ref line { stroke: var(--ink-2); stroke-dasharray: 3 3; }
.ch .ref text { fill: var(--muted); font-size: 10px; }
.ch .row .name { fill: var(--ink-2); }
.ch .row .sub { fill: var(--faint); font-size: 10px; }
.ch .row .band { fill: transparent; }
.ch .row.on .band { fill: var(--hover); }
.ch .row.on .name { fill: var(--ink); }
.ch .span { stroke: var(--rule-strong); stroke-width: 2; stroke-linecap: round; }
.ch .rng { stroke: var(--muted); stroke-width: 6; stroke-linecap: round; opacity: .35; }
.ch circle.d { stroke: var(--page); stroke-width: 1.5; }
.ch .bar { rx: 2; }
.ch .val { fill: var(--ink-2); font-size: 11px; font-variant-numeric: tabular-nums; }
.ch .line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.ch .end, .ch .plabel { fill: var(--ink-2); font-size: 10px; }
.ch .cross { stroke: var(--rule-strong); stroke-dasharray: 2 3; opacity: 0; }
.ch.hot .cross { opacity: 1; }
.ch.hot .tip { opacity: 1; transform: none; }
.pd-legend li[style]::before { background: var(--c); }

/* ------------------------------------------------------------------ figures and placeholders */
figure { margin: 0; }
figcaption { margin-top: var(--s3); max-width: var(--w-text); font-size: 13px; line-height: 20px; color: var(--muted); text-wrap: pretty; }
figcaption b { color: var(--ink); }
.ph {
  position: relative; display: grid; place-items: center; width: 100%; aspect-ratio: var(--ar, 16 / 9);
  background: repeating-linear-gradient(-45deg, transparent 0 7px, var(--rule) 7px 8px), var(--tile);
  border: 1px solid var(--rule-strong); overflow: hidden;
}
.ph > div { max-width: min(44ch, calc(100% - 2 * var(--s4))); padding: var(--s3) var(--s4); background: var(--page); border: 1px solid var(--rule); text-align: center; }
.ph b { display: block; font-size: 11px; font-weight: 500; line-height: 16px; letter-spacing: .1em; text-transform: uppercase; }
.ph span { display: block; margin-top: var(--s1); font-size: 12px; line-height: 18px; color: var(--muted); }

/* paper figures (web/build_figs.sh): drawn for a white page, so they keep a white sheet in dark mode too */
.paper { background: #ffffff; border: 1px solid var(--rule); }
.paper img { width: 100%; height: auto; }


/* ------------------------------------------------------------------ overview: intro, then specification list | rate chart
   Chart series: --c-ours teal / --c-acl orange (the demo's two accents, re-stepped as a validated categorical pair on
   both surfaces). Legend + direct labels, so identity is never colour alone. The collapsed table under the chart is its
   data source and its table view. */
:root { --c-ours: #0d9488; --c-acl: #c2410c; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --c-ours: #13a594; --c-acl: #dc6a26; } }
:root[data-theme="dark"] { --c-ours: #13a594; --c-acl: #dc6a26; }

.intro { margin: 0 0 var(--s6); max-width: var(--w-text); text-wrap: pretty; }
.spec { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--s6) 64px; align-items: stretch; }
@media (max-width: 860px) { .spec { grid-template-columns: 1fr; } }
.specs { margin: 0; }
.specs > div { display: grid; grid-template-columns: 13ch minmax(0, 1fr); gap: var(--s3); padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.specs > div:last-child { border-bottom: 1px solid var(--rule); }
.specs dt { font-size: 11px; font-weight: 500; line-height: 20px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.specs dd { margin: 0; font-size: 13px; line-height: 20px; color: var(--ink); text-wrap: pretty; }
.specs sup, .note sup { font-size: 9px; line-height: 0; color: var(--muted); }

/* the chart takes the height of the spec list beside it (plot = flex 1), never less than 200px */
.rd { display: flex; flex-direction: column; padding-top: var(--s3); border-top: 1px solid var(--rule); }
.rd figcaption { margin-top: var(--s2); }
.rd-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2) var(--s4); }
.rd-head b { font-size: 13px; }
.legend { margin: 0 0 0 auto; padding: 0; list-style: none; display: flex; gap: var(--s4); font-size: 12px; line-height: 16px; color: var(--ink-2); }
.legend li { display: flex; align-items: center; gap: var(--s2); }
.legend li::before { content: ""; width: 14px; height: 2px; border-radius: 1px; }
.legend .c-ours::before { background: var(--c-ours); } .legend .c-acl::before { background: var(--c-acl); }
.rd-plot { position: relative; flex: 1 1 0; min-height: 200px; margin-top: var(--s3); }
@media (max-width: 860px) { .rd-plot { flex: none; aspect-ratio: 4 / 3; } }
.rd-plot svg { width: 100%; height: 100%; overflow: visible; font: 11px var(--font); }
.rd-plot .grid line { stroke: var(--rule); }
.rd-plot .axis text { fill: var(--muted); }
.rd-plot .line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.rd-plot .dot { stroke: var(--page); stroke-width: 2; }
.rd-plot .s-ours .line { stroke: var(--c-ours); } .rd-plot .s-ours .dot { fill: var(--c-ours); }
.rd-plot .s-acl .line { stroke: var(--c-acl); } .rd-plot .s-acl .dot { fill: var(--c-acl); }
.rd-plot .end { fill: var(--ink-2); font-size: 11px; }
.rd-plot .s-orig .dot { fill: var(--ink); }
.rd-plot .s-orig .ref { stroke: var(--rule-strong); stroke-dasharray: 3 4; }
.rd-plot .brk { stroke: var(--muted); }
.rd-plot .dot.on { r: 6; }
.rd-plot .cross { stroke: var(--rule-strong); stroke-dasharray: 2 3; opacity: 0; }
.rd-plot.hot .cross { opacity: 1; }
.tip {
  position: absolute; pointer-events: none; z-index: 2; padding: var(--s2) var(--s3);
  background: var(--page); border: 1px solid var(--rule-strong); font-size: 12px; line-height: 18px; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
  opacity: 0; transform: translateY(4px); transition: opacity .15s ease-out, transform .15s var(--ease);
}
.rd-plot.hot .tip, .pd-plot.hot .tip { opacity: 1; transform: none; }
.tip b { display: block; margin-bottom: var(--s1); font-weight: 500; }
.tip div { display: flex; align-items: center; gap: var(--s2); color: var(--ink-2); }
.tip div::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--c); flex: none; }
.tip div span { margin-left: auto; padding-left: var(--s4); color: var(--ink); }
.tip .r { display: block; margin-top: var(--s1); color: var(--muted); }

.rd-data { margin-top: var(--s1); }
.rd-table tr.orig td { color: var(--muted); text-align: left; }
.rd-data summary { display: inline-block; cursor: pointer; font-size: 12px; line-height: 18px; color: var(--muted); list-style: none; }
.rd-data summary::-webkit-details-marker { display: none; }
.rd-data summary::before { content: "+ "; }
.rd-data[open] summary::before { content: "− "; }
.rd-data summary:hover { color: var(--ink); }
.rd-table { width: 100%; margin-top: var(--s2); border-collapse: collapse; font-size: 13px; line-height: 20px; font-variant-numeric: tabular-nums; }
.rd-table th { font-size: 11px; font-weight: 500; line-height: 16px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); text-align: right; padding: var(--s2) 0 var(--s2) var(--s3); border-bottom: 1px solid var(--rule); white-space: nowrap; }
.rd-table td { text-align: right; padding: var(--s1) 0 var(--s1) var(--s3); border-bottom: 1px solid var(--rule); }
.rd-table th:first-child, .rd-table td:first-child { text-align: left; padding-left: 0; }
.rd-table th[colspan] { text-align: center; border-bottom-color: var(--rule-strong); }
.note { margin: var(--s4) 0 0; max-width: var(--w-text); font-size: 12px; line-height: 18px; color: var(--muted); text-wrap: pretty; }

/* ------------------------------------------------------------------ live demo = the teaser
   The frame spans --w-wide right under the hero. Desktop: js adds .auto and loads the iframe at once (poster says
   "Loading"); phones and no-js: the poster links out, since the Space's two-column viewer does not fit. */
.demo { position: relative; height: min(740px, calc(100dvh - 96px)); min-height: 560px; border: 1px solid var(--rule-strong); background: var(--tile); }
.demo iframe { width: 100%; height: 100%; border: 0; background: var(--page); opacity: 0; transition: opacity .25s ease-out; }
.demo.loaded iframe { opacity: 1; }
.demo .poster { position: absolute; inset: 0; display: grid; place-items: center; transition: opacity .25s ease-out; }
.demo .poster .ph { position: absolute; inset: 0; aspect-ratio: auto; border: 0; }
.demo .poster .go { position: relative; display: flex; flex-direction: column; align-items: center; gap: var(--s3); max-width: calc(100% - 2 * var(--s4)); padding: var(--s5) var(--s6); background: var(--page); border: 1px solid var(--rule); text-align: center; }
.demo .poster .go small { font-size: 12px; line-height: 18px; color: var(--muted); }
.demo .wait { display: none; font-size: 13px; font-weight: 500; }
.demo.auto .wait { display: block; animation: pulse 1.6s ease-in-out infinite; }
.demo.auto .open { display: none; }
.demo.loaded .poster { opacity: 0; pointer-events: none; }
@keyframes pulse { 50% { opacity: .4; } }
@media (max-width: 860px) { .demo { height: auto; min-height: 0; aspect-ratio: 4 / 5; } }
.demo-meta { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); margin-top: var(--s3); font-size: 13px; line-height: 20px; color: var(--muted); }
.demo-meta b { color: var(--ink); }
.demo-meta a { color: var(--ink); white-space: nowrap; }
.demo-meta > span { flex: 1 1 40ch; min-width: 0; }
.demo-meta .r { margin-left: auto; }

/* ------------------------------------------------------------------ BibTeX */
.bib-k { margin: 0 0 var(--s2); font-size: 11px; font-weight: 500; line-height: 16px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.bib + .bib-k { margin-top: var(--s5); }
/* version list above the BibTeX: version | what it is | links */
.versions { list-style: none; margin: 0 0 var(--s7); padding: 0; }
.versions li { display: grid; grid-template-columns: 48px minmax(0, 1fr) auto; gap: var(--s2) var(--s5); align-items: baseline; padding: var(--s4) 0; border-top: 1px solid var(--rule); }
.versions li:last-child { border-bottom: 1px solid var(--rule); }
.versions .v { font-size: 20px; line-height: 24px; font-weight: 500; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.versions b { font-size: 15px; color: var(--ink); }
.versions div { font-size: 13px; color: var(--muted); }
.versions p { margin: var(--s1) 0 0; max-width: var(--w-text); font-size: 13px; line-height: 20px; color: var(--muted); text-wrap: pretty; }
.versions p strong { color: var(--ink); font-weight: 500; }
.versions .st { margin-left: var(--s2); padding: 1px var(--s2); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); border: 1px solid var(--rule-strong); border-radius: 2px; vertical-align: 2px; }
.versions .st.now { color: var(--ours); border-color: currentColor; }
.versions .lk { display: flex; gap: var(--s4); font-size: 12px; color: var(--faint); white-space: nowrap; }
.versions .lk a { color: var(--ink); }
@media (max-width: 720px) { .versions li { grid-template-columns: 40px minmax(0, 1fr); } .versions .lk { grid-column: 2; } }
.bib { position: relative; border: 1px solid var(--rule); background: var(--tile); }
.bib pre { margin: 0; padding: var(--s4) var(--s5); overflow-x: auto; font: 13px/20px var(--font); color: var(--ink-2); }
.bib .copy { position: absolute; top: var(--s2); right: var(--s2); min-height: 28px; padding: 0 var(--s3); font-size: 12px; background: var(--page); }

footer { margin-top: var(--s9); padding: var(--s5) 0 var(--s6); border-top: 1px solid var(--rule); font-size: 12px; line-height: 18px; color: var(--faint); }
footer .wrap { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
footer .r { margin-left: auto; }

/* ------------------------------------------------------------------ reveal on scroll (js adds .rv; .in when visible) */
.rv { opacity: 0; transform: translateY(8px); transition: opacity .25s ease-out, transform .25s var(--ease); }
.rv.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rv { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; }
}

/* ------------------------------------------------------------------ acknowledgements: mesh credits (same look as the data tables' toggles) */
.credits { margin-top: var(--s1); }
.credits summary { display: inline-block; cursor: pointer; font-size: 12px; line-height: 18px; color: var(--muted); list-style: none; }
.credits summary::-webkit-details-marker { display: none; }
.credits summary::before { content: "+ "; }
.credits[open] summary::before { content: "− "; }
.credits summary:hover { color: var(--ink); }
.credits ul { margin: var(--s1) 0 0; padding-left: 1.2em; max-width: var(--w-text); font-size: 12px; line-height: 18px; color: var(--muted); }
