/* ==========================================================================
   Figures: Mermaid diagrams drawn as ink on the page. Loaded only on pages with
   a diagram (base.njk). Tokens first; below them nothing hardcodes a colour or
   a px size. Stroke widths are SVG user units. Dark rules are written twice.
   ========================================================================== */
:root {
  /* What an author's colour resolves to (src/assets/js/figures/model.js). The first three are the
     house palette, the same in both themes; each `-line` is that hue held to 3:1 on the paper. */
  --fig-good: #2d6a4f;
  --fig-bad: #9d4444;
  --fig-subject: #5a5a8a;
  --fig-cool: #2e6da4;
  --fig-caution: #896d1f;
  --fig-violet: #8a3fa0;
  --fig-orange: #b85a14;
  --fig-on-solid: #fff;
  --fig-good-line: var(--fig-good);
  --fig-bad-line: var(--fig-bad);
  --fig-subject-line: var(--fig-subject);
  --fig-cool-line: var(--fig-cool);
  --fig-caution-line: var(--fig-caution);
  --fig-violet-line: var(--fig-violet);
  --fig-orange-line: var(--fig-orange);
  --fig-tint: 15%;
  --fig-mix-line: 58%;
  --fig-ghost: .14;
  --fig-far: .62;
  --fig-far-ink: 78%;
  --fig-hair: 1;
  --fig-ink-time: 260ms;
  --fig-ink-step: 80ms;
  --fig-rule: .06rem;
  --fig-mask: #000;
}
@media (prefers-color-scheme: dark) {
  :root:not(.light-mode) {
    --fig-good-line: var(--color-accent);
    --fig-bad-line: #d17a7a;
    --fig-subject-line: #9a9ac8;
    --fig-cool-line: #6aa9dc;
    --fig-caution-line: #c9a441;
    --fig-violet-line: #c48ad6;
    --fig-orange-line: #e8954f;
    --fig-tint: 34%;
    --fig-mix-line: 56%;
    --fig-ghost: .22;
  }
}
:root.dark-mode {
  --fig-good-line: var(--color-accent);
  --fig-bad-line: #d17a7a;
  --fig-subject-line: #9a9ac8;
  --fig-cool-line: #6aa9dc;
  --fig-caution-line: #c9a441;
  --fig-violet-line: #c48ad6;
  --fig-orange-line: #e8954f;
  --fig-tint: 34%;
  --fig-mix-line: 56%;
  --fig-ghost: .22;
}

/* Paper is light whatever the screen was: the theme's dark values would print light ink on a white page. */
@media print {
  .fig {
    --color-bg: #f8f6f1;
    --color-text: #1c1c1c;
    --color-text-muted: #666;
    --color-accent: #1a6b4a;
    --color-border: #e0ddd6;
    --fig-good-line: var(--fig-good);
    --fig-bad-line: var(--fig-bad);
    --fig-subject-line: var(--fig-subject);
    --fig-cool-line: var(--fig-cool);
    --fig-caution-line: var(--fig-caution);
    --fig-violet-line: var(--fig-violet);
    --fig-orange-line: var(--fig-orange);
    --fig-tint: 15%;
    --fig-mix-line: 58%;
    --fig-ghost: .14;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }
}
/* A dark page stays dark with background graphics on, so the light tokens bring their own paper. Dark only: on a light
   theme the paper is the page's, and `exact` would print it as a tint on white. Printing the whole site is not this file's. */
@media print and (prefers-color-scheme: dark) {
  :root:not(.light-mode) .fig { background: var(--fig-paper); }
}
@media print {
  :root.dark-mode .fig { background: var(--fig-paper); }
}

/* ---- Frame -------------------------------------------------------------- */
/* The one setting for the figures' face: the CSS paints with it, and the engine measures labels in it. */
:root { --fig-face: var(--font-serif); }

.fig {
  --fig-paper: var(--color-bg);
  --fig-ink: var(--color-text);
  --fig-line: color-mix(in oklab, var(--fig-ink) var(--fig-mix-line), var(--fig-paper));
  --fig-node: var(--fig-paper);
  --fig-node-line: var(--fig-line);
  --fig-node-width: 1;
  --fig-edge-width: 1.15;
  --fig-size: 1rem;
  --fig-edge-size: var(--fig-size);
  --fig-region: color-mix(in oklab, var(--fig-ink) 5%, var(--fig-paper));
  --fig-radius: .125rem;
  min-width: 0;
  position: relative;
  /* No card: two hairlines and room are all that set a figure off from the prose. */
  margin: var(--space-lg) 0;
  padding: var(--space-md) 0;
  border-block: var(--fig-rule) solid var(--color-border);
}
.post-content > .fig { margin-block: var(--space-lg); }
/* Laid out beside its source, unseen, until the drawing is ready. Height 0, not display none: it must measure. */
.post-content > .fig.is-drawing, .fig.is-drawing { height: 0; margin: 0; padding: 0; border: 0; overflow: hidden; visibility: hidden; }
.fig__stage { position: relative; text-align: center; }
.fig__stage[data-fit="scroll"] { overflow-x: auto; overflow-y: hidden; }
.fig__stage svg {
  display: block; margin-inline: auto; height: auto; overflow: visible;
  font-family: var(--fig-face); font-size: var(--fig-size); color: var(--fig-ink);
  font-optical-sizing: auto;
  -webkit-tap-highlight-color: transparent;
}
.fig__measure { position: absolute; visibility: hidden; pointer-events: none; height: 0; overflow: hidden; left: 0; top: 0; }
.fig svg p, .fig__measure svg p { margin: 0; }
.fig svg .label, .fig svg .nodeLabel, .fig svg .edgeLabel { font-family: var(--fig-face); color: var(--n-ink, var(--fig-ink)); }
.fig__measure .edgeLabel, .fig svg span.edgeLabel { display: inline-block; }
.fig svg text { fill: var(--fig-ink); font-family: var(--fig-face); }

/* ---- Tone: nodes, clusters and card lines take everything from these ------ */
.fig [data-tone="good"] { --n-solid: var(--fig-good); --n-line: var(--fig-good-line); }
.fig [data-tone="bad"] { --n-solid: var(--fig-bad); --n-line: var(--fig-bad-line); }
.fig [data-tone="subject"] { --n-solid: var(--fig-subject); --n-line: var(--fig-subject-line); }
.fig [data-tone="cool"] { --n-solid: var(--fig-cool); --n-line: var(--fig-cool-line); }
.fig [data-tone="caution"] { --n-solid: var(--fig-caution); --n-line: var(--fig-caution-line); }
.fig [data-tone="violet"] { --n-solid: var(--fig-violet); --n-line: var(--fig-violet-line); }
.fig .node { --n-fill: var(--fig-node); --n-stroke: var(--fig-node-line); --n-ink: var(--fig-ink); }
.fig .node[data-strength="solid"] { --n-fill: var(--n-solid); --n-stroke: var(--n-solid); --n-ink: var(--fig-on-solid); }
.fig .node[data-strength="tint"] { --n-fill: color-mix(in oklab, var(--n-solid) var(--fig-tint), var(--fig-paper)); --n-stroke: var(--n-line); }
.fig .node[data-strength="line"] { --n-stroke: var(--n-line); --fig-node-width: 1.75; }
.fig .node :is(rect, polygon, circle, ellipse, path):not(.label *) {
  fill: var(--n-fill); stroke: var(--n-stroke); stroke-width: var(--fig-node-width);
}
.fig .node rect:not(.label *) { rx: var(--fig-radius); ry: var(--fig-radius); }
.fig .flowchart-link { fill: none; stroke: var(--fig-line); stroke-width: var(--fig-edge-width); stroke-linecap: round; }
.fig .edge-thickness-thick { stroke-width: 2.5; }
.fig .edge-pattern-dashed { stroke-dasharray: 3 3; }
.fig .edge-pattern-dotted { stroke-dasharray: 2 3.5; }
.fig .edge-thickness-invisible { stroke-width: 0; }
.fig marker path, .fig marker polygon, .fig marker circle { fill: var(--fig-line); stroke: none; }
.fig .marker.cross path { stroke: var(--fig-line); fill: none; }
.fig .edgeLabel .labelBkg { background: var(--fig-paper); }
.fig .edgeLabel p, .fig .edgeLabel span { font-size: var(--fig-edge-size); font-style: italic; }
/* A group is a dotted outline until its author colours it: a coloured group is a region, tinted, with a firm edge. */
.fig .cluster rect { fill: none; stroke: var(--fig-line); stroke-width: .75; stroke-dasharray: 1 3; }
.fig .cluster:is([data-strength="tint"], [data-strength="solid"]) rect { fill: color-mix(in oklab, var(--n-solid) var(--fig-tint), var(--fig-paper)); stroke: var(--n-line); stroke-width: 1; stroke-dasharray: none; }
.fig .cluster[data-strength="line"] rect { stroke: var(--n-line); stroke-width: 1.75; stroke-dasharray: none; }
.fig .cluster-label .nodeLabel, .fig .cluster-label p { color: var(--fig-ink); font-style: italic; font-weight: 500; }
/* A title sits above the edges on its group's colour (figure.js, groupTitles). */
.fig .cluster-label p { background: var(--c-paper, var(--fig-paper)); }
.fig .cluster-label:is([data-strength="tint"], [data-strength="solid"]) { --c-paper: color-mix(in oklab, var(--n-solid) var(--fig-tint), var(--fig-paper)); }
.fig svg foreignObject.is-card { overflow: visible; }
.fig__card-title { display: block; font-weight: 600; }
/* Never position anything inside foreignObject: WebKit paints it at the SVG's origin, not in its box. */
.fig__card-line { display: block; }
/* A role that belonged to one line of a card, drawn in the node's padding so it costs no width. */
.fig__card-line[data-tone] {
  margin-left: -.35em; padding-left: .35em;
  background: linear-gradient(var(--n-line), var(--n-line)) no-repeat 0 50% / .13em calc(100% - .5em);
}

/* Block: a group's title sits in a band of its own at the top of the group */
.fig g.label[data-outside] .nodeLabel { color: var(--fig-ink); font-weight: 600; }
.fig .node:not([data-tone]) > rect.composite { fill: none; stroke-width: .75; stroke-dasharray: 1 3; }

/* Sequence */
.fig rect.actor { fill: var(--fig-node); stroke: var(--fig-node-line); stroke-width: var(--fig-node-width); }
.fig .actor-line { stroke: var(--fig-line); stroke-width: .75; stroke-dasharray: 1 3; }
.fig [class^="messageLine"] { stroke: var(--fig-line); stroke-width: var(--fig-edge-width); }
.fig text.actor, .fig .noteText { fill: var(--fig-ink); stroke: none; }
/* A wrapped message can sit on its own line: the paper halo keeps it readable. */
.fig .messageText { fill: var(--fig-ink); paint-order: stroke; stroke: var(--fig-paper); stroke-width: 3; stroke-linejoin: round; }
.fig rect.note { fill: color-mix(in oklab, var(--fig-caution) var(--fig-tint), var(--fig-paper)); stroke: var(--fig-caution-line); stroke-width: var(--fig-hair); }
.fig .activation0, .fig .activation1, .fig .activation2 { fill: var(--fig-region); stroke: var(--fig-line); }
.fig .labelBox { fill: var(--fig-region); stroke: var(--fig-line); }
.fig .loopLine { stroke: var(--fig-line); }
.fig .labelText, .fig .loopText, .fig .loopText tspan { fill: var(--fig-ink); }

/* Sankey: graphite by default. A fixed colour order would invent meaning. */
.fig[data-kind="sankey"] g.links path { stroke: var(--fig-line); stroke-opacity: .32; fill: none; }
.fig[data-kind="sankey"] g.nodes rect { fill: var(--fig-ink); stroke: none; }
.fig[data-kind="sankey"] g.node-labels text { font-size: var(--fig-edge-size); paint-order: stroke; stroke: var(--fig-paper); stroke-width: 3; stroke-linejoin: round; }

/* Quadrant */
.fig .quadrant rect { fill: var(--fig-region); stroke: var(--fig-paper); stroke-width: 2; }
.fig .quadrant:nth-child(2) rect, .fig .quadrant:nth-child(4) rect { fill: color-mix(in oklab, var(--fig-ink) 2%, var(--fig-paper)); }
.fig .quadrant text { fill: var(--fig-ink); font-weight: 600; }
.fig .data-point circle { fill: var(--color-accent); stroke: var(--fig-paper); }
.fig .data-point text { fill: var(--fig-ink); }
.fig[data-kind="quadrant"] .labels text, .fig[data-kind="quadrant"] .title text { fill: var(--fig-ink); }
.fig[data-kind="quadrant"] line { stroke: var(--fig-line); }

/* Radar: two series, and one is dashed so colour is not alone */
.fig .radarGraticule { fill: none; stroke: var(--fig-line); stroke-opacity: .4; }
.fig .radarAxisLine { stroke: var(--fig-line); stroke-opacity: .5; }
.fig .radarAxisLabel { fill: var(--fig-ink); font-size: var(--fig-edge-size); }
.fig .radarCurve-0 { fill: var(--fig-cool-line); fill-opacity: .16; stroke: var(--fig-cool-line); stroke-width: 2; }
.fig .radarCurve-1 { fill: var(--fig-orange-line); fill-opacity: .14; stroke: var(--fig-orange-line); stroke-width: 2; stroke-dasharray: 5 3; }
.fig .radarTitle, .fig .radarLegendText, .fig [class^="radarLegendBox"] { display: none; }
.fig__legend { display: flex; flex-wrap: wrap; gap: 0 var(--space-md); justify-content: center; margin: var(--space-xs) 0 0; font-family: var(--font-sans); font-size: var(--text-xs); color: var(--fig-ink); }
.fig__legend span::before { content: ""; display: inline-block; width: 1.4em; margin-right: .4em; vertical-align: .25em; border-top: .13rem solid var(--fig-cool-line); }
.fig__legend span + span::before { border-top: .13rem dashed var(--fig-orange-line); }

/* A chart title that its drawing has no room for */
.fig__title { margin: 0 0 var(--space-sm); font-family: var(--fig-face); font-size: var(--text-base); font-weight: 600; text-align: center; color: var(--fig-ink); }

/* Timeline: re-set as text, so it needs no SVG at any width */
.fig-timeline { list-style: none; margin: 0; padding: 0 0 0 .5rem; text-align: left; font-family: var(--fig-face); }
.fig-timeline li { position: relative; padding: 0 0 var(--space-md) var(--space-md); border-left: var(--fig-rule) solid var(--fig-line); }
.fig-timeline li:last-child { padding-bottom: 0; }
.fig-timeline p { margin: 0; }
.fig-timeline li::before { content: ""; position: absolute; left: calc(var(--space-xs) * -1 - .03rem); top: .45em; width: calc(var(--space-xs) * 2); height: calc(var(--space-xs) * 2); min-width: .5rem; min-height: .5rem; border-radius: 50%; background: var(--fig-ink); }
.fig-timeline li:last-child::before { background: var(--color-accent); }
.fig-timeline__when { font-family: var(--font-sans); font-size: var(--text-xs); font-weight: 600; color: var(--color-text-muted); }
.fig-timeline__lead { font-size: var(--text-base); font-weight: 600; line-height: 1.3; color: var(--fig-ink); }
.fig-timeline__rest { font-size: var(--text-sm); line-height: 1.45; color: var(--color-text-muted); }

/* ---- Below the drawing --------------------------------------------------- */
/* The readout is out of flow and its tallest sentence is reserved here (--fig-say-h), so tracing moves nothing.
   It shares the row with the disclosure and covers it while a trace is up. */
.fig__foot { position: relative; margin-top: var(--space-sm); min-height: var(--fig-say-h, 0); }
.fig__say {
  position: absolute; inset: 0 0 auto; z-index: 1; margin: 0; pointer-events: none; background: var(--fig-paper);
  font-family: var(--font-serif); font-size: var(--text-sm); line-height: 1.4; color: var(--color-text);
}
/* Off the disclosure whenever someone is using it, pinned step or not. */
.fig__say:empty, .fig:has(.fig__text[open]) .fig__say, .fig:has(.fig__text summary:focus-visible) .fig__say, .fig:has(.fig__run:focus-visible) .fig__say { visibility: hidden; }
.fig__text { font-family: var(--font-sans); font-size: var(--text-xs); color: var(--color-text-muted); }
.fig__text summary { cursor: pointer; width: fit-content; padding-block: .15rem; text-decoration: underline; text-decoration-color: var(--color-border); text-underline-offset: .2em; }
.fig__text summary:hover { color: var(--color-text); }
.fig__steps { margin-top: var(--space-sm); font-family: var(--font-serif); font-size: var(--text-sm); line-height: 1.45; color: var(--color-text); }
.fig__steps ol { margin: 0 0 var(--space-sm); padding-left: 1.4em; }
.fig__group { margin: var(--space-sm) 0 var(--space-xs); font-family: var(--font-sans); font-size: var(--text-xs); font-weight: 600; }
/* Scrolling is the last resort. It keeps its hint and is keyboard reachable. */
.fig__stage[data-fit="scroll"]:focus-visible { outline: .19rem solid var(--color-accent); }
.fig__hint { margin: var(--space-xs) 0 0; font-family: var(--font-sans); font-size: var(--text-xs); color: var(--color-text-muted); }
.fig__stage.is-capped:not(.is-open) { max-height: var(--fig-cap); overflow-y: hidden; mask-image: linear-gradient(to bottom, var(--fig-mask) 82%, transparent); -webkit-mask-image: linear-gradient(to bottom, var(--fig-mask) 82%, transparent); }
.fig__fold { display: block; min-height: 2.75rem; margin: var(--space-xs) auto 0; padding: var(--space-xs) var(--space-sm); font-family: var(--font-sans); font-size: var(--text-ui); color: var(--color-accent); background: none; border: 0; cursor: pointer; text-decoration: underline; text-underline-offset: .2em; }

/* ---- Trace --------------------------------------------------------------- */
.fig :focus-visible { outline: .19rem solid var(--color-accent); outline-offset: .13rem; border-radius: var(--fig-radius); }
.is-touchable { cursor: pointer; }
.fig svg g:focus, .fig svg g[role="button"]:focus-visible { outline: none; }
.fig svg g[role="button"]:focus-visible :is(rect, polygon, circle, ellipse, path):not(.label *) { stroke: var(--color-accent); stroke-width: 3; }
.fig svg text[role="button"]:focus { outline: none; }
.fig svg text[role="button"]:focus-visible { text-decoration: underline; }
.fig .node, .fig .flowchart-link, .fig .edgeLabel, .fig .cluster, .fig .cluster-label,
.fig [data-et="message"], .fig .messageText, .fig g.link, .fig g.node-labels text, .fig [data-et="participant"], .fig [data-et="note"] {
  transition: opacity var(--transition-base);
}
.fig.is-tracing .node:not([data-t]), .fig.is-tracing .flowchart-link:not([data-t]),
.fig.is-tracing .edgeLabels > g.edgeLabel:not([data-t]), .fig.is-tracing .cluster:not([data-t]), .fig.is-tracing .cluster-label:not([data-t]),
.fig.is-tracing [data-et="message"]:not([data-t]), .fig.is-tracing .messageText:not([data-t]),
.fig.is-tracing [data-et="note"]:not([data-t]), .fig.is-tracing [data-et="participant"]:not([data-t]),
.fig.is-tracing g.link:not([data-t]), .fig.is-tracing g.node-labels text:not([data-t]) { opacity: var(--fig-ghost); }
/* Two hops out: quieter, but still words a reader can read. Shapes and lines fade; text only softens, and a solid
   node gives up its fill, because white on a faded fill is what falls under 4.5:1. */
.fig.is-tracing .flowchart-link[data-t="far"] { opacity: var(--fig-far); }
.fig.is-tracing .cluster[data-t="far"] rect { opacity: var(--fig-far); }
.fig.is-tracing .node[data-t="far"] { --n-ink: color-mix(in oklab, var(--fig-ink) var(--fig-far-ink), var(--fig-paper)); --n-stroke: var(--fig-line); }
.fig.is-tracing .node[data-t="far"][data-strength="solid"] { --n-fill: color-mix(in oklab, var(--n-solid) var(--fig-tint), var(--fig-paper)); --n-stroke: var(--n-line); }
.fig.is-tracing .edgeLabels > g.edgeLabel[data-t="far"] { --n-ink: color-mix(in oklab, var(--fig-ink) var(--fig-far-ink), var(--fig-paper)); }
.fig.is-tracing .node[data-t="here"] { --fig-node-width: 2.25; --n-stroke: var(--color-accent); }
.fig.is-tracing .node[data-t="here"][data-strength="solid"] { --n-stroke: var(--fig-ink); }
.fig-thread {
  fill: none; stroke-width: 2; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 1; pointer-events: none;
  animation: fig-ink var(--fig-ink-time) ease-out forwards; animation-delay: calc(var(--hop) * var(--fig-ink-step));
}
.fig-thread.is-down { stroke: var(--color-accent); }
.fig-thread.is-up { stroke: var(--fig-ink); stroke-width: 1.5; }
@keyframes fig-ink { to { stroke-dashoffset: 0; } }
.fig marker.is-down path { fill: var(--color-accent); }
.fig marker.is-up path { fill: var(--fig-ink); }
.fig g.link[data-t] path { stroke: var(--color-accent); stroke-opacity: .4; }
/* The paper halo keeps a label off the graphite flows at rest; on a lit flow it would smudge. */
.fig.is-tracing g.node-labels text { stroke: none; }

/* ---- Hand-made figures ---------------------------------------------------- */
/* A drawing an author made for one post (scripts/hand-figures.cjs). Same frame and disclosure as a drawn figure, no
   engine. Whole with no script; src/assets/js/figures/hand.js adds one token, one control language, one readout. SVG
   text sizes are attributes, in user units, so they scale with the drawing and stay above 11px at a 358px column. */
.fig--hand { --hf-far-ink: color-mix(in oklab, var(--fig-ink) var(--fig-far-ink), var(--fig-paper)); --hf-tap: 2.75rem; --hf-at: 0; }
.fig--hand .fig__stage { text-align: left; font-family: var(--fig-face); color: var(--fig-ink); }
/* :where keeps the resets at .post-content's own weight, so a single hf- class below can set a margin or padding. */
.post-content :where(.fig--hand) :is(ol, ul) { list-style: none; margin: 0; padding: 0; }
.post-content :where(.fig--hand) li { margin: 0; }
.post-content :where(.fig--hand) p { margin: 0; }
.post-content .fig__steps ol { list-style: decimal; margin: 0 0 var(--space-sm); padding-left: 1.4em; }
.post-content .fig__steps p { margin: 0 0 var(--space-xs); }
.post-content .fig__title { margin-bottom: var(--space-sm); }

/* One control language, Step through it's: the buttons, bar, dots and caption share its rules below (.fig__panel on).
   Absent until the script has run, so a script that fails leaves the figure whole with no blank.
   Captions keep their height, so a press never moves a control. */
.hf-ctl { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs) var(--space-sm); margin-top: var(--space-sm); }
.hf-cases__label { flex-basis: 100%; font-family: var(--font-sans); font-size: var(--text-xs); color: var(--color-text-muted); }
.hf-btn[aria-pressed="true"] { border-color: var(--color-accent); box-shadow: inset 0 0 0 thin var(--color-accent); }
.hf-btn[aria-pressed="true"]::before { content: "✓ "; color: var(--color-accent); }
/* A loop has no last step: the choice sits on the one row, in place, and a phone puts the count under it. */
.hf-key.hf-key--choice { grid-template-columns: auto minmax(0, 1fr) auto auto; }
.hf-btn { min-width: var(--hf-tap); touch-action: manipulation; }
.hf-btn--go { min-width: 8em; }
.hf-key .hf-dots { grid-column: 1 / -1; }
.fig--hand > .hf-cap { margin-block-start: var(--space-sm); }
.hf-cap strong { line-height: 0; }
.hf-cap:not(.is-said) { color: var(--color-text-muted); }
.fig--hand:not(.is-live) :is(.hf-ctl, .hf-panel, .hf-cap) { display: none; }
.fig--hand :focus { outline: none; }
.fig--hand :focus-visible { outline: .13rem solid var(--color-accent); outline-offset: .13rem; }
.fig--hand :is(.hf-btn, .hf-dot):focus-visible { outline-width: .2em; outline-offset: .1em; }
.fig--hand g:focus-visible { outline: none; }
.fig--hand g:focus-visible > .hf-hit { stroke: var(--color-accent); stroke-width: 2; }
.fig--hand [data-pick] { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.fig--hand .is-far { color: var(--hf-far-ink); }
.fig--hand text.is-far { fill: var(--hf-far-ink); }
.fig--hand path.is-far, .fig--hand rect.is-far, .fig--hand g.is-far { opacity: var(--fig-far); }
/* A dimmed band loses its fill and keeps its edge, so it stays 3:1 against the paper. */
.fig--hand path.hf-flow.is-far { opacity: 1; fill-opacity: .05; }

/* The token: the map's synapse, the one thing that moves. */
.hf-token { display: none; fill: var(--color-accent); stroke: var(--fig-paper); stroke-width: 2.5; pointer-events: none; }
.hf-token.is-on { display: block; }
.fig--hand .hf-guide { fill: none; stroke: none; }
.hf-stop.is-on .hf-shape { stroke: var(--color-accent); stroke-width: 2.5; }
.hf-stop.is-on .hf-solid { stroke: var(--color-accent); stroke-width: 3; paint-order: stroke; }

/* Drawings */
.fig__stage .hf-svg { width: 100%; max-width: 32rem; }
.fig__stage .hf-svg--sm { max-width: 20rem; }
.fig__stage .hf-svg--loop { max-width: 16rem; }
.fig .hf-shape { fill: var(--fig-paper); stroke: var(--fig-line); stroke-width: 1.25; }
.fig .hf-shape--dashed { stroke-dasharray: 5 4; }
.fig .hf-solid { fill: var(--n-solid); }
.fig .hf-tint { fill: color-mix(in oklab, var(--n-solid) var(--fig-tint), var(--fig-paper)); stroke: var(--n-line); stroke-width: 1; }
.fig .hf-empty { fill: none; stroke: var(--n-line); stroke-width: 1; stroke-dasharray: 4 4; }
.fig .hf-edge { fill: none; stroke: var(--fig-line); stroke-width: 1.5; stroke-linecap: round; }
.fig .hf-edge--dashed { stroke-dasharray: 5 5; }
.fig .hf-edge--tone { stroke: var(--n-line); }
.fig .hf-ground { fill: none; stroke: var(--fig-ink); stroke-width: 2; }
.fig .hf-on-solid { fill: var(--fig-on-solid); }
.fig .hf-tone-text { fill: var(--n-line); }
.fig .hf-strong { font-weight: 600; }
.fig .hf-edge-label { font-style: italic; }
.fig .hf-halo { paint-order: stroke; stroke: var(--fig-paper); stroke-width: 4; stroke-linejoin: round; }
.fig .hf-flow { fill: var(--fig-ink); fill-opacity: .13; stroke: var(--fig-line); stroke-width: .75; transition: opacity var(--fig-ink-time); }
.fig .hf-flow--tone { fill: var(--n-line); fill-opacity: .3; stroke: var(--n-line); }
.fig .hf-flow.is-lit { fill-opacity: .24; }
.fig .hf-flow--tone.is-lit { fill-opacity: .55; }
.fig .hf-bar { fill: var(--fig-ink); }
.fig .hf-value { font-weight: 600; }
.fig .hf-hit { fill: transparent; stroke: none; }

/* Two loops of one geometry, held side by side at every width, so both tokens stay in view. */
.hf-loops { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-sm); }
.hf-loop .fig__title { text-align: center; margin-bottom: 0; }
.post-content .hf-loop .fig__title { margin-bottom: 0; }
.hf-tally { min-height: 2.8em; font-family: var(--font-sans); font-size: var(--text-xs); line-height: 1.4; text-align: center; color: var(--color-text-muted); }
.post-content .hf-tally { margin-bottom: var(--space-xs); }

/* Eras over one consumer band: columns wide, rows on a phone with the band down the side. */
.hf-eras { --hf-a: color-mix(in oklab, var(--fig-subject-line) calc(var(--fig-tint) * 1.6), var(--fig-paper)); --hf-b: color-mix(in oklab, var(--fig-cool-line) calc(var(--fig-tint) * 1.6), var(--fig-paper)); --hf-c: color-mix(in oklab, var(--fig-good-line) calc(var(--fig-tint) * 1.6), var(--fig-paper));
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); column-gap: var(--space-sm); }
.is-live .hf-era { cursor: pointer; }
.hf-era { grid-column: var(--era); grid-row: 1; padding-bottom: var(--space-sm); }
.hf-era__when { font-family: var(--font-sans); font-size: var(--text-xs); font-weight: 600; color: var(--color-text-muted); }
.hf-era__lead { font-size: var(--text-base); font-weight: 600; line-height: 1.25; }
.hf-era__rest { font-size: var(--text-sm); line-height: 1.35; color: var(--color-text-muted); margin-top: var(--space-xs); }
.hf-era.is-far :is(.hf-era__when, .hf-era__rest) { color: var(--hf-far-ink); opacity: .85; }
.hf-era.is-lit .hf-era__rest { color: var(--fig-ink); }
.hf-eras__band { position: relative; grid-column: 1 / -1; grid-row: 2; background: linear-gradient(to right, var(--hf-a) 30%, var(--hf-b) 50% 72%, var(--hf-c) 90%); border-radius: var(--fig-radius); }
.hf-marker { display: none; position: absolute; top: 0; left: calc((var(--hf-at) - .5) * 20%); width: .9rem; height: .9rem; margin: -.45rem; border-radius: 50%; background: var(--color-accent); border: .15rem solid var(--fig-paper); box-sizing: border-box; z-index: 2; transition: left var(--fig-ink-time) ease, top var(--fig-ink-time) ease; }
.fig--hand.is-picking .hf-marker { display: block; }
.hf-consumer { position: relative; z-index: 1; grid-row: 2; padding: var(--space-xs) var(--space-sm); font-size: var(--text-sm); font-style: italic; text-align: center; }
.fig--hand .hf-consumer.is-far { color: var(--fig-ink); }
.hf-consumer--a { grid-column: 1 / 3; }
.hf-consumer--b { grid-column: 3 / 5; }
.hf-consumer--c { grid-column: 5; padding-inline: 0; font-weight: 600; font-style: normal; }

/* A series as a thread: one line, a dot per post, the current post inked. */
ol.hf-path { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); column-gap: var(--space-sm); padding-inline: .13rem; }
.hf-path li { position: relative; padding-top: var(--space-md); font-size: var(--text-sm); line-height: 1.3; }
.hf-path li::before { content: ""; position: absolute; top: .3rem; left: 0; right: calc(var(--space-sm) * -1); border-top: var(--fig-rule) solid var(--fig-line); }
.hf-path li:last-child::before { right: 0; }
.hf-path li::after { content: ""; position: absolute; top: 0; left: 0; width: .69rem; height: .69rem; border-radius: 50%; background: var(--fig-paper); border: var(--fig-rule) solid var(--fig-line); box-sizing: border-box; }
.hf-path li.is-lit::after { background: var(--color-accent); border-color: var(--color-accent); }
.hf-path__n { display: block; font-family: var(--font-sans); font-size: var(--text-xs); font-weight: 600; color: var(--color-text-muted); }
.hf-path .is-here { font-weight: 600; }
.hf-path .is-here::after { background: var(--color-accent); border-color: var(--color-accent); }

/* A scale, not four boxes. Risk runs along the ramp, so no tick or cross. */
.hf-ramp { position: relative; height: 1.25rem; }
.hf-ramp__bar { position: absolute; top: 50%; left: 0; right: 0; height: .5rem; margin-top: -.25rem; border-radius: var(--fig-radius); background: linear-gradient(to right, var(--fig-good-line), var(--fig-caution-line), var(--fig-orange-line), var(--fig-bad-line)); }
.hf-marker--ramp { top: 50%; left: calc((var(--hf-at) - .5) * 25%); }
.hf-level { cursor: pointer; }
ol.hf-scale { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.hf-scale li { padding: var(--space-xs); text-align: center; }
.hf-level__name { font-family: var(--font-sans); font-size: var(--text-xs); font-weight: 600; letter-spacing: .04em; }
.hf-level__say { font-size: var(--text-sm); font-style: italic; line-height: 1.3; }

/* Search as two rails: the keyword rail is finished while the semantic one is still leaving. No clock: order only.
   Stations are dots on a thread, the map's own marks. */
.hf-rails { --hf-dot: .69rem; --hf-gap: var(--space-md); --hf-name: 1.5rem; --hf-fork: 1.4rem; position: relative; display: grid; gap: var(--hf-gap); }
.hf-lane { min-width: 0; }
.hf-lane { position: relative; }
.post-content .hf-lane__name { height: var(--hf-name); margin: 0; font-family: var(--font-sans); font-size: var(--text-xs); line-height: 1.2; font-weight: 600; letter-spacing: .04em; color: var(--color-text-muted); }
.hf-rail { position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); align-content: start; }
.hf-st { position: relative; padding: calc(var(--hf-dot) + var(--space-xs)) var(--space-xs) 0 0; font-size: var(--text-sm); line-height: 1.25; transition: color var(--fig-ink-time); }
.post-content .hf-st { margin: 0; }
.hf-st__dot { position: absolute; top: 0; left: 0; width: var(--hf-dot); height: var(--hf-dot); border-radius: 50%; box-sizing: border-box; background: var(--fig-paper); border: var(--fig-rule) solid var(--fig-line); z-index: 1; }
.hf-st::after { content: ""; position: absolute; top: calc(var(--hf-dot) / 2 - var(--fig-rule) / 2); left: 0; right: 0; border-top: var(--fig-rule) solid var(--fig-line); }
.hf-st:last-child::after { display: none; }
.hf-st--out .hf-st__dot { background: var(--fig-good-line); border-color: var(--fig-good-line); }
.hf-st--in .hf-st__dot { border: .13rem solid var(--fig-cool-line); }
.hf-st--in .hf-st__t { font-weight: 600; }
.hf-st.is-lit .hf-st__t { color: var(--fig-ink); }
.hf-rails .hf-token { display: block; position: absolute; left: 0; top: 0; width: .9rem; height: .9rem; margin: -.45rem; border-radius: 50%; background: var(--color-accent); border: .15rem solid var(--fig-paper); box-sizing: border-box; opacity: 0; transform: translate(var(--x, .45rem), var(--y, .45rem)); transition: transform calc(var(--fig-ink-time) * 1.6) ease; z-index: 2; }
.hf-rails .hf-token.is-on { opacity: 1; }
.hf-rails .hf-token.is-quiet { transition: none; }
.hf-run { position: relative; display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); row-gap: var(--space-sm); }
.hf-run > .hf-st--in { grid-column: 1; grid-row: 1; padding-right: var(--hf-fork); }
.hf-run > .hf-st--in::after { display: block; }
.hf-rail--key { grid-column: 2 / 4; grid-row: 1; }
.hf-rail--sem { grid-column: 2 / -1; grid-row: 2; }
/* The fork, one bracket from the start's thread down to the second rail. */
.hf-rail--key::before { content: ""; position: absolute; top: calc(var(--hf-dot) / 2 - var(--fig-rule) / 2); right: 100%; width: var(--hf-fork); height: calc(100% + var(--space-sm)); border-left: var(--fig-rule) solid var(--fig-line); border-bottom: var(--fig-rule) solid var(--fig-line); }
/* A carriage return: the build's thread runs off its last station, turns under the lane, and comes back to the start. */
.hf-rail--build .hf-st:last-child::after { display: block; }
.hf-rail--build::after { content: ""; position: absolute; top: calc(var(--hf-dot) / 2 - var(--fig-rule) / 2); bottom: calc(var(--hf-gap) / -2); right: 0; width: var(--space-sm); border-top: var(--fig-rule) solid var(--fig-line); border-right: var(--fig-rule) solid var(--fig-line); border-bottom: var(--fig-rule) solid var(--fig-line); border-radius: 0 var(--fig-radius) var(--fig-radius) 0; }
.hf-lane--run::before { content: ""; position: absolute; top: calc(var(--hf-gap) / -2); left: calc(var(--hf-dot) / 2 - var(--fig-rule) / 2); right: var(--space-sm); height: calc(var(--hf-gap) / 2 + var(--hf-name)); border-top: var(--fig-rule) solid var(--fig-line); border-left: var(--fig-rule) solid var(--fig-line); }
.hf-lane--run .hf-lane__name { padding-inline-start: calc(var(--hf-dot) + var(--space-xs)); }

/* Every point sits at its exact coordinates as a percentage of the plot, so the plot can change shape without moving
   one. A column keeps its label on one side: the third of each quadrant faces in, so it cannot cross the midline. */
.hf-matrix { --hf-tick: var(--text-sm); display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--space-xs); row-gap: var(--space-xs); }
.hf-plot { position: relative; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(2, minmax(0, 1fr)); aspect-ratio: 12 / 7; border-inline-start: .13rem solid var(--fig-ink); border-block-end: .13rem solid var(--fig-ink); }
.hf-cell { padding: var(--space-xs) var(--space-sm); font-size: var(--hf-tick); font-weight: 600; line-height: 1.2; background: var(--fig-region); }
.hf-cell--tr, .hf-cell--bl { background: color-mix(in oklab, var(--fig-ink) 2%, var(--fig-paper)); }
.hf-cell--tr, .hf-cell--br { text-align: right; }
.hf-cell--tl, .hf-cell--tr { border-block-end: var(--fig-rule) solid var(--fig-line); }
.hf-cell--tl, .hf-cell--bl { border-inline-end: var(--fig-rule) solid var(--fig-line); }
.hf-cell.is-lit { background: color-mix(in oklab, var(--color-accent) calc(var(--fig-tint) * .8), var(--fig-paper)); }
.fig--hand .hf-cell:focus-visible { outline-offset: -.13rem; }
ul.hf-points { position: absolute; inset: 0; pointer-events: none; }
.hf-pt { --hf-pt-box: 1.5rem; position: absolute; left: calc(var(--x) * 1% - var(--hf-pt-box) / 2); bottom: calc(var(--y) * 1% - var(--hf-pt-box) / 2); width: var(--hf-pt-box); height: var(--hf-pt-box); border-radius: 50%; font-size: var(--hf-tick); line-height: 1.1; pointer-events: auto; }
.hf-pt::before { content: ""; position: absolute; left: calc(50% - .28rem); top: calc(50% - .28rem); width: .56rem; height: .56rem; border-radius: 50%; background: var(--color-accent); }
.hf-pt.is-far::before { background: var(--hf-far-ink); opacity: var(--fig-far); }
.hf-pt.is-lit::before { box-shadow: 0 0 0 .2rem color-mix(in oklab, var(--color-accent) 30%, transparent); }
.hf-pt__hit { position: absolute; inset: 0; border-radius: 50%; }
.hf-pt__t { position: absolute; left: calc(50% + .55rem); top: 50%; transform: translateY(-50%); white-space: nowrap; }
.hf-pt--l .hf-pt__t { left: auto; right: calc(50% + .55rem); }
.hf-axis { display: flex; justify-content: space-between; align-items: center; gap: var(--space-xs); font-size: var(--hf-tick); font-style: italic; color: var(--fig-ink); }
.hf-axis::before { content: ""; order: 1; flex: 1; border-top: var(--fig-rule) solid var(--fig-line); }
.hf-axis::after { content: ""; order: 2; margin-inline-start: calc(var(--space-xs) * -1); border: .25rem solid transparent; border-left-color: var(--fig-line); border-left-width: .38rem; border-right-width: 0; }
.hf-axis span:last-child { order: 3; }
.hf-axis--y { grid-row: 1; flex-direction: row; writing-mode: vertical-rl; transform: rotate(180deg); }
.hf-axis--y::before { border-top: 0; border-left: var(--fig-rule) solid var(--fig-line); }
.hf-axis--y::after { margin-inline-start: 0; margin-block-start: calc(var(--space-xs) * -1); border-color: transparent; border-left-color: var(--fig-line); border-width: .25rem 0 .25rem .38rem; writing-mode: horizontal-tb; }
.hf-axis--x { grid-column: 2; }

/* A stack read as an argument: five questions down one thread, the answers beside each. */
.hf-stack { position: relative; display: grid; }
.hf-stack::before { content: ""; position: absolute; top: .75rem; bottom: 2rem; left: .31rem; border-left: var(--fig-rule) solid var(--fig-line); }
.hf-layer { position: relative; display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: var(--space-md); padding: var(--space-sm) 0 var(--space-sm) calc(.69rem + var(--space-sm)); border-top: var(--fig-rule) solid var(--color-border); }
.hf-layer:first-child { border-top: 0; }
.hf-layer__dot { position: absolute; left: 0; top: calc(var(--space-sm) + .35em); width: .69rem; height: .69rem; border-radius: 50%; box-sizing: border-box; background: var(--fig-paper); border: var(--fig-rule) solid var(--fig-line); }
.hf-layer.is-lit .hf-layer__dot { background: var(--color-accent); border-color: var(--color-accent); }
.fig--hand .hf-layer__q { min-height: var(--hf-tap); }
.hf-layer__ask { font-size: var(--text-lg, var(--text-base)); font-style: italic; line-height: 1.2; }
.hf-layer__name { margin-top: .15rem; font-family: var(--font-sans); font-size: var(--text-xs); font-weight: 600; letter-spacing: .04em; color: var(--color-text-muted); }
ul.hf-layer__items { display: grid; row-gap: .1rem; font-size: var(--text-sm); line-height: 1.3; }
.hf-layer.is-far :is(.hf-layer__name) { color: var(--hf-far-ink); }

@media (max-width: 40rem) {
  .hf-cap { padding-inline: var(--space-sm); }
  .hf-key.hf-key--choice { grid-template-columns: auto minmax(0, 1fr) auto; }
  .hf-key--choice .hf-count { grid-row: 2; grid-column: 1 / -1; }
  .hf-key--choice [data-key="stop"] { justify-self: center; }
  .hf-eras { grid-template-columns: 2.25rem minmax(0, 1fr); column-gap: var(--space-sm); }
  .hf-era { grid-column: 2; grid-row: var(--era); padding-block: 0 var(--space-sm); }
  .hf-era__rest { margin-top: 0; }
  .hf-eras__band { grid-column: 1; grid-row: 1 / span 5; background: linear-gradient(to bottom, var(--hf-a) 30%, var(--hf-b) 50% 72%, var(--hf-c) 90%); }
  .hf-marker { top: calc((var(--hf-at) - .5) * 20%); left: 100%; transition: top var(--fig-ink-time) ease; }
  .hf-marker--ramp { top: calc((var(--hf-at) - .5) * 25%); left: 50%; transition: top var(--fig-ink-time) ease; }
  .hf-consumer { grid-column: 1; padding: var(--space-xs) 0; writing-mode: vertical-rl; transform: rotate(180deg); justify-self: center; align-self: center; }
  .hf-consumer--a { grid-row: 1 / 3; }
  .hf-consumer--b { grid-row: 3 / 5; }
  .hf-consumer--c { grid-row: 5; }
  .hf-matrix { --hf-tick: var(--text-xs); }
  .hf-plot { aspect-ratio: 5 / 4; }
  .hf-cell { padding: var(--space-xs); }
  .hf-pt__t { left: calc(50% + .45rem); }
  .hf-pt--l .hf-pt__t { right: calc(50% + .45rem); left: auto; }
  .hf-pt--wrap .hf-pt__t { white-space: normal; width: min-content; }
  ol.hf-path { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .hf-path li { display: flex; gap: .3em; align-items: center; min-height: var(--hf-tap); padding: 0 0 0 calc(.69rem + .75rem); }
  .hf-path li::before { top: 50%; bottom: -50%; left: .31rem; right: auto; border-top: 0; border-left: var(--fig-rule) solid var(--fig-line); }
  .hf-path li:last-child::before { display: none; }
  .hf-path li::after { top: calc(50% - .345rem); }
  .hf-path__n { display: inline; font: inherit; color: inherit; }
  /* The ramp stands beside the levels, as the eras' band does, so the marker lines up with what it names. */
  .hf-spectrum { display: grid; grid-template-columns: .5rem minmax(0, 1fr); column-gap: var(--space-sm); padding-inline-start: .25rem; }
  .hf-ramp { height: auto; }
  .hf-ramp__bar { top: 0; bottom: 0; left: 0; right: 0; height: auto; margin: 0; background: linear-gradient(to bottom, var(--fig-good-line), var(--fig-caution-line), var(--fig-orange-line), var(--fig-bad-line)); }
  ol.hf-scale { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .hf-scale li { padding: 0; }
  .hf-level { display: flex; flex-direction: column; justify-content: center; min-height: var(--hf-tap); text-align: left; }
  .hf-loops { gap: var(--space-xs); }
  .hf-loop .fig__title { font-size: var(--text-sm); }
  .hf-rails { --hf-gap: var(--space-xs); }
  .hf-rail { grid-auto-flow: row; }
  .hf-st { min-height: 2.6rem; padding: 0 0 var(--space-xs) calc(var(--hf-dot) + var(--space-xs)); }
  .hf-st::after { top: var(--hf-dot); bottom: 0; right: auto; left: calc(var(--hf-dot) / 2 - var(--fig-rule) / 2); border-top: 0; border-left: var(--fig-rule) solid var(--fig-line); }
  .hf-rail--build .hf-st:last-child { padding-bottom: var(--space-sm); }
  .hf-rail--build .hf-st:last-child::after { bottom: calc(var(--hf-gap) * -1); }
  .hf-rail--build::after { display: none; }
  .hf-lane--run::before { top: 0; right: auto; height: var(--hf-name); border-top: 0; }
  .hf-run { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-sm); row-gap: var(--space-sm); }
  .hf-run > .hf-st--in { grid-column: 1 / -1; grid-row: 1; min-height: 0; padding-right: 0; padding-bottom: var(--space-sm); }
  .hf-run > .hf-st--in::after { bottom: calc(var(--space-sm) * -1); }
  .hf-rail--key { grid-column: 1; grid-row: 2; }
  .hf-rail--sem { grid-column: 2; grid-row: 2; }
  /* The fork: a branch off the start's thread, over to the second rail. */
  .hf-rail--key::before { top: calc(var(--space-sm) * -.5); left: calc(var(--hf-dot) / 2 - var(--fig-rule) / 2); right: calc(var(--space-sm) * -1 - var(--hf-dot) / 2); width: auto; height: calc(var(--space-sm) * .5); border-left: 0; border-bottom: 0; border-top: var(--fig-rule) solid var(--fig-line); border-right: var(--fig-rule) solid var(--fig-line); }
  .hf-layer { grid-template-columns: minmax(0, 1fr); gap: var(--space-xs); padding-block: var(--space-xs); }
  .hf-stack::before { bottom: 3rem; }
}
/* Nothing to hover on a touch screen: the recap follows the figure in the post anyway. */
@media (hover: none) { .fig--hand:has(.hf-path) .hf-cap { display: none; } }
@media (prefers-reduced-motion: reduce) { .fig--hand * { transition: none !important; } }

/* ---- Step through it --------------------------------------------------- */
/* At rest, one quiet line on the disclosure's row: a tall target that does not look it, and absolute, so a figure's
   height is the same with or without it. */
.fig__run {
  position: absolute; inset-block-start: calc((1lh + .3rem - 2.75rem) / 2); inset-inline-end: 0;
  display: flex; align-items: center; min-height: 2.75rem; padding: 0 0 0 var(--space-sm);
  font-family: var(--font-sans); font-size: var(--text-xs); line-height: inherit; color: var(--color-text-muted);
  background: none; border: 0; cursor: pointer;
  text-decoration: underline; text-decoration-color: var(--color-border); text-underline-offset: .2em;
}
.fig__run:hover { color: var(--color-text); }
.fig__run[hidden] { display: none; }
/* Running: the same family as the Turn Lab's stepper, on the page and with no card. Back, count and Next on one row, the
   answers under it, dots, then the caption last, so a long sentence never moves a button under the finger. */
.fig__panel, .hf-panel { display: grid; gap: var(--space-xs); margin-top: var(--space-sm); padding-block: var(--space-xs); background: var(--fig-paper); font-family: var(--font-sans); }
.fig__panel.is-tall { position: sticky; bottom: 0; z-index: 2; border-top: var(--fig-rule) solid var(--color-border); padding-bottom: max(var(--space-xs), env(safe-area-inset-bottom)); }
.fig__bar, .hf-key { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--space-sm); }
.fig__count, .hf-count { justify-self: center; margin: 0; font-size: var(--text-ui); font-variant-numeric: tabular-nums; color: var(--color-text-muted); white-space: nowrap; }
.fig__key, .hf-btn {
  min-height: 2.75rem; padding: var(--space-xs) var(--space-sm); font-family: var(--font-sans); font-size: var(--text-ui); font-weight: 600; line-height: 1.25; text-align: start;
  color: var(--color-text); background: var(--fig-paper); border: thin solid var(--color-border); border-radius: .4em; cursor: pointer;
}
.fig__key:hover:not(:disabled, [aria-disabled="true"]), .hf-btn:hover:not([aria-disabled="true"]) { border-color: var(--color-accent); color: var(--color-text); }
.fig__key--go, .hf-btn--go { color: var(--fig-paper); background: var(--color-accent); border-color: var(--color-accent); }
.fig__key--go:hover:not(:disabled, [aria-disabled="true"]), .hf-btn--go:hover:not([aria-disabled="true"]) { color: var(--fig-paper); background: var(--color-accent-hover); }
.fig__key--answer { font-weight: 400; border-color: var(--color-accent); }
.fig__key--quiet { padding: 0 0 0 var(--space-sm); font-size: var(--text-xs); font-weight: 400; color: var(--color-text-muted); background: none; border: 0; text-decoration: underline; text-decoration-color: var(--color-border); text-underline-offset: .2em; }
/* Chrome sends a disabled button no mousedown, so a press on it would blur the run's focus: it falls to the panel instead. */
.fig__key:disabled { pointer-events: none; text-decoration: none; opacity: .45; }
/* Next at a decision holds the focus, so it stays legible: no fill, muted ink, a border to see. */
.fig__key[aria-disabled="true"], .hf-btn[aria-disabled="true"] { cursor: default; color: var(--color-text-muted); background: none; border-color: var(--color-text-muted); }
.fig__key--quiet[aria-disabled="true"] { text-decoration: none; }
.fig__answers { display: flex; flex-wrap: wrap; gap: var(--space-xs); }
.fig__answers:empty { display: none; }
.fig .fig__dots, .fig .hf-dots { display: flex; flex-wrap: wrap; justify-content: center; margin: 0; padding: 0; list-style: none; }
.fig .fig__dots li, .fig .hf-dots li { margin: 0; padding: 0; }
.fig__dot, .hf-dot { display: grid; place-items: center; width: 1.75rem; height: 1.75rem; padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: pointer; }
.fig__dot::before, .hf-dot::before { content: ""; width: .7rem; height: .7rem; border: thin solid var(--color-text-muted); border-radius: 50%; }
.fig__dot.is-done::before, .hf-dot.is-done::before { background: var(--color-text-muted); }
.fig__dot[aria-current="step"]::before, .hf-dot[aria-current="step"]::before { background: var(--color-accent); border-color: var(--color-accent); transform: scale(1.2); }
.fig__dot:hover::before, .hf-dot:hover::before { border-color: var(--color-accent); }
.fig__aside { position: absolute; inset-block-start: calc((1lh + .3rem - 2.75rem) / 2); inset-inline-end: 0; display: flex; font-size: var(--text-xs); }
/* At the run's end it joins the panel: under the caption, or above Next where a stuck panel grows upward. On a short panel near the fold the added row can still shift Next a little. */
.fig__panel .fig__aside { position: static; justify-content: flex-end; }
.fig__panel.is-tall .fig__aside { order: -1; }
.fig__line, .hf-cap { margin: 0; padding-inline-start: var(--space-sm); border-inline-start: .25em solid var(--color-accent); font-family: var(--font-serif); font-size: var(--text-sm); line-height: 1.4; color: var(--color-text); }
.fig__line strong, .hf-cap strong { font-family: var(--font-sans); font-weight: 600; }
.fig.is-stepping .fig__fold { display: none; }
.fig.is-stepping .is-touchable { cursor: default; }
.fig.is-stepping [data-run="answer"].is-touchable { cursor: pointer; }
.fig-thread.is-still { animation: none; stroke-dashoffset: 0; }
.fig-thread.is-pointed { stroke-dasharray: .02 .02; }

/* The run's paint. Now is Trace's here, ahead is its far, been is the figure as drawn with its edges inked in. A step
   waiting at a join holds in ink, and the steps a decision can go to are ringed: they are answers. */
@media not print {
  .fig.is-stepping .flowchart-link[data-run="ahead"] { opacity: var(--fig-far); }
  .fig.is-stepping .cluster[data-run="ahead"] rect { opacity: var(--fig-far); }
  .fig.is-stepping .node[data-run="ahead"] { --n-ink: color-mix(in oklab, var(--fig-ink) var(--fig-far-ink), var(--fig-paper)); --n-stroke: var(--fig-line); }
  .fig.is-stepping .edgeLabels > g.edgeLabel[data-run="ahead"] { --n-ink: color-mix(in oklab, var(--fig-ink) var(--fig-far-ink), var(--fig-paper)); }
  .fig.is-stepping .node:is([data-run="ahead"], [data-run="answer"])[data-strength="solid"] { --n-fill: color-mix(in oklab, var(--n-solid) var(--fig-tint), var(--fig-paper)); --n-stroke: var(--n-line); }
  .fig.is-stepping .node[data-run="answer"][data-strength="solid"] { --n-ink: var(--fig-ink); }
  .fig.is-stepping .node[data-run="now"] { --fig-node-width: 2.25; --n-stroke: var(--color-accent); }
  .fig.is-stepping .node[data-run="now"][data-strength="solid"], .fig.is-stepping .node[data-run="wait"] { --fig-node-width: 2.25; --n-stroke: var(--fig-ink); }
  .fig.is-stepping .node[data-run="answer"] { --fig-node-width: 2; --n-stroke: var(--color-accent); }
  .fig.is-stepping .node[data-run="answer"] :is(rect, polygon, circle, ellipse, path):not(.label *) { stroke-dasharray: 5 3; }
  /* A press near the last one is refused: the ring goes quiet until the gate lifts (step.js, settle). */
  .fig.is-stepping .node.is-settling { --n-stroke: var(--color-text-muted); --n-ink: var(--color-text-muted); }
  .fig.is-stepping .cluster:is([data-run="now"], [data-run="answer"]) rect { stroke: var(--color-accent); stroke-width: 2.25; }
  .fig.is-stepping .cluster[data-run="now"] rect { stroke-dasharray: none; }
  .fig.is-stepping .cluster[data-run="answer"] rect { stroke-dasharray: 5 3; }
  .fig.is-stepping [data-et="message"][data-run="ahead"], .fig.is-stepping [data-et="note"][data-run="ahead"] rect { opacity: var(--fig-far); }
  .fig.is-stepping .messageText[data-run="ahead"], .fig.is-stepping [data-et="note"][data-run="ahead"] .noteText { fill: color-mix(in oklab, var(--fig-ink) var(--fig-far-ink), var(--fig-paper)); }
  .fig.is-stepping [data-et="message"][data-run="now"] { stroke: var(--color-accent); stroke-width: 2; }
  .fig.is-stepping [data-et="message"][data-run="been"] { stroke: var(--fig-ink); }
  .fig.is-stepping .messageText[data-run="now"] { font-weight: 600; }
  .fig.is-stepping [data-et="note"][data-run="now"] rect, .fig.is-stepping [data-et="participant"][data-run="now"] rect { stroke: var(--color-accent); stroke-width: 2; }
}

/* Paper: every figure whole and at rest, none of the controls. Inline widths and the edge fade need the overrides. */
@media print {
  .fig { break-inside: avoid; }
  .fig * { transition: none !important; }
  .fig__stage, .fig__stage.is-capped:not(.is-open), .post-content .fig__stage[data-fit="scroll"] { max-height: none; overflow: visible; mask-image: none !important; -webkit-mask-image: none !important; animation: none; }
  .fig__stage[data-fit="scroll"] svg { width: 100% !important; max-width: 100% !important; }
  /* A figure taller than a page scales to fit one: unbreakable, it would otherwise leave a page holding only its rule. */
  .fig__stage svg { max-height: calc(100vh - 6rem); }
  .fig__fold, .fig__say, .fig__hint, .fig__text:not([open]), .fig-thread, .fig__run, .fig__panel, .fig__aside, .hf-ctl, .hf-panel, .hf-cap, .hf-token, .hf-marker { display: none !important; }
  .fig__foot { min-height: 0; margin-top: 0; }
  .fig--hand .is-far { opacity: 1 !important; }
  .fig.is-tracing :is(.node, .flowchart-link, .edgeLabel, .cluster, .cluster-label, [data-et], .messageText, g.link, g.node-labels text) { opacity: 1 !important; }
}

@media (prefers-reduced-motion: reduce) {
  .fig * { transition: none !important; }
  .fig-thread { animation: none; stroke-dashoffset: 0; }
}
