/* Shared styles for the web edition and both PDFs. Tokens come from tokens.css (Promptless design system).
   Contrast pairs used here were computed against WCAG 2.2: ink-900 on white 18.4:1, ink-500 on white 5.0:1,
   ink-500 on brand-50 4.5:1, brand-600 on white 6.0:1, brand-700 on brand-50 7.3:1, brand-400 on ink-950 6.5:1,
   white on brand-500 4.6:1, white on ink-600 8.5:1. Chart marks against white: brand-700 8.0:1, brand-500 4.6:1,
   ink-500 5.0:1, ink-600 8.5:1, ink-800 16.4:1, and the ink-400 leader lines and arrows 3.05:1; against the brand-50 band, brand-500 4.2:1. On the chapter opener's ink-950, the numeral (ink-500) is 3.9:1 and the paws
   (brand-600) are 3.2:1. Decorative colors (paws) carry no information. */


:root {
  --ink: var(--pl-ink-900);
  --ink-soft: var(--pl-ink-700);
  --muted: var(--pl-ink-500);
  --rule: var(--pl-ink-150);
  --panel: var(--pl-brand-50);
  --panel-ink: var(--pl-brand-700);
  --accent: var(--pl-brand-500);
  --accent-text: var(--pl-brand-600);
  --navy: var(--pl-ink-950);
  --pass: #167044; --pass-bg: #edf8f1;
  --fail: #a33933; --fail-bg: #fdf0ef;
  --mark: var(--pl-brand-500);
  --mark-focus: var(--pl-brand-700);
  --mark-muted: var(--pl-ink-500);
  --mark-base: var(--pl-ink-800);
  --track: var(--pl-ink-100);
  --sans: "Geist", ui-sans-serif, system-ui, sans-serif;
  --mono: "Geist Mono", ui-monospace, monospace;
}

/* The type scale. Every font size in the book is one of these steps. build.mjs puts the edition's class on <html>.
   The covers, the chapter openers, the title page, and the web hero also set their own display type.
   - Body: all reading text, from paragraphs, lists, and tables to callouts, checklists, the glossary, and chart
     category labels, and the h4 headings that group sections within a chapter. Chart values are body, every one at the same size.
   - Small: metadata, such as figure numbers and notes, labels, chart sub-labels and axis ticks, running heads,
     folios, and the web footer, and code blocks and doc excerpts, whose mono face sets larger than the text face at
     the same size. Inline code stays at body. It is the only step below body, and nothing is smaller.
   - Display: figure titles, section headings, the PDFs' contents title, the stat numbers, and the leaderboard's
     composite score in its phone layout.
     A section heading is a chapter's h3 or a front- or back-matter h2, and every one sets in the h3 step. A front-matter
     figure that is its own section has its title as the section's h2, and that title keeps the figure-title step. */
:root.paged {
  --type-small: 9.2pt; --leading-small: 12pt;
  --type-body: 11.5pt; --leading-body: 16.5pt;
  --type-title: 14.25pt; --type-h3: 15.2pt; --type-value: 15.2pt; --type-h2: 21.2pt;
  --type-stat: 23pt; --type-stat-lg: 28.5pt;
}
:root.web {
  --type-small: 16px; --leading-small: 1.45;
  --type-body: 19px; --leading-body: 1.6;
  --type-h3: 28px; --type-title: 34px; --type-value: 34px;
  --type-stat: 38px; --type-stat-lg: 57px;
}
/* The web edition leaves the root at the browser's default size, as dogbench.ai does, so the rem sizes in the site's
   navigation bar (../site/nav.css) match the site. */
:root.paged, body { font-size: var(--type-body); line-height: var(--leading-body); }
/* The small step, everywhere it applies in both editions. */
.label, .fig-num, .fig-note, .score-note, .score-head, .fig-data summary, .bar-label small, .bar-sub, .score-agent small, .stat a, .card .k, .prio,
.cloud-notes, .doc-head, .doc-body, pre, .mark-n, .checklist h4, .link-card a, :is(table.leaderboard, table.cloud-table, table.steps-table) th[scope="row"] small, .toc-group,
.pf-id, .pf-file, .ex-diagram, .ex-caption {
  font-size: var(--type-small); line-height: var(--leading-small);
}
.fig-title { font-size: var(--type-title); line-height: 1.2; }
.chapter-body h3, h2.front, h2.back { font-size: var(--type-h3); line-height: 1.25; }
.chapter-body > h4 { font-size: var(--type-body); line-height: var(--leading-body); }
.stat b, .why .why-stat b { font-size: var(--type-stat); }
/* SVG text sizes are in the SVG's user units, so each step is divided by the SVG's scale, --svg-k: its placed
   width over its 600-unit viewBox width. print.css and web.css set --svg-k. Text is body unless it takes a class. */
.fig svg text, .fig svg .t-body { font-size: calc(var(--type-body) / var(--svg-k)); }
.fig svg .t-small { font-size: calc(var(--type-small) / var(--svg-k)); }

html { font-family: var(--sans); color: var(--ink); background: #fff; -webkit-font-smoothing: antialiased; font-kerning: normal; }
body { margin: 0; }
h1, h2, h3, h4 { font-weight: 700; letter-spacing: -0.02em; color: var(--ink); margin: 0; }
p { margin: 0 0 0.75em; }
a { color: var(--accent-text); text-decoration-thickness: 1px; text-underline-offset: 0.15em; }
strong { font-weight: 600; }
code { font-family: var(--mono); background: var(--pl-ink-75); padding: 0.05em 0.3em; border-radius: 3px; }
pre { font-family: var(--mono); background: var(--pl-ink-50); border: 1px solid var(--rule); border-radius: 8px; padding: 0.8em 1em; overflow-x: auto; white-space: pre-wrap; }
pre code { background: none; padding: 0; }
ul, ol { padding-left: 1.25em; margin: 0 0 0.9em; }
li { margin: 0 0 0.3em; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* The Promptless wordmark set after text, as in "from Promptless": an inline SVG in the PDFs, an <img> on the web.
   It sits in the line, so the space before it in the markup is the gap: the viewBox starts at its first ink, and a
   word space plus the side bearing of the letter before it leaves about 0.3em. Its letters' baseline is 34.58 of the
   viewBox's 50 units down, so it drops by the rest, 0.3084 of its height, to put that baseline on the text's.
   --wordmark-h is in em, so the drop scales with the type. */
.pl-wordmark { --wordmark-h: 2.08em; display: inline; height: var(--wordmark-h); width: auto; vertical-align: calc(-0.3084 * var(--wordmark-h)); }

/* Section labels like "WHY IT MATTERS" */
.label { font-family: var(--mono); font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent-text); }

/* Chapter opener */
.opener { background: var(--navy); color: #fff; position: relative; overflow: hidden; isolation: isolate; }
.chapter-num::before { content: attr(data-n); }
.opener .chapter-num { color: var(--pl-ink-500); }
.opener h2 { color: #fff; }
.opener .lede { color: var(--pl-ink-200); }
.opener .tiles { display: flex; gap: 1.5em; }
.opener .tile { flex: 1; border-top: 1px solid var(--pl-ink-700); padding-top: 0.6em; }
.opener .tile b { display: block; color: var(--pl-brand-400); font-weight: 700; letter-spacing: -0.03em; line-height: 1; }
.opener .tile span { color: var(--pl-ink-200); display: block; }
/* The paws sit behind the opener's text, in a band above the chapter heading that web.css and print.css size. */
.opener .paws { position: absolute; right: 0; top: 0; z-index: -1; pointer-events: none; }
.opener .paws path, .opener .paws ellipse { fill: var(--pl-brand-600); }

/* Figures */
.fig { margin: 1.4em 0 1.6em; break-inside: avoid; }
.fig-head { margin-bottom: 0.7em; }
.fig-num { font-family: var(--mono); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); display: block; margin-bottom: 0.25em; }
.fig-title { font-family: var(--sans); font-weight: 700; letter-spacing: -0.015em; margin: 0; color: var(--ink); }
.fig-note { color: var(--muted); margin-top: 0.7em; }
.fig-data summary { cursor: pointer; color: var(--accent-text); font-weight: 500; }
.fig-data table { margin-top: 0.6em; }
.fig svg { display: block; width: 100%; height: auto; overflow: visible; }
.fig svg text { font-family: var(--sans); fill: var(--ink); }
.fig svg .mono { font-family: var(--mono); }
.fig svg .muted { fill: var(--muted); }

/* Tables */
table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
th, td { text-align: left; padding: 0.4em 0.5em; border-bottom: 1px solid var(--rule); vertical-align: top; }
th { font-weight: 600; color: var(--ink-soft); }
thead th { border-bottom-color: var(--pl-ink-300); }
td.num, th.num { text-align: right; }
td.num { font-family: var(--mono); }

/* Horizontal bar rows (HTML charts). print.css and web.css set the sizes: --bar-h (thickness), --bar-gap (space
   between rows, split above and below each row's hairline), and --value-w (the value column). A chart sits on an
   accent rule, as the glance and people ledgers do, and hairlines divide its rows. Each bar runs on a pale track
   that stands for 100, so every track spans the same width and the scale shows. Bars are square-ended, and a
   nonzero bar is at least 2 px long. Values sit in one right-aligned mono column, all in ink and at one size, so
   emphasis comes from bar color alone: the focus row's darker blue, blue for the rest, and gray for minor rows.
   Against white and against the track, the marks are brand-700 8.0:1 and 7.0:1, brand-500 4.6:1 and 4.0:1, ink-500
   5.0:1 and 4.3:1, ink-600 8.5:1 and 7.4:1, and ink-800 16.4:1 and 14.3:1. */
.bars { --value-w: 3.6em; display: grid; border-top: 2px solid var(--accent); padding-top: 0.3em; }
.bar-row { display: grid; grid-template-columns: var(--label-w, 38%) minmax(0, 1fr) var(--value-w); align-items: center; column-gap: 0.8em; padding: calc(var(--bar-gap) / 2) 0; }
.bar-row + .bar-row { border-top: 1px solid var(--rule); }
.bar-label { line-height: 1.2; font-weight: 500; }
.bar-label small { display: block; color: var(--muted); font-weight: 400; }
.bar-sub { grid-column: 1 / -1; color: var(--muted); }
.bar-track { position: relative; height: var(--bar-h); background: var(--track); }
.bar-fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--mark); }
.bar-fill:not(.w-0) { min-width: 2px; }
.bar-row.focus .bar-fill { background: var(--mark-focus); }
.bar-row.muted .bar-fill { background: var(--mark-muted); }
.bar-row.base .bar-fill { background: var(--mark-base); }
.bar-row.s2 .bar-fill, .bar-fill.s2 { background: var(--pl-ink-600); }
.bar-value { font-family: var(--mono); font-weight: 500; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; line-height: 1.2; }
/* Stacked bars: each segment carries its count inside it, and a 2 px surface gap separates the segments. */
/* Their counts are not out of 100, so the bars run on no track. */
.bars.stack { padding-top: 0; }
.bars.stack .bar-row { grid-template-columns: var(--label-w, 38%) minmax(0, 1fr); }
.bars.stack .bar-track { background: none; }
.bar-fill.seg.s2 { border-left: 2px solid #fff; }
.seg-value { position: absolute; top: 50%; transform: translateY(-50%); color: #fff; font-weight: 700; line-height: 1; padding-left: 0.55em; }
.legend { display: flex; flex-wrap: wrap; gap: 0.3em 1.4em; margin: 0 0 0.9em; }
.legend span { display: inline-flex; align-items: center; gap: 0.45em; }
.legend .key { display: inline-block; width: 0.85em; height: 0.85em; border-radius: 2px; background: var(--mark); }
.legend .key.s2 { background: var(--pl-ink-600); }
/* The scoring figure is a table: one row per agent, its two measures as bars on a shared 0 to 100 track, and the
   composite they produce at the right. Each row's cells sit on the grid, so the bars line up down each column. */
.score-table { --bar-h: 0.7em; display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) auto; column-gap: 1em; }
.score-row { display: contents; }
.score-row > * { display: flex; align-items: center; margin: 0; padding: 0.5em 0; border-top: 1px solid var(--rule); }
.score-head > * { align-items: flex-end; padding: 0 0 0.3em; border-top: 0; color: var(--muted); }
.score-head + .score-row > * { border-top: 2px solid var(--accent); }
.score-head > :last-child, .score-total { justify-content: flex-end; }
.score-agent { display: block; font-weight: 600; line-height: 1.2; }
.score-agent small { display: block; color: var(--muted); font-weight: 400; }
.score-bar { column-gap: 0.4em; }
.score-bar .minibar { min-width: 0; }
.score-bar b, .score-total { flex: none; width: 3.2em; font-family: var(--mono); font-weight: 500; font-variant-numeric: tabular-nums; text-align: right; }
.score-total { justify-content: flex-end; font-weight: 600; }
.minibar span.s2 { background: var(--pl-ink-600); }
.score-note { color: var(--muted); margin: 0.6em 0 0; }

/* The reading guide: four panels, each a label, a claim, a diagram, and a caption. The diagrams are aria-hidden, so
   each caption states what its diagram shows. print.css stacks the panels down the page, and web.css sets them as
   cards, two to a row where the main column has room. */
.explainer { display: grid; }
.ex-panel { display: grid; align-content: start; }
.ex-text > .label { display: block; }
.ex-claim { font-weight: 600; letter-spacing: -0.01em; color: var(--ink); margin: 0; }
.ex-caption { color: var(--ink-soft); margin: 0; }
.ex-diagram { min-width: 0; }
.ex-k { display: block; color: var(--muted); }
.ex-op { color: var(--muted); font-weight: 600; text-align: center; }
/* Panel 1: an illustrative rubric, a row per criterion, over the score it earns. */
.ex-rubric { border: 1px solid var(--rule); border-radius: 8px; overflow: hidden; }
.ex-head, .ex-crit, .ex-result { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; column-gap: 0.6em; align-items: baseline; }
.ex-head { display: block; background: var(--pl-ink-75); font-family: var(--mono); font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.ex-crit { border-top: 1px solid var(--rule); }
.ex-crit.fail > span:nth-child(2) { color: var(--muted); }
.ex-result { grid-template-columns: minmax(0, 1fr) auto; align-items: center; border-top: 1px solid var(--pl-ink-300); }
.ex-result span { color: var(--muted); }
.ex-result b { font-size: var(--type-h3); font-weight: 700; letter-spacing: -0.03em; line-height: 1; color: var(--accent-text); }
/* Panel 2: the top agent's two measures and its composite score, each on a 0 to 100 track. */
.ex-composite { display: grid; }
.ex-measure { display: grid; grid-template-columns: 8.6em minmax(0, 1fr) 3.4em; column-gap: 0.5em; align-items: center; }
.ex-measure > span:first-child { color: var(--ink-soft); }
.ex-measure b { font-family: var(--mono); font-weight: 500; text-align: right; }
.ex-measure.s2 .minibar span { background: var(--pl-ink-600); }
.ex-measure.total .minibar span { background: var(--mark-focus); }
.ex-measure.total > span:first-child { color: var(--ink); font-weight: 600; }
.ex-measure.total b { font-weight: 700; }
/* Panel 3: model plus harness makes an agent, then three of the paper's agents. */
.ex-eq { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto minmax(0, 1fr); column-gap: 0.4em; align-items: center; }
.ex-chip { border: 1px solid var(--pl-ink-200); background: var(--pl-ink-75); border-radius: 6px; text-align: center; font-weight: 600; color: var(--ink); }
.ex-chip.agent { background: var(--pl-brand-700); border-color: transparent; color: #fff; }
.ex-pairs { display: grid; grid-template-columns: auto auto minmax(0, 1fr); column-gap: 0.45em; }
.ex-pairs > span:not(.ex-op) { color: var(--ink); }
/* Panel 4: one square per held-out item, beside the count. */
.ex-split { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; }
.ex-units { display: block; height: auto; }
.ex-units rect { fill: var(--mark); }
.ex-count b { display: block; font-size: var(--type-stat); font-weight: 700; letter-spacing: -0.03em; line-height: 1; color: var(--ink); }
.ex-count span { display: block; color: var(--muted); }
.ex-pill { grid-column: 1 / -1; justify-self: start; display: inline-block; background: var(--navy); color: #fff; font-family: var(--mono); font-weight: 500; border-radius: 999px; white-space: nowrap; }

/* Stat tiles */
.tiles-grid { display: grid; gap: 1em; }
.stat { border-top: 2px solid var(--accent); padding-top: 0.5em; }
.stat b { display: block; font-weight: 700; letter-spacing: -0.03em; color: var(--accent); line-height: 1.05; }
.stat span { display: block; color: var(--ink-soft); }
.stat a { font-family: var(--mono); color: var(--muted); text-decoration: none; }

/* Callouts, examples, and "why it matters" notes. A note is a callout after the paragraph it annotates. Each of its
   stats is a row under a rule, as the chapter openers' tiles are, its number beside its words. print.css and web.css
   set the notes' spacing. */
.callout { background: var(--navy); color: #fff; border-radius: 12px; margin: 1.4em 0; break-inside: avoid; }
.callout p { margin: 0; font-weight: 500; }
.example { background: var(--panel); border-radius: 12px; break-inside: avoid; margin: 1.2em 0; }
.example .label { color: var(--panel-ink); display: block; margin-bottom: 0.4em; }
.example p { margin: 0; color: var(--ink); }
.why { background: var(--navy); color: #fff; border-radius: 12px; break-inside: avoid; }
.why .label { display: block; letter-spacing: 0.12em; color: var(--pl-brand-400); }
.why .why-stat { display: flex; align-items: center; border-top: 1px solid var(--pl-ink-700); }
.why .why-stat:last-of-type { padding-bottom: 0; }
.why .why-stat b { flex: 0 0 3.2em; color: var(--pl-brand-400); font-weight: 700; letter-spacing: -0.03em; line-height: 1; }
.why .why-stat span { color: var(--pl-ink-200); }
.why p { color: var(--pl-ink-200); }

/* Cards used by lesson and case-study figures */
.cards { display: grid; gap: 0.8em; }
.card { border: 1px solid var(--rule); border-radius: 10px; background: #fff; break-inside: avoid; }
.card h4 { font-weight: 600; letter-spacing: -0.01em; margin: 0 0 0.3em; }
.card .k { font-family: var(--mono); font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-text); display: block; margin-bottom: 0.4em; }
.card p { margin: 0; color: var(--ink-soft); }
.card.panel { background: var(--panel); border-color: transparent; }
.card.panel .k { color: var(--panel-ink); }
.card.dark { background: var(--navy); border-color: transparent; }
.card.dark h4, .card.dark p { color: #fff; }
.card .catch { background: var(--panel); border-radius: 8px; margin-top: 0.6em; }
.card .catch .k { color: var(--panel-ink); }
.chip { display: inline-block; font-weight: 500; background: var(--panel); color: var(--panel-ink); border-radius: 999px; }
.prio { display: inline-block; font-family: var(--mono); font-weight: 600; border-radius: 4px; padding: 0.05em 0.35em; }
.prio.p0 { background: var(--navy); color: #fff; }
.prio.p1 { background: var(--panel); color: var(--panel-ink); }
.prio.p2, .prio.p3 { background: var(--pl-ink-75); color: var(--muted); }
.verdict { font-family: var(--mono); font-weight: 600; }
.verdict.pass { color: var(--pass); }
.verdict.fail { color: var(--fail); }

/* Diff-style document panels (case study) */
.doc { border: 1px solid var(--rule); border-radius: 10px; overflow: hidden; break-inside: avoid; background: #fff; }
.doc-head { background: var(--navy); color: #fff; font-family: var(--mono); }
.doc-head span { display: block; color: var(--pl-brand-400); }
.doc-head span.fail { color: #f2a7a1; }
.doc-body { font-family: var(--mono); }
.doc-line { display: grid; grid-template-columns: 1.4em 1fr auto; column-gap: 0.4em; align-items: start; }
.doc-line.ctx { color: var(--muted); }
.doc-line.add { background: var(--panel); }
.doc-line.add .sign { color: var(--accent-text); }
.doc-line.miss { background: var(--fail-bg); color: var(--fail); border: 1px dashed var(--fail); border-radius: 6px; }
.mark-n { display: inline-flex; align-items: center; justify-content: center; border-radius: 999px; background: var(--fail); color: #fff; font-family: var(--sans); font-weight: 700; }
.hl { background: var(--fail); color: #fff; border-radius: 3px; padding: 0 0.2em; }
.notes-list { list-style: none; padding: 0; margin: 0; }
.notes-list li { display: grid; grid-template-columns: auto 1fr; column-gap: 0.6em; }
.notes-list b { display: block; }
.notes-list span { color: var(--ink-soft); }

/* Checklist */
.checklist { break-inside: avoid; }
.checklist h4 { font-family: var(--mono); font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-text); }
.checklist ul { list-style: none; padding: 0; margin: 0; }
.checklist li { display: grid; grid-template-columns: auto 1fr; column-gap: 0.6em; align-items: start; }
.checklist .box { border: 1.5px solid var(--pl-ink-600); border-radius: 3px; }

/* Question and glossary lists */
.questions dt { font-weight: 600; }
.questions dd { margin: 0; color: var(--ink-soft); }
.glossary { display: grid; grid-template-columns: auto 1fr; column-gap: 1.2em; }
.glossary dt { font-weight: 600; }
.glossary dt::after { content: ":"; }
.glossary dd { margin: 0; color: var(--ink-soft); }

/* Link cards with QR codes */
.links { display: grid; gap: 0.8em; }
.link-card { display: grid; grid-template-columns: auto 1fr; column-gap: 0.9em; align-items: center; border: 1px solid var(--rule); border-radius: 10px; break-inside: avoid; }
.link-card svg { display: block; }
.link-card b { display: block; }

/* Contributors */
.person { display: grid; grid-template-columns: 11em minmax(0, 1fr); column-gap: 0.9em; border-top: 1px solid var(--rule); padding: 0.4em 0; }
.person:first-child { border-top: 2px solid var(--accent); }
.person b { font-weight: 600; }
.person b:only-child { grid-column: 1 / -1; }
.person span { color: var(--muted); }

/* SVG chart marks. Dots carry a 2 px surface ring; axes are recessive and the charts draw no gridlines. */
.fig svg .dot { fill: var(--mark); stroke: #fff; stroke-width: 2; }
.fig svg .dot-base { fill: var(--mark-base); stroke: #fff; stroke-width: 2; }
.fig svg .gap { fill: var(--pl-brand-100); }
.fig svg .gap-text { fill: var(--panel-ink); }
.fig svg .strip { fill: var(--track); }
.fig svg .tick-mark { fill: var(--mark); }
.fig svg .leader { stroke: var(--pl-ink-400); stroke-width: 1.5; }
.fig svg .axis { stroke: var(--pl-ink-300); stroke-width: 1.5; }
.fig svg .target { stroke: var(--ink); stroke-width: 3; }
.fig svg .whisker { stroke: var(--mark); stroke-width: 6; stroke-linecap: round; }
.fig svg .link { stroke: var(--mark-muted); stroke-width: 5; stroke-linecap: round; }
.fig svg .node { fill: #fff; stroke: var(--pl-ink-200); stroke-width: 1.5; }
.fig svg .focus .node { fill: var(--panel); stroke: var(--pl-brand-300); }
.fig svg .edge { stroke: var(--pl-ink-400); stroke-width: 2; fill: none; }
.fig svg .ahead { fill: var(--pl-ink-400); }
/* Figure 1.2: the repository is context, not a step, so its box and arrow are dashed and its tag replaces a number.
   The tag's ink-600 text on ink-150 is 6.8:1, and the asterisk's brand-600 on white is 6.0:1. */
.fig svg .context .node { fill: var(--pl-ink-50); stroke: var(--pl-ink-400); stroke-dasharray: 5 4; }
.fig svg .edge.dashed { stroke-dasharray: 5 4; }
.fig svg .tag { fill: var(--pl-ink-150); }
.fig svg .tag-text { fill: var(--pl-ink-600); font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; }
.fig svg .star { fill: var(--accent-text); font-style: normal; font-weight: 700; }
.fig svg .footnote { font-style: italic; }

/* Figure layouts */
.tiles-grid.glance { grid-template-columns: 1fr; gap: 0; }
/* The glance stats are a ledger: each number sits in a fixed column beside its words, as in the "why it matters"
   notes, and its page reference sits at the right, as in the contents, so captions of any length keep every row
   aligned. */
.glance .stat { display: grid; grid-template-columns: calc(3.4 * var(--type-stat)) minmax(0, 1fr) auto; column-gap: 0.9em; align-items: start; border-top: 1px solid var(--rule); padding: 0.55em 0; }
.glance .stat:first-child { border-top: 2px solid var(--accent); }
.glance .stat a { font-family: var(--sans); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; line-height: var(--leading-body); }
.tiles-grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cards.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* The case study's four stages: a 2 x 2 grid in reading order. Each card spans three rows of the grid, for its heading,
   its failure, and its catch, so those parts line up across a row and the two cards in a row share a height. */
.cards.stages { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cards.stages .card { display: grid; grid-row: span 3; grid-template-rows: subgrid; row-gap: 0; }
.cards.two-uneven { grid-template-columns: 0.85fr 1.15fr; }
dl.mini { margin: 0; }
dl.mini dt { font-weight: 600; margin-top: 0.55em; }
dl.mini dd { margin: 0; color: var(--ink-soft); }
.card.panel dl.mini dt { color: var(--ink); }
ol.path { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.7em; }
ol.path li { margin: 0; }
ul.chips { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 0.5em; }
ul.chips li { margin: 0; }
.rubric-list { list-style: none; padding: 0; margin: 0.4em 0 0.7em; }
.rubric-list li { display: grid; grid-template-columns: 5.6em 1fr; column-gap: 0.6em; margin-bottom: 0.4em; align-items: baseline; }
/* The people are a ledger, like the glance stats: each group is a label over rows, one person a row, the name
   beside the affiliation. */
.provenance { display: grid; row-gap: 1.1em; }
.provenance .label { display: block; margin-bottom: 0.35em; }
:is(table.leaderboard, table.cloud-table) th[scope="row"] .agent { display: block; font-weight: 600; white-space: nowrap; }
:is(table.leaderboard, table.cloud-table) th[scope="row"] small { display: block; color: var(--muted); font-weight: 400; }
table.leaderboard td.rank { color: var(--muted); }
:is(table.leaderboard, table.cloud-table) td.composite { font-weight: 700; }
:is(table.leaderboard, table.cloud-table) :is(tbody th, tbody td) { vertical-align: middle; }
.nowrap { white-space: nowrap; }
.minibar { flex: 1; height: var(--bar-h); background: var(--track); position: relative; }
.minibar span { position: absolute; left: 0; top: 0; bottom: 0; background: var(--mark); }
.minibar span:not(.w-0) { min-width: 2px; }
/* The cloud-agent table sets its reference row apart under its own label, in the text's softer ink. */
table.cloud-table tr.group td { padding-top: 1.1em; padding-bottom: 0.2em; border-bottom: 1px solid var(--pl-ink-300); }
table.cloud-table tr.reference > * { color: var(--ink-soft); }
table.cloud-table tr.reference td.composite { font-weight: 400; }
table.cloud-table th[scope="row"] small { white-space: nowrap; }
.cloud-notes { margin: 0.7em 0 0; padding-left: 1.1em; color: var(--muted); }
.cloud-notes li { margin-bottom: 0.2em; }
.steps-table th[scope="row"] { width: 32%; }
.steps-table th[scope="row"] small { display: block; color: var(--muted); font-weight: 400; margin-top: 1pt; }
.steps-table th[scope="row"] small.lesson { color: var(--accent-text); margin-top: 0; }
.pants-flow { background: var(--panel); border-radius: 12px; }
.pf-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.8em; }
.pf-head span { color: var(--muted); }
.pf-grid { display: grid; grid-template-columns: 1.5fr auto 0.9fr auto 1.2fr; align-items: center; column-gap: 0.7em; }
.pf-shards { display: grid; row-gap: 0.4em; }
.pf-shard { display: grid; grid-template-columns: auto auto 1fr; column-gap: 0.5em; align-items: center; }
.pf-id { background: var(--navy); color: #fff; font-family: var(--mono); border-radius: 5px; padding: 0.2em 0.5em; }
.pf-file { background: #fff; border: 1px solid var(--rule); font-family: var(--mono); border-radius: 5px; padding: 0.2em 0.5em; }
.pf-v { font-family: var(--mono); font-weight: 600; }
.pf-arrow { color: var(--accent-text); font-weight: 700; }
.pf-combine { background: #fff; border: 1px solid var(--rule); border-radius: 8px; padding: 0.6em; text-align: center; font-weight: 500; }
.pf-result { display: grid; row-gap: 0.4em; }
.pf-report { background: #fff; border: 1px solid var(--rule); border-radius: 8px; padding: 0.5em; text-align: center; font-weight: 600; }
.pf-pass { background: var(--pl-brand-700); color: #fff; border-radius: 8px; padding: 0.5em; text-align: center; font-weight: 600; }
.pf-rules { display: grid; grid-template-columns: 1fr 1fr; column-gap: 1.2em; margin-top: 0.9em; }
.pf-rules p { margin: 0; color: var(--ink-soft); }
.docs-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8em; align-items: start; }
.doc-notes .notes-list { margin-top: 0.8em; }
.web-only { }
@media print { .web-only { display: none; } }

/* Before-and-after dots: the "before" mark is a ring, so the pair differs in shape as well as color. */
.fig svg .dot-ring { fill: #fff; stroke: var(--pl-ink-600); stroke-width: 3; }
.card h4 .k { display: block; margin-bottom: 0.35em; }
mark.hl { background: var(--fail); color: #fff; border-radius: 3px; padding: 0 0.2em; }
