*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.65 var(--font-body);
  overflow-x: hidden;
}
h1, h2, h3 { font-family: var(--font-display); color: var(--text-strong); line-height: 1.25; margin: 0 0 var(--space-3); font-weight: 700; }
h1 { font-size: clamp(2rem, 5vw, 3.2rem); letter-spacing: -0.01em; }
h2 { font-size: 1.45rem; }
h3 { font-size: 1.1rem; font-weight: 500; }
p { margin: 0 0 var(--space-3); }
a { color: var(--link); text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; border-radius: 4px; }

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--space-4); }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: var(--space-4); top: var(--space-2); background: var(--surface); padding: var(--space-2) var(--space-3); z-index: 10; }
.muted { color: var(--muted); }

/* Header */
.site-header { border-bottom: 1px solid var(--border); background: var(--header-bg); position: sticky; top: 0; z-index: 5; }
.header-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding-top: var(--space-3); padding-bottom: var(--space-2); }
.brand { display: inline-flex; align-items: center; gap: var(--space-3); text-decoration: none; color: var(--text-strong); font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; }
.seal { width: 36px; height: 36px; flex: none; }
.seal rect { fill: var(--seal-bg); }
.seal text { fill: var(--seal-text); font: 700 15px var(--font-display); }
.header-tools { display: flex; align-items: center; gap: var(--space-2); }
.lang { font-size: 0.9rem; font-weight: 500; padding: 6px 10px; border-radius: var(--radius); text-decoration: none; border: 1px solid var(--border-strong); color: var(--text); }
.theme-toggle { width: 38px; height: 38px; border-radius: var(--radius); border: 1px solid var(--border-strong); background: transparent; color: var(--text); cursor: pointer; display: grid; place-items: center; }
.theme-toggle svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.site-nav { display: flex; gap: var(--space-1); overflow-x: auto; padding-bottom: var(--space-2); scrollbar-width: none; }
.site-nav::-webkit-scrollbar { display: none; }
/* On a phone the five tabs wrap onto two lines rather than hide behind a scroll (remark of Charles). */
@media (max-width: 600px) { .site-nav { flex-wrap: wrap; overflow: visible; row-gap: 0; } }
.site-nav a { display: inline-flex; align-items: center; min-height: 44px; white-space: nowrap; padding: 6px 12px; border-radius: 999px; text-decoration: none; color: var(--text); font-size: 0.95rem; }
.site-nav a:hover { background: var(--surface-2); }
.site-nav a[aria-current="page"] { background: var(--accent); color: var(--on-accent); font-weight: 500; }

/* Hero and page heads */
.hero { padding: var(--space-7) 0 var(--space-6); }
.page-head { padding: var(--space-6) 0 var(--space-4); }
.kicker { color: var(--muted); font-weight: 500; letter-spacing: 0.02em; margin-bottom: var(--space-2); }
.lead { font-size: 1.15rem; max-width: 62ch; }
.actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-4); }
.btn { font: inherit; border: 0; background: none; cursor: pointer; display: inline-flex; align-items: center; min-height: 44px; padding: 10px 18px; border-radius: var(--radius); font-weight: 500; text-decoration: none; }
.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { filter: brightness(0.95); }
.btn-ghost { border: 1px solid var(--border-strong); color: var(--text); }
.btn-ghost:hover { background: var(--surface-2); }

/* Temporary progress panel (D14) */
.progress-panel { margin-bottom: var(--space-5); display: grid; gap: var(--space-3); }
.progress-panel h2 { margin-bottom: 0; font-size: 1.15rem; }
.progress-panel > .meta { margin: 0; }
.progress-head { display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--space-2); font-weight: 500; margin-bottom: var(--space-1); }
.progress-bar { position: relative; height: 10px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.progress-fill { position: absolute; inset: 0 auto 0 0; width: var(--w); background: var(--bar); border-radius: 999px; }
.progress-soft { background: var(--tag-bg); outline: 1px solid var(--bar); outline-offset: -1px; }

/* Stats */
.stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: var(--space-6); }
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-4); }
.stat strong { display: block; font: 700 2rem/1.1 var(--font-display); color: var(--text-strong); }
.stat span { color: var(--muted); font-size: 0.95rem; }

/* Panels and layout */
.split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); margin-bottom: var(--space-6); }
.panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-5); }
.panel-accent { border-left: 6px solid var(--accent); border-radius: 0 var(--radius-lg) var(--radius-lg) 0; }
.block { margin-bottom: var(--space-6); }
.summary { font-size: 1.05rem; max-width: 70ch; }
.notice { background: var(--surface-2); border-left: 4px solid var(--accent); padding: var(--space-3) var(--space-4); max-width: 75ch; }
.label { font-weight: 600; margin: var(--space-4) 0 var(--space-2); color: var(--text-strong); }
.plain { list-style: none; padding: 0; margin: 0; }
.plain li { margin-bottom: var(--space-1); }

/* Cards */
.chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-4); }
.filters { margin-bottom: var(--space-4); }
.filter-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.filter-row .chips { margin-bottom: var(--space-2); }
.filter-label { min-width: 6.5rem; font-weight: 600; color: var(--muted); margin-bottom: var(--space-2); }
.chip { min-height: 44px; padding: 6px 14px; border-radius: 999px; border: 1px solid var(--border-strong); background: transparent; color: var(--text); font: 500 0.9rem var(--font-body); cursor: pointer; }
.chip[aria-pressed="true"] { background: var(--pressed-bg); color: var(--pressed-text); border-color: var(--pressed-bg); }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-4); margin-bottom: var(--space-6); }
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-5); display: flex; flex-direction: column; }
.card[hidden] { display: none; }
.card { position: relative; }
.card h3 { margin-top: var(--space-3); }
.card h3 a { color: var(--text-strong); text-decoration: none; }
.card h3 a::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius-lg); }
.card:hover h3 a { text-decoration: underline; }
.card:focus-within { outline: 3px solid var(--link); outline-offset: 2px; }
.card h3 a:focus-visible { outline: none; }
.card-top { display: flex; justify-content: space-between; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.card-note { color: var(--muted); font-size: 0.92rem; font-style: italic; }
.meta { color: var(--muted); font-size: 0.85rem; }
.badge { display: inline-block; font-size: 0.78rem; font-weight: 600; padding: 2px 10px; border-radius: 999px; }
.badge-planned { background: var(--surface-2); color: var(--muted); }
.badge-in-progress { background: var(--risk-medium); color: var(--risk-medium-text); }
.badge-done { background: var(--risk-low); color: var(--risk-low-text); }
.tags { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; padding: 0; margin: auto 0 0; padding-top: var(--space-3); }
.tags li { background: var(--tag-bg); color: var(--tag-text); font-size: 0.8rem; padding: 2px 10px; border-radius: 999px; }

/* Project detail */
.crumb { margin: var(--space-4) 0 0; }
.crumb a { display: inline-flex; align-items: center; min-height: 44px; }
.project-meta { justify-content: flex-start; margin-bottom: var(--space-4); }
.pager { justify-content: space-between; margin-bottom: var(--space-6); }
.pager [rel="next"] { margin-left: auto; }

/* lib-c demo (D15) */
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.file-pick { cursor: pointer; }
.file-pick:focus-within { outline: 3px solid var(--link); outline-offset: 2px; }
.drop { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-4); border: 2px dashed var(--border-strong); border-radius: var(--radius-lg); }
.drop.is-over { border-color: var(--accent); background: var(--tag-bg); }
.demo .actions { align-items: center; }
.demo-samples { margin-right: var(--space-1); }
.demo-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--space-2) var(--space-4); margin: var(--space-3) 0; }
.demo-stats div { background: var(--surface-2); border-radius: var(--radius); padding: var(--space-2) var(--space-3); }
.demo-stats dt { color: var(--muted); font-size: 0.85rem; }
.demo-stats dd { margin: 0; font: 600 1.1rem var(--font-mono); color: var(--text-strong); overflow-wrap: anywhere; }
.demo-stats div:has([data-field="bbox"]) { grid-column: 1 / -1; }
.demo [data-result] { margin-top: var(--space-4); }

/* SQL playground (D20) */
.sql-label { display: block; margin-top: var(--space-4); font-weight: 600; color: var(--text-strong); }
.sql-editor { display: block; box-sizing: border-box; width: 100%; min-height: 10rem; margin-top: var(--space-2); padding: var(--space-3); resize: vertical;
  font: 0.95rem/1.5 var(--font-mono); color: var(--text-strong); background: var(--surface-2); border: 1px solid var(--border-strong); border-radius: var(--radius); }
.sql-editor:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }
.sqlplay [data-result] .table-wrap { max-height: 28rem; overflow: auto; }
.sqlplay [data-result] .table-wrap:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }
.sqlplay td { white-space: nowrap; font-family: var(--font-mono); font-size: 0.85rem; padding: 6px 12px; }
.sqlplay td.num { text-align: right; }
.sqlplay thead th { position: sticky; top: 0; padding: 6px 12px; font-size: 0.85rem; }
.sql-schema { margin-top: var(--space-4); }
.sql-schema summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; font-weight: 600; }
.sql-schema li { overflow-wrap: anywhere; margin-bottom: var(--space-1); }

/* Maille playground (D22): result line and syntax tree as nested lists. */
.maille-result { font: 600 1rem var(--font-mono); color: var(--text-strong); overflow-wrap: anywhere; min-height: 1.5em; }
.mailleplay .demo-error .btn { margin-top: var(--space-2); }
.maille-tree { margin-top: var(--space-4); }
.maille-tree summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; font-weight: 600; }
.mailleplay [data-tree] { max-height: 32rem; overflow: auto; }
.ast, .ast ul { list-style: none; margin: 0; padding-left: var(--space-4); }
.ast { padding-left: 0; }
.ast ul { border-left: 1px solid var(--border-strong); margin-left: 6px; }
.ast-node { display: inline-flex; align-items: baseline; gap: 6px; min-height: 32px; padding: 2px 6px; border: 0; border-radius: var(--radius);
  background: none; color: var(--text); font: 0.9rem var(--font-mono); cursor: pointer; text-align: left; overflow-wrap: anywhere; }
.ast-node:hover { background: var(--surface-2); }
.ast-node:focus-visible { outline: 3px solid var(--link); outline-offset: 1px; }
.ast-kind { color: var(--text-strong); font-weight: 600; }
.ast-node code { background: var(--tag-bg); color: var(--tag-text); padding: 0 4px; border-radius: 3px; }

/* Live LaTeX editor (D23): source and preview side by side, one at a time on a narrow screen. */
.latex-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-4); margin-top: var(--space-3); }
.latex-pane { display: flex; flex-direction: column; min-width: 0; }
.latex-pane .sql-label { margin-top: 0; }
.latex-source .sql-editor { flex: 1; height: 70vh; min-height: 20rem; resize: none; font-size: 0.85rem; }
.latex-preview { position: relative; height: 70vh; min-height: 20rem; overflow: auto; margin-top: var(--space-2); padding: var(--space-4); border: 1px solid var(--border-strong);
  border-radius: var(--radius); background: var(--bg); color: var(--text); overflow-wrap: anywhere; }
.latex-preview:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }
.latex-tabs { display: none; }
.latex-side { margin-top: var(--space-4); margin-bottom: 0; }
.latex-side h3 { margin-bottom: var(--space-2); }
[data-status][data-state="error"] { color: var(--risk-high-text); }
.latex-diags li, .latex-outline li { margin: 0; }
.diag, .outline-link { display: block; width: 100%; min-height: 44px; padding: 6px 8px; border: 0; border-radius: var(--radius); background: none;
  color: var(--text); font: inherit; text-align: left; cursor: pointer; overflow-wrap: anywhere; }
.diag:hover, .outline-link:hover { background: var(--surface-2); }
.diag:focus-visible, .outline-link:focus-visible { outline: 3px solid var(--link); outline-offset: 1px; }
.diag-kind { font-weight: 600; }
.diag-error .diag-kind { color: var(--risk-high-text); }
.diag-warning .diag-kind { color: var(--risk-medium-text); }
.outline-2 .outline-link { padding-left: var(--space-5); }
.outline-3 .outline-link { padding-left: calc(2 * var(--space-5)); }
@media (max-width: 900px) {
  .latex-tabs { display: flex; }
  .latex-grid { grid-template-columns: minmax(0, 1fr); }
  .latexed[data-view="preview"] .latex-source, .latexed[data-view="source"] .latex-preview-pane { display: none; }
}
/* The rendered article. */
.latex-preview .tex-title h3 { font-size: 1.5rem; margin: 0 0 var(--space-2); }
.latex-preview h4 { font-size: 1.25rem; margin: var(--space-5) 0 var(--space-2); }
.latex-preview h5 { font-size: 1.1rem; margin: var(--space-4) 0 var(--space-2); }
.latex-preview h6 { font-size: 1rem; margin: var(--space-3) 0 var(--space-2); }
.latex-preview p { margin: 0 0 var(--space-3); max-width: none; }
.tex-num { color: var(--muted); margin-right: 0.3em; }
.tex-title { text-align: center; margin-bottom: var(--space-4); }
.tex-author, .tex-date { margin: 0; color: var(--muted); }
.tex-abstract { margin: 0 var(--space-4) var(--space-4); font-size: 0.95rem; }
.tex-abstract-title, .tex-toc-title, .tex-notes-title { font-weight: 600; color: var(--text-strong); text-align: center; margin-bottom: var(--space-2); }
.tex-toc ol { list-style: none; padding: 0; }
.tex-toc-2 { padding-left: var(--space-4); }
.tex-toc-3 { padding-left: calc(2 * var(--space-4)); }
.tex-display { overflow-x: auto; overflow-y: hidden; margin: var(--space-3) 0; }
.tex-table { overflow-x: auto; margin: var(--space-3) 0; }
.tex-table table { width: auto; font-size: 0.9rem; }
.tex-table td { padding: 4px 10px; border: 0; }
.tex-table tr.tex-rule td { border-top: 1px solid var(--border-strong); }
.tex-logo { font-family: serif; }
.tex-logo .tex-a { font-size: 0.75em; vertical-align: 0.25em; margin: 0 -0.3em 0 -0.35em; }
.tex-logo .tex-e { vertical-align: -0.5ex; margin: 0 -0.1em 0 -0.15em; }
.tex-sc { font-variant: small-caps; }
.tex-undefined, .tex-unknown, .tex-error { color: var(--risk-high-text); }
.tex-notes { border-top: 1px solid var(--border-strong); margin-top: var(--space-5); padding-top: var(--space-3); font-size: 0.9rem; }
.tex-bib ol { padding-left: var(--space-5); }

/* Generalized maps course (D24): the cube net and the quiz. */
.gm-lesson h3 { margin-top: var(--space-5); }
.gm-lesson code, .gm-course legend code { font-family: var(--font-mono); }
.gm-figure { margin: var(--space-5) 0; }
.gm-net { display: block; width: 100%; max-width: 720px; height: auto; margin: 0 auto; }
.gm-paper .gm-bg { fill: var(--gm-paper); }
.gm-square rect, .gm-face-fill { fill: var(--gm-paper); stroke: var(--gm-face-stroke); stroke-width: 1; }
.gm-face { fill: var(--gm-label); font: 600 11px var(--font-body); pointer-events: none; }
.gm-letter { fill: var(--gm-ink); font: 600 10px var(--font-mono); pointer-events: none; }
.gm-side { stroke: var(--gm-ink); stroke-width: 2.5; stroke-linecap: round; }
.gm-vertex { fill: var(--gm-ink); }
.gm-dart-line { stroke: var(--gm-ink); stroke-width: 2.2; stroke-linecap: round; }
.gm-dart-dot { fill: var(--gm-ink); }
.gm-dart { cursor: pointer; }
.gm-dart line { stroke: var(--gm-ink); stroke-width: 2.2; stroke-linecap: round; }
.gm-dart circle { fill: var(--gm-ink); }
.gm-dart .gm-hit { stroke: transparent; stroke-width: 12; }
.gm-dart.in-orbit line:not(.gm-hit) { stroke: var(--gm-orbit); stroke-width: 3.2; }
.gm-dart.in-orbit circle { fill: var(--gm-orbit); }
.gm-dart.is-current line:not(.gm-hit) { stroke: var(--gm-current); stroke-width: 4; }
.gm-dart.is-current circle { fill: var(--gm-current); r: 4; }
.gm-static { stroke-width: 1.4; stroke-linecap: round; fill: none; }
.gm-link { stroke-width: 2.4; stroke-dasharray: 5 3; stroke-linecap: round; fill: none; }
.gm-l0, .gm-a0 { --gm: var(--gm-a0); }
.gm-l1, .gm-a1 { --gm: var(--gm-a1); }
.gm-l2, .gm-a2 { --gm: var(--gm-a2); }
.gm-static, .gm-link { stroke: var(--gm); }
.gm-alpha { border-left: 6px solid var(--gm); }
.gm-decompose .gm-step-svg { display: block; width: 100%; max-width: 520px; height: auto; margin: var(--space-3) auto 0; }
.gm-step-caption { max-width: 520px; margin: var(--space-2) auto 0; }
.gm-status { min-height: 1.5em; font-weight: 600; color: var(--text-strong); }
.gm-quiz { margin-top: var(--space-6); }
.gm-question { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3) var(--space-4); margin: 0 0 var(--space-3); }
.gm-question legend { font-weight: 600; color: var(--text-strong); padding: 0 var(--space-1); }
.gm-option { display: flex; align-items: center; gap: var(--space-2); min-height: 44px; cursor: pointer; }
.gm-option input { width: 20px; height: 20px; accent-color: var(--accent); }
.gm-feedback { font-weight: 600; margin: var(--space-2) 0 0; }
.gm-feedback[data-state="ok"] { color: var(--risk-low-text); }
.gm-feedback[data-state="ko"] { color: var(--risk-high-text); }
.gm-score { font-weight: 600; color: var(--text-strong); }

/* ML results (D27): confusion matrices with the risk badge colours (already contrast-checked):
   right answers in green, errors in red, zeros muted. */
.confusion caption { text-align: left; font-weight: 600; color: var(--text-strong); padding-bottom: var(--space-2); }
.confusion th, .confusion td { padding: 6px 8px; font-size: 0.85rem; }
.confusion td.cm { color: var(--muted); }
.confusion td.cm-diag { background: var(--risk-low); color: var(--risk-low-text); font-weight: 700; }
.confusion td.cm-off { background: var(--risk-high); color: var(--risk-high-text); font-weight: 700; }
.ml-confusions { margin-top: var(--space-4); }

/* Othello (D28): a green felt board. Below 560 px the coordinates are hidden (each square's label still
   names it) and the board takes the viewport width minus 8 px, centred on the viewport: at 375 px a
   square is 44.5 px wide. */
.oth-controls { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-5); }
.oth-colour { border: 0; padding: 0; margin: 0; }
.oth-colour legend { font-weight: 600; color: var(--text-strong); padding: 0; }
.oth-colour label { display: inline-flex; align-items: center; gap: var(--space-1); min-height: 44px; margin-right: var(--space-3); cursor: pointer; }
.oth-colour input { width: 20px; height: 20px; accent-color: var(--accent); }
.oth-level { display: flex; flex-direction: column; gap: var(--space-1); font-weight: 600; color: var(--text-strong); }
.oth-level select { min-height: 44px; padding: 0 var(--space-2); font: inherit; color: var(--text-strong); background: var(--surface-2); border: 1px solid var(--border-strong); border-radius: var(--radius); }
.oth-status { min-height: 1.5em; font-weight: 600; color: var(--text-strong); margin-top: var(--space-3); }
.oth-wrap { --oth-size: min(480px, calc(100vw - 8px)); width: var(--oth-size); position: relative; left: 50%; transform: translateX(-50%); }
.oth-files { display: grid; grid-template-columns: 18px repeat(8, 1fr); font: 600 0.8rem var(--font-mono); color: var(--muted); text-align: center; }
.oth-files::before { content: ""; }
.oth-inner { display: grid; grid-template-columns: 18px 1fr; }
.oth-ranks { display: grid; grid-template-rows: repeat(8, 1fr); font: 600 0.8rem var(--font-mono); color: var(--muted); align-items: center; }
.oth-board { display: grid; grid-template-columns: repeat(8, 1fr); aspect-ratio: 1; background: var(--oth-line); border: 2px solid var(--oth-line); gap: 1px; border-radius: 4px; }
.oth-cell { position: relative; min-width: 0; min-height: 0; padding: 0; border: 0; background: var(--oth-felt); cursor: default; }
.oth-cell.is-legal { cursor: pointer; }
.oth-cell::after { content: ""; position: absolute; inset: 12%; border-radius: 50%; }
.oth-cell[data-disc="black"]::after { background: var(--oth-black); box-shadow: inset 0 -3px 0 var(--oth-black-shade); }
.oth-cell[data-disc="white"]::after { background: var(--oth-white); box-shadow: inset 0 -3px 0 var(--oth-white-shade); }
.oth-cell.is-legal::after { inset: 40%; background: var(--oth-hint); }
.oth-cell.is-last { box-shadow: inset 0 0 0 3px var(--oth-last); }
.oth-cell:focus-visible { outline: 3px solid var(--link); outline-offset: -3px; z-index: 1; }
.othello .oth-wrap + .meta { margin-top: var(--space-3); }
@media (max-width: 560px) {
  .oth-files, .oth-ranks { display: none; }
  .oth-inner { grid-template-columns: 1fr; }
}

/* Tic-tac-toe (D34): reuses the Othello controls; a 3 x 3 grid of buttons, X in the text colour and O in the
   link colour (pistachio on dark, bamboo on light), the winning line underlined by the link colour. */
.ttt-board { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; width: min(300px, 100%); aspect-ratio: 1; margin-top: var(--space-3); }
.ttt-cell { min-width: 44px; min-height: 44px; padding: 0; font: 700 clamp(2rem, 9vw, 3rem)/1 var(--font-display); color: var(--text-strong);
  background: var(--surface-2); border: 1px solid var(--border-strong); border-radius: var(--radius); cursor: default; }
.ttt-cell.is-legal { cursor: pointer; }
.ttt-cell.is-legal:hover { border-color: var(--link); }
.ttt-cell[data-mark="O"] { color: var(--link); }
.ttt-cell.is-last { box-shadow: inset 0 0 0 2px var(--border-strong); }
.ttt-cell.is-win { box-shadow: inset 0 0 0 3px var(--link); }
.ttt-cell:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }

/* Battleship screenshot (D29): scales down with the page. */
.naval-shot { margin: var(--space-4) 0; }
.naval-shot img { display: block; width: 100%; max-width: 716px; height: auto; border: 1px solid var(--border-strong); border-radius: var(--radius); }
.naval-run { overflow-x: auto; background: var(--surface-2); padding: var(--space-3); border-radius: var(--radius); }
/* A code block may scroll sideways on a phone: it takes the focus so the keyboard can scroll it too. */
.naval-run:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }

/* Text adventure (D30): a terminal-like log and a command line. */
.adv-log { height: 22rem; overflow-y: auto; padding: var(--space-3); background: var(--bg); border: 1px solid var(--border-strong); border-radius: var(--radius);
  font: 0.9rem/1.5 var(--font-mono); color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.adv-log:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }
.adv-log p { margin: 0 0 var(--space-2); max-width: none; }
.adv-command { color: var(--accent); font-weight: 600; }
.adv-error { color: var(--risk-high-text); }
.adv-form { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-3); }
.adv-prompt { font: 600 1rem var(--font-mono); color: var(--accent); }
.adv-form input { flex: 1; min-width: 0; min-height: 44px; padding: 0 var(--space-3); font: 0.95rem var(--font-mono); color: var(--text-strong);
  background: var(--surface-2); border: 1px solid var(--border-strong); border-radius: var(--radius); }
.adv-form input:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }

/* Topology viewer (D17) */
.viewer-grid { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--space-4); margin-top: var(--space-4); }
.viewer-stage { position: relative; min-width: 0; border-radius: var(--radius-lg); background: var(--surface-2); overflow: hidden; }
.viewer-stage canvas { display: block; width: 100%; aspect-ratio: 4 / 3; max-height: 520px; touch-action: none; cursor: grab; }
.viewer-tip { position: absolute; pointer-events: none; background: var(--bg); color: var(--text-strong); border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 2px 8px; font: 500 0.85rem var(--font-mono); white-space: nowrap; }
.viewer-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 0; }
.viewer .btn[aria-pressed="true"] { background: var(--pressed-bg); color: var(--pressed-text); border-color: var(--pressed-bg); }
.legend { margin: var(--space-3) 0; }
.legend-bar { height: 10px; border-radius: 999px; background: linear-gradient(to right, var(--curv-neg), var(--curv-zero), var(--curv-pos)); }
.legend-ticks { position: relative; height: 1.4em; font-size: 0.8rem; margin-top: var(--space-1); font-variant-numeric: tabular-nums; }
.legend-ticks span { position: absolute; transform: translateX(-50%); white-space: nowrap; }
.legend-ticks span:first-child { transform: none; }
.legend-ticks span:last-child { transform: translateX(-100%); }
.legend-note { margin: var(--space-1) 0 0; }
.legend-scale { display: flex; justify-content: space-between; font-size: 0.85rem; margin-top: var(--space-1); font-variant-numeric: tabular-nums; }
/* minmax(0, ...): a wide child (the table of persistence pairs) scrolls in its frame instead of widening the page. */
@media (max-width: 720px) { .viewer-grid { grid-template-columns: minmax(0, 1fr); } }
/* Topology viewer (Charles's review): the mesh stays in sight, on the left, while the diagrams scroll by on the right.
   The stage no longer stretches to the column's height (a tall empty panel), and sticks under the site header. */
@media (min-width: 721px) {
  [data-topo-viewer] .viewer-grid { align-items: start; }
  [data-topo-viewer] .viewer-stage { position: sticky; top: calc(var(--header-h, 64px) + var(--space-3)); }
  [data-topo-viewer] .viewer-stage canvas { max-height: calc(100vh - var(--header-h, 64px) - 2 * var(--space-4)); }
}

/* Timelines */
.timeline { list-style: none; padding: 0; margin: 0; border-left: 2px solid var(--accent); }
.timeline > li { display: grid; grid-template-columns: 120px 1fr; gap: var(--space-4); padding: 0 0 var(--space-5) var(--space-4); position: relative; }
.timeline > li::before { content: ""; position: absolute; left: -7px; top: 8px; width: 12px; height: 12px; border-radius: 50%; background: var(--bg); border: 2px solid var(--dot); }
.timeline h3 { margin-bottom: var(--space-1); }
.timeline p { margin-bottom: var(--space-1); }
.timeline.compact > li { padding-bottom: var(--space-3); }
/* Research page: professional experience and education side by side, each on its own line (period above). */
.paths .timeline > li { grid-template-columns: 1fr; gap: var(--space-1); }
.paths [data-timeline="experience"] { border-left-color: var(--gantt-build); }
.tl-period { font-weight: 600; color: var(--text-strong); font-variant-numeric: tabular-nums; }
.thesis-title { font-size: 1.2rem; }

/* Publications */
.pubs { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-3); }
.pubs li { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-4); }
.pub-type { font-size: 0.82rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.pub-title { font-weight: 500; color: var(--text-strong); margin: var(--space-1) 0; }
.pubs .muted { margin: 0; font-size: 0.92rem; }

/* Tables */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); }
table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
th, td { text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--border); vertical-align: top; }
thead th { background: var(--surface-2); font-weight: 600; color: var(--text-strong); white-space: nowrap; }
tbody th { font-weight: 500; }
tfoot th, tfoot td { font-weight: 700; border-bottom: none; color: var(--text-strong); }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cell-sub { display: block; font-size: 0.82rem; font-weight: 400; }
tr[hidden] { display: none; }
.bar { display: inline-block; vertical-align: middle; height: 8px; width: calc(var(--w) * 0.6); max-width: 60px; background: var(--bar); border-radius: 4px; margin-right: 8px; }
.score { display: inline-block; min-width: 28px; text-align: center; font-weight: 700; border-radius: 6px; padding: 1px 6px; }
/* Risk register (method page): sortable headers and the probability-impact matrix of each risk. */
.risks th .sort { display: inline-flex; align-items: center; gap: 4px; min-height: 44px; padding: 0; border: 0; background: none;
  font: inherit; color: inherit; cursor: pointer; white-space: nowrap; }
.risks th .sort:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }
.risks th.num .sort { margin-left: auto; }
.sort-mark::after { content: "↕"; color: var(--muted); }
th[aria-sort="ascending"] .sort-mark::after { content: "▲"; color: inherit; }
th[aria-sort="descending"] .sort-mark::after { content: "▼"; color: inherit; }
.risk-matrix { display: inline-grid; grid-template-columns: repeat(3, 14px); gap: 2px; padding: 3px; border-left: 2px solid var(--border-strong); border-bottom: 2px solid var(--border-strong); vertical-align: middle; }
.risk-matrix .cell { width: 14px; height: 14px; border-radius: 2px; opacity: 0.45; }
.risk-matrix .cell.score-high { background: var(--risk-high-text); }
.risk-matrix .cell.score-medium { background: var(--risk-medium-text); }
.risk-matrix .cell.score-low { background: var(--risk-low-text); }
.risk-matrix .cell.is-risk { opacity: 1; }
.risk-matrix .cell.is-risk { box-shadow: 0 0 0 2px var(--text-strong); position: relative; }
.risk-matrix .cell.is-risk::after { content: ""; position: absolute; inset: 4px; border-radius: 50%; background: var(--text-strong); }
.score-high { background: var(--risk-high); color: var(--risk-high-text); }
.score-medium { background: var(--risk-medium); color: var(--risk-medium-text); }
.score-low { background: var(--risk-low); color: var(--risk-low-text); }

/* Gantt */
.gantt { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-4); }
.gantt-row { display: grid; grid-template-columns: minmax(180px, 34%) 1fr; gap: var(--space-3); align-items: center; padding: 6px 0; border-bottom: 1px dashed var(--border); }
.gantt-row:last-child { border-bottom: none; }
.gantt-label { font-size: 0.92rem; }
/* minmax(0, 1fr): a column never widens to fit its number, so header and bars share the same grid. */
.gantt-track { display: grid; grid-template-columns: repeat(var(--sprints), minmax(0, 1fr)); height: 18px; }
.gantt-track.months { height: auto; font-size: 0.72rem; color: var(--muted); }
.gantt-track.months span { display: flex; justify-content: center; overflow: visible; white-space: nowrap; }
.gantt-bar { border-radius: 6px; height: 18px; }
.kind-setup { background: var(--muted); }
.kind-build { background: var(--gantt-build); }
.kind-front { background: var(--pistache); }
.gantt-head { border-bottom: 1px solid var(--border); }
.gantt-state { font-size: 0.78rem; color: var(--muted); margin-left: var(--space-1); }
.gantt-row[data-state="planned"] .gantt-bar { opacity: 0.4; }
.gantt-row[data-state="current"] .gantt-bar { outline: 2px solid var(--text-strong); outline-offset: 1px; }
.gantt-row[data-state="current"] .gantt-state { color: var(--text-strong); font-weight: 600; }

/* Lists */
.steps, .checks { margin: 0; padding-left: 1.3rem; }
.steps li, .checks li { margin-bottom: var(--space-2); }
.checks { list-style: none; padding-left: 0; }
.checks li::before { content: "✓"; color: var(--link); font-weight: 700; margin-right: var(--space-2); }

/* Footer */
.site-footer { border-top: 1px solid var(--border); padding: var(--space-5) 0; color: var(--muted); font-size: 0.9rem; }
.footer-row { display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--space-3); }

/* Mobile */
@media (max-width: 720px) {
  .hero { padding: var(--space-6) 0 var(--space-5); }
  .stats { grid-template-columns: 1fr 1fr 1fr; gap: var(--space-2); }
  .stat { padding: var(--space-3); }
  .stat strong { font-size: 1.5rem; }
  .stat span { font-size: 0.8rem; }
  .split { grid-template-columns: 1fr; }
  .timeline > li { grid-template-columns: 1fr; gap: var(--space-1); }
  .gantt-row { grid-template-columns: 1fr; gap: var(--space-1); }
  .gantt-head .gantt-label { display: none; }
  .brand span { font-size: 1rem; }
  .gantt-track.months span:not([data-major]) { visibility: hidden; }
}

/* Risk register on a narrow screen: the header keeps only its sort buttons, each risk becomes a card
   (number and name, then probability, impact, score and matrix, then the mitigation and the outcome). */
@media (max-width: 720px) {
  .risks, .risks tbody { display: block; }
  .risks thead tr { display: flex; flex-wrap: wrap; gap: 0 var(--space-3); padding: var(--space-1) var(--space-3); background: var(--surface-2); }
  .risks thead th { padding: 0; border: 0; background: none; }
  .risks thead th:not(:has(.sort)) { display: none; }
  .risks tbody tr { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); padding: var(--space-3); border-bottom: 1px solid var(--border); }
  .risks tbody td, .risks tbody th { padding: 0; border: 0; }
  .risks .c-id { flex: 0 0 2.5rem; }
  .risks .c-label { flex: 1 1 calc(100% - 3.5rem); }
  .risks .c-val { text-align: left; white-space: nowrap; }
  .risks .c-val::before { content: attr(data-label) " "; color: var(--muted); font-size: 0.85rem; }
  .risks .c-mitigation, .risks .c-outcome { flex: 1 1 100%; }
  .risks .c-outcome::before { content: attr(data-label) " "; color: var(--muted); font-size: 0.85rem; }
}

@media (prefers-reduced-motion: no-preference) {
  .card { transition: transform 0.15s ease, border-color 0.15s ease; }
  .card:hover { transform: translateY(-2px); border-color: var(--border-strong); }
}

/* Project management page: sprint log and charts (D40). */
.sprint-log { display: grid; gap: var(--space-3); }
.sprint-item { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3) var(--space-4); }
.sprint-item p { margin: var(--space-2) 0; }
.sprint-goal::first-letter { text-transform: uppercase; }
.sprint-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-2); }
.sprint-older { margin-top: var(--space-3); }
.sprint-older summary, .chart-data summary { cursor: pointer; padding: 10px 0; font-weight: 600; }
.sprint-older .sprint-log { margin-top: var(--space-3); }
.chart-figure { margin: var(--space-5) 0; max-width: 760px; }
.chart-figure h3 { margin-bottom: var(--space-1); }
.chart-wrap { overflow-x: auto; }
.chart-wrap:focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }
.chart { display: block; width: 100%; min-width: 560px; height: auto; }
.chart-grid { stroke: var(--chart-grid); stroke-width: 1; }
.chart-tick, .chart-label { fill: var(--muted); font: 12px var(--font-body); }
.chart-label { fill: var(--text); }
.chart-bar { fill: var(--chart-series); }
.chart-line { fill: none; stroke: var(--chart-series); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-dot { fill: var(--chart-series); stroke: var(--surface); stroke-width: 2; }
.chart-ref { stroke: var(--chart-ref); stroke-width: 1.5; stroke-dasharray: 5 4; }
.chart-target { fill: transparent; }
.chart-hit:hover .chart-bar { opacity: 0.8; }
.chart-legend { display: flex; flex-wrap: wrap; gap: var(--space-4); margin: var(--space-2) 0; color: var(--text); }
.chart-legend li { display: flex; align-items: center; gap: var(--space-2); }
.key { display: inline-block; width: 22px; height: 0; border-top: 2px solid var(--chart-series); }
.key-ref { border-top: 2px dashed var(--chart-ref); }
/* A scope added along the way (D49): a ring at the top of its step in the burndown. */
.chart-step { fill: var(--surface); stroke: var(--chart-series); stroke-width: 2; }
.key-step { width: 10px; height: 10px; border: 2px solid var(--chart-series); border-radius: 50%; }
.chart-data table { margin-top: var(--space-2); }

/* Ray tracer (D45) */
.rt-controls { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: var(--space-3) 0; }
.rt-field { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.rt-field select { min-height: 44px; padding: 0 var(--space-2); font: inherit; color: var(--text-strong); background: var(--surface-2); border: 1px solid var(--border-strong); border-radius: var(--radius); }
.rt-stage { border-radius: var(--radius-lg); background: var(--surface-2); overflow: hidden; }
.rt-stage.is-over { outline: 3px dashed var(--accent); outline-offset: 2px; }
.rt-file { align-items: center; }
/* Vertical swipes still scroll the page on touch screens; horizontal ones orbit. */
.rt-stage canvas { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; touch-action: pan-y; cursor: grab; }
.rt-progress { font-variant-numeric: tabular-nums; min-height: 1.5em; }
.rt-view { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-3); }
.rt-slider { display: grid; grid-template-columns: auto minmax(0, 1fr) 4.5em; align-items: center; gap: var(--space-2); }
.rt-slider input { min-height: 44px; width: 100%; accent-color: var(--accent); }
.rt-slider output { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }

/* Ada crossroads (D46) */
.cross-grid { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr); gap: var(--space-4); align-items: start; }
@media (max-width: 640px) { .cross-grid { grid-template-columns: minmax(0, 1fr); } }
.cross-map { display: block; width: 100%; max-width: 260px; height: auto; background: var(--surface-2); border-radius: var(--radius); }
.cross-road { fill: var(--tl-road); }
.cross-marking { stroke: var(--tl-marking); stroke-width: 2; stroke-dasharray: 8 8; }
.cross-housing { fill: var(--tl-housing); }
.cross-lamp { fill: var(--tl-off); }
.cross-lamp.is-on[data-lamp="R"], .cross-bar.is-R { fill: var(--tl-red); }
.cross-lamp.is-on[data-lamp="Y"], .cross-bar.is-Y { fill: var(--tl-amber); }
.cross-lamp.is-on[data-lamp="G"], .cross-bar.is-G { fill: var(--tl-green); }
.cross-car { fill: var(--tl-car); }
/* The browser's [hidden] rule does not reach SVG elements. */
.cross-car[hidden] { display: none; }
.cross-axis, .cross-chart-label { fill: var(--text); font: 12px var(--font-body); }
.cross-clock { font-variant-numeric: tabular-nums; min-height: 1.5em; }
.cross-speed { max-width: 12rem; }
.cross-chart { display: block; width: 100%; height: auto; }

/* What each technology does in a project (its role), under the stack's tags. */
.roles { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-2) var(--space-3); margin: 0; }
.roles dt { font-weight: 600; color: var(--text-strong); }
.roles dd { margin: 0; }
@media (max-width: 480px) { .roles { grid-template-columns: minmax(0, 1fr); } .roles dd { margin-bottom: var(--space-2); } }

/* Topology viewer: height filtration and critical points (sprint 36). */
.topo-mode { border: 0; padding: 0; margin: var(--space-3) 0; display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); }
.topo-mode legend { font-weight: 600; color: var(--text-strong); margin-bottom: var(--space-1); }
.topo-mode label { display: inline-flex; align-items: center; gap: var(--space-2); min-height: 44px; }
.topo-height { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
.topo-height[hidden] { display: none; }
/* "1,41 sur 1,41": wider than the ray tracer's values. */
.topo-height .rt-slider { grid-template-columns: auto minmax(0, 1fr) 7em; }
.topo-keys { display: flex; flex-wrap: wrap; gap: var(--space-3); list-style: none; padding: 0; margin: 0; }
.topo-key { display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: var(--space-1); vertical-align: middle; }
.topo-key.is-min { background: var(--crit-min); }
.topo-key.is-saddle { background: var(--crit-saddle); }
.topo-key.is-max { background: var(--crit-max); }
.topo-chi { width: 100%; height: auto; max-width: 360px; }
.topo-chi .chi-line { fill: none; stroke: var(--chart-series); stroke-width: 2; }
.topo-chi .chi-axis { stroke: var(--chart-grid); }
.topo-chi .chi-level { stroke: var(--chart-ref); stroke-dasharray: 4 3; }
.topo-chi text { fill: var(--muted); font: 11px var(--font-body); }

/* Persistence diagram (sprint 37): a mark per dimension, in the colours of the critical points that give birth
   to it (minimum, saddle, maximum); the noise under the threshold is greyed. */
/* minmax(0, 1fr): an implicit `auto` column would take the width of the table of pairs. */
.topo-pers { margin: var(--space-3) 0 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
/* "Minimum persistence" takes its own row: beside it and its value, the track had no room in the viewer's
   narrow column (on a phone, the threshold's label does the same). */
.topo-pers .rt-slider { grid-template-columns: minmax(0, 1fr) 7em; }
.topo-pers .rt-slider label { grid-column: 1 / -1; }
@media (max-width: 480px) { .topo-height .rt-slider label { grid-column: 1 / -1; } .topo-height .rt-slider { grid-template-columns: minmax(0, 1fr) 7em; } }
.topo-diagram { width: 100%; height: auto; max-width: 360px; }
/* The browser's [hidden] rule does not reach SVG elements. */
.topo-diagram[hidden] { display: none; }
.topo-diagram .pers-axis { stroke: var(--chart-grid); }
.topo-diagram .pers-diagonal { stroke: var(--chart-grid); stroke-width: 1.5; }
.topo-diagram .pers-band { fill: var(--chart-grid); opacity: 0.35; }
.topo-diagram text { fill: var(--muted); font: 11px var(--font-body); }
.pers-shape.is-h0 { fill: var(--crit-min); }
.pers-shape.is-h1 { fill: var(--crit-saddle); }
.pers-shape.is-h2 { fill: var(--crit-max); }
.pers-point.is-noise .pers-shape { fill: var(--muted); opacity: 0.45; }
/* The pair as an upright bar: from the diagonal (its birth) to the point (its death); dashed up to the ∞ line. */
.pers-stem { stroke-width: 2; }
.pers-stem.is-h0, .pers-foot.is-h0 { stroke: var(--crit-min); fill: var(--crit-min); }
.pers-stem.is-h1, .pers-foot.is-h1 { stroke: var(--crit-saddle); fill: var(--crit-saddle); }
.pers-stem.is-h2, .pers-foot.is-h2 { stroke: var(--crit-max); fill: var(--crit-max); }
/* A class that never dies going up (Charles's review, D50): closed on the way down, its mark ringed in the text
   colour; dashed when it closes below its birth (under the diagonal, a bar read backwards). */
.pers-point.is-essential .pers-shape { stroke: var(--text-strong); stroke-width: 1.5; }
.pers-point.is-down .pers-stem { stroke-dasharray: 4 3; }
.bar.is-essential .bar-line { stroke: var(--text-strong); stroke-width: 0.8; }
.bar.is-down .bar-line { fill-opacity: 0.35; stroke-dasharray: 3 2; }
[data-ext-reeb][hidden], [data-ext-reeb-text][hidden] { display: none; }
.pers-point.is-noise .pers-stem, .pers-point.is-noise .pers-foot { stroke: var(--muted); fill: var(--muted); opacity: 0.45; }
.pers-key { width: 12px; height: 12px; margin-right: var(--space-1); vertical-align: middle; }

/* Barcode and picked pair (sprint 39): a bar per pair in the colour of its dimension, the dashed height threshold
   across; the bars it crosses (alive at that level) are opaque, the others faded, the noise greyed. The picked
   pair is outlined in the text colour wherever it shows (bar, point, row). */
.topo-bars { width: 100%; height: auto; max-width: 360px; }
.topo-bars[hidden] { display: none; }
.topo-bars text { fill: var(--muted); font: 11px var(--font-body); }
.topo-bars .bars-group { fill: var(--text-strong); font-weight: 600; }
.topo-bars .pers-axis { stroke: var(--chart-grid); }
.topo-bars .bars-level { stroke: var(--chart-ref); stroke-dasharray: 4 3; stroke-width: 1.5; }
.bar { cursor: pointer; }
.bar .bar-hit { fill: transparent; }
.bar .bar-line { opacity: 0.4; }
.bar.is-alive .bar-line { opacity: 1; }
.bar.is-noise .bar-line { fill: var(--muted); }
.bar-line.is-h0 { fill: var(--crit-min); }
.bar-line.is-h1 { fill: var(--crit-saddle); }
.bar-line.is-h2 { fill: var(--crit-max); }
.bar.is-picked .bar-hit { fill: var(--chart-grid); }
.bar.is-picked .bar-line { opacity: 1; stroke: var(--text-strong); stroke-width: 1; }
.pers-point { cursor: pointer; }
.pers-point .pers-ring { fill: transparent; stroke: none; }
.pers-point.is-picked .pers-ring { stroke: var(--text-strong); stroke-width: 1.5; }
.topo-bars [role=option]:focus, .topo-diagram [role=option]:focus { outline: none; }
.topo-bars [role=option]:focus-visible .bar-hit { stroke: var(--text-strong); stroke-width: 1; }
.topo-diagram [role=option]:focus-visible .pers-ring { stroke: var(--text-strong); stroke-width: 1.5; stroke-dasharray: 2 2; }
.pers-pick { min-height: 44px; padding: 0 var(--space-2); background: none; border: 1px solid var(--border-strong); border-radius: var(--radius); color: var(--text); font: inherit; cursor: pointer; text-align: left; }
.pers-pick[aria-pressed=true] { border-color: var(--text-strong); color: var(--text-strong); font-weight: 600; }
tr.is-picked { background: var(--surface-2); }
.topo-pick { border-left: 3px solid var(--border-strong); padding-left: var(--space-2); }
.topo-pick[hidden] { display: none; }
.topo-tour { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3); display: grid; gap: var(--space-2); }
.topo-tour[hidden] { display: none; }
.topo-tour p { margin: 0; }

/* Reeb graph (sprint 38): arcs in the text colour, nodes in the colours of the critical points. */
.topo-reeb { margin: var(--space-3) 0 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); }
.topo-check { display: inline-flex; align-items: center; gap: var(--space-2); min-height: 44px; }
.topo-reeb-flat { width: 100%; height: auto; max-width: 360px; }
.topo-reeb-flat[hidden] { display: none; }
.topo-reeb-flat .reeb-arc { fill: none; stroke: var(--text-strong); stroke-width: 1.5; }
.topo-reeb-flat .reeb-level { stroke: var(--chart-ref); stroke-dasharray: 4 3; }
.reeb-node { stroke: var(--surface); stroke-width: 1; }
.reeb-node.is-min { fill: var(--crit-min); }
.reeb-node.is-saddle, .reeb-node.is-other { fill: var(--crit-saddle); }
.reeb-node.is-max { fill: var(--crit-max); }

/* In plain words (D53): a box at the top of each project page, closed by default; the summary row is a 44 px target. */
.plain { margin: var(--space-4) 0; border: 1px solid var(--border-strong); border-left: 4px solid var(--accent); border-radius: var(--radius); background: var(--surface); }
.plain summary { cursor: pointer; min-height: 44px; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-4); }
.plain .plain-title { font-weight: 600; color: var(--text-strong); }
.plain .plain-hint { color: var(--muted); font-size: 0.9rem; }
/* It must look clickable (Charles's review): display: flex hides the browser's own triangle, so a chevron that turns,
   an explicit "Read the summary" / "Close" on the right, and a hover state. */
.plain summary { list-style: none; }
.plain summary::-webkit-details-marker { display: none; }
.plain summary:hover { background: var(--surface-2); }
.plain summary:hover .plain-action { text-decoration: underline; }
.plain-chevron { width: 0.6em; height: 0.6em; border-right: 2px solid var(--text-strong); border-bottom: 2px solid var(--text-strong); transform: rotate(-45deg); transition: transform 0.15s; flex: none; margin-right: var(--space-1); }
.plain[open] .plain-chevron { transform: rotate(45deg); }
.plain-action { margin-left: auto; font-weight: 600; color: var(--text-strong); white-space: nowrap; }
.plain .plain-close, .plain[open] .plain-open { display: none; }
.plain[open] .plain-close { display: inline; }
@media (prefers-reduced-motion: reduce) { .plain-chevron { transition: none; } }
.plain dl { margin: 0; padding: 0 var(--space-4) var(--space-4); display: grid; gap: var(--space-3); }
.plain dt { font-weight: 600; color: var(--text-strong); }
.plain dd { margin: var(--space-1) 0 0; max-width: 70ch; }

/* The tactical RPG's page: the video and the drawing of its parts (colours from the tokens). */
.rpg-video video { display: block; width: 100%; max-width: 716px; height: auto; border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--surface-2); }
.arch { margin: var(--space-3) 0; }
.arch svg { display: block; width: 100%; height: auto; }
.arch .arch-box rect { fill: var(--surface-2); stroke: var(--border-strong); stroke-width: 1.5; }
.arch .arch-core rect { stroke: var(--accent); stroke-width: 3; }
.arch .arch-name { fill: var(--text-strong); font-size: 17px; font-weight: 600; text-anchor: middle; }
.arch .arch-tech { fill: var(--muted); font-size: 13px; text-anchor: middle; }
.arch .arch-link line { stroke: var(--chocolat-clair); stroke-width: 2; }
.arch .arch-link text { fill: var(--text); font-size: 13px; }
.arch marker path { fill: var(--chocolat-clair); }
.arch-list li { margin-bottom: var(--space-2); }
.rpg-launcher img { max-width: 360px; }
/* Documentation assistant (D58): the best search in bold, recorded answers under a rule. */
.row-best th, .row-best td { font-weight: 700; color: var(--text-strong); }
.rag-example { border-top: 1px solid var(--border-strong); padding-top: var(--space-3); margin-top: var(--space-3); max-width: 75ch; }
.rag-sources { margin-top: 0; }
.rag-sources a { overflow-wrap: anywhere; }
