/* Algorithm-discovery view (views/algorithm/*). The 12-step Hidden Structure
   walkthrough. Everything is scoped under .algorithm-view so these rules never
   leak into the figure walkthrough.

   Visual contract: the renderers emit structural classes + data-* attributes
   and lean on `currentColor` for accents (so the CSS layer drives hue via
   `color:`). Matrix cells carry no inline background, so they're styled here
   like the canonical TSM in matrix.css. Region palette (--color-core/shared/
   control/peripheral) is shared with the rest of the app via theme.css.

   Voice (linxule.com counterpoint): step titles + caption + verdict prose are
   the human voice (Cormorant); labels, indicators, controls, chain/annotation
   tags, data cells are the machine voice (IBM Plex Mono). The violet bloom is
   earned on interaction — semantic warmth (the core, leakage, feedback) uses
   --warm / --color-* tokens, never the interaction accent. */

/* ---------------------------------------------------------------- shell --- */

/* Box-less (2026-05-29). Marginalia layout (2026-05-30): the view fills #tsm
   (full content width in view-algorithm); the inner .algorithm-layout owns a
   3-region grid — rail / plate / cockpit — mirroring the figure walkthrough so
   the two views read as the same document. The old centred single column left
   both side-margins empty while the matrix sat capped at 560px; the rail +
   cockpit now frame the plate and the matrix grows toward the viewport. */
.algorithm-view {
  /* Chrome above the centre matrix (page header + stage padding); the matrix
     square caps at calc(100vh - this) so the whole dense grid fits the fold. A
     token (the figure plate uses --matrix-chrome:312px; this view's cockpit
     carries the caption, so less sits above the plate) shared by the
     .algorithm-matrix rule AND step-6's inline VFO grid. */
  --algo-matrix-chrome: 200px;
  padding: 4px 0 24px;
}

/* rail | plate | cockpit. Capped + centred so the matrix sits on a framed
   plate, not a full-bleed sprawl; proportions echo .layout (220/1fr/340),
   tightened for the denser 12-step view. */
.algorithm-layout {
  display: grid;
  grid-template-columns: 184px minmax(0, 1fr) 320px;
  gap: 0 40px;
  align-items: start;
  max-width: 1380px;
  margin: 0 auto;
}

/* ---- Left rail: 12-step index, grouped by phase (orientation only) ---- */
.algorithm-rail {
  position: sticky;
  top: 88px; /* match the figure .narrative's spine-clearance (was 84) */
  align-self: start;
  max-height: calc(100vh - 112px);
  overflow-y: auto;
}

.algorithm-rail-phase {
  margin: 16px 0 7px;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  color: var(--muted);
}
.algorithm-rail-phase:first-child { margin-top: 0; }

.algorithm-rail-step {
  display: flex;
  gap: 9px;
  padding: 3px 0;
  font-size: 0.8rem;
  line-height: 1.3;
  color: var(--muted);
}

.algorithm-rail-num {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--muted); /* was --rule (#c8c8c8) → ~1.5:1, effectively invisible */
  flex: none;
  width: 1.3em;
  text-align: right;
  padding-top: 0.2em;
}

/* Machine voice (mono) to match the figure view's scene-index — the left index
   is structural "table of contents" furniture, not prose; the same sticky slot
   shouldn't switch voices when you toggle between the two views. */
.algorithm-rail-label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  line-height: 1.35;
}

/* Current step — ink weight (cyan stays the spine's single accident). */
.algorithm-rail-step.current { color: var(--ink); }
.algorithm-rail-step.current .algorithm-rail-num { color: var(--ink); font-weight: 600; }
.algorithm-rail-step.current .algorithm-rail-label { font-weight: 500; }

/* ---- Centre: the stage ---- */
.algorithm-main { min-width: 0; }

.algorithm-stage {
  min-height: 320px;
  padding: 0 0 8px;
  overflow-x: auto;
}

/* ---- Right: the cockpit (sticky) ---- */
.algorithm-cockpit {
  position: sticky;
  top: 88px; /* match the figure .narrative's spine-clearance (was 84) */
  align-self: start;
  /* Mirror the rail's guard so a long Step-10/11 caption scrolls within the
     cockpit instead of clipping below the fold (omitting it defeats the sticky
     guarantee). */
  max-height: calc(100vh - 112px);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

/* DOM order is title → caption → controls (caption-first, so a screen reader
   meets the explanation before the buttons); `order` lifts the controls above
   the caption visually so Next/Back hold position as the caption length swings. */
.algorithm-cockpit .algorithm-step-title { order: -2; }
.algorithm-cockpit .algorithm-controls { order: -1; }

.algorithm-step-title {
  font-family: var(--font-body);
  font-size: clamp(1.2rem, 1.5vw, 1.5rem);
  font-weight: 400;
  line-height: 1.18;
  margin: 0 0 14px;
  color: var(--ink);
}

.algorithm-caption {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink);
}

/* Narrow / single-column: hide the rail; the cockpit goes display:contents so
   its children join the layout flex and the MATRIX can sit between the controls
   and the caption — title → controls → matrix → caption (the matrix isn't
   buried below the whole cockpit, the regression the figure view already fixed). */
/* Breakpoint at 1100 (not 1024): below it the 3-col centre track starves the
   dense matrix, so single-column — where the matrix gets the full width — reads
   better than a cramped three columns. */
@media (max-width: 1100px) {
  .algorithm-layout {
    display: flex;
    flex-direction: column;
    max-width: 720px;
  }
  .algorithm-rail { display: none; }
  .algorithm-cockpit { display: contents; }
  .algorithm-cockpit .algorithm-step-title { order: -3; }
  .algorithm-cockpit .algorithm-controls { order: -2; }
  .algorithm-main { order: -1; }
  .algorithm-cockpit .algorithm-caption { order: 0; }
  .algorithm-step-title { font-size: clamp(1.4rem, 4vw, 1.7rem); }
}

@media (max-width: 600px) {
  .algorithm-view {
    padding: 0 0 16px;
  }
}

/* ------------------------------------------------------------- controls --- */

/* In the cockpit, the controls are a nav strip between the title and the
   caption: a hairline below sets the nav off from the prose. */
.algorithm-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 16px;
  padding: 0 0 14px;
  border-bottom: 1px solid var(--rule);
}

/* Box-less text controls (2026-05-29), matching the figure walkthrough: no
   fills, no borders. Next is the emphasized action (ink); the rest are muted. */
.algorithm-controls button {
  padding: 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: color 200ms ease, opacity 200ms ease;
}

.algorithm-controls button:hover:not(:disabled) {
  color: var(--bloom);
}

.algorithm-controls button:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Next is the primary action — ink, pushed to the right edge of the row. */
.algorithm-controls .algorithm-next {
  color: var(--ink);
  margin-left: auto;
}

.algorithm-controls .algorithm-next:hover:not(:disabled) {
  color: var(--bloom);
}

.algorithm-controls .algorithm-indicator {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

/* The "← Back to the figures" on-ramp toggle (lives in .scene-selector). */
/* Box-less (2026-05-29): the mode toggle is a quiet machine-voice line, not a
   boxed button — it lives in .mode-bar under the header (and must stay visible
   in both views). */
.view-toggle {
  padding: 0;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: color 200ms ease;
}

.view-toggle:hover {
  color: var(--bloom);
}

.view-toggle.active {
  color: var(--ink);
}

.algorithm-load-error {
  padding: 16px;
  border: 1px dashed var(--warm);
  border-radius: 2px;
  color: var(--warm);
  font-size: 14px;
}

/* --------------------------------------------- Step 1 / 2: component tiles --- */

.algorithm-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: 8px;
  margin: 4px 0;
}

/* Box-less (2026-05-29): no border, no fill, no left-rail. Each tile is just a
   label + a kind line carrying a small semantic dot (see ::before below) — the
   left-rail "pill" treatment Xule disliked is gone. Family colour now reads as
   a dot, the same idiom as the verdict bullets + matrix legend. */
.algorithm-tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 4px 0;
}

.algorithm-tile-label {
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.25;
  color: var(--ink);
}

.algorithm-tile-kind {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}

/* Dot vocabulary (declared intent, 2026-05-29): ROUND dots = a category/family
   TAG — entity family (here), VFI/VFO annotation kind, matrix-legend families.
   SQUARE bullets (border-radius:2px) = a four-square REGION result (Step-10
   verdict bullets), echoing the square region blocks inside the matrix. The two
   shapes are kept distinct ON PURPOSE; don't unify them.

   Semantic family dot — replaces the old left rail. A small disc before the
   kind line, coloured by entity family. SEMANTIC colours (--color-* tokens),
   never the interaction accent. Default grey; tinted per family below. */
.algorithm-tile-kind::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 7px;
  vertical-align: baseline;
  background: var(--rule);
}
.algorithm-tile[data-entity-type*="runtime"]  .algorithm-tile-kind::before { background: var(--color-core); }
.algorithm-tile[data-entity-type*="protocol"] .algorithm-tile-kind::before { background: var(--color-core); }
.algorithm-tile[data-entity-type*="agent"]    .algorithm-tile-kind::before { background: var(--color-control); }
.algorithm-tile[data-entity-type*="subagent"] .algorithm-tile-kind::before { background: var(--color-control); }
.algorithm-tile[data-entity-type*="skill"]    .algorithm-tile-kind::before { background: var(--color-shared); }
.algorithm-tile[data-entity-type*="tool"]     .algorithm-tile-kind::before { background: var(--color-case); }
.algorithm-tile[data-entity-type*="provider"] .algorithm-tile-kind::before { background: var(--color-screen); }

/* Color-rail key (Step 1). Decodes the per-tile left-rail families. */
.algorithm-tile-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--muted);
}

.algorithm-tile-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.algorithm-tile-legend-swatch {
  width: 9px;
  height: 9px;
  border-radius: 50%; /* round, matching the per-tile family dots */
  display: inline-block;
  flex: none;
}

/* Step 2: exemplar tiles laid in a row + the direction list + pop-out. */
.algorithm-tiles-with-arrows {
  grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
  justify-content: start;
  align-items: start; /* don't stretch exemplar tiles to the arrow-list height */
}

/* The direction list is a DOM child of the tiles wrap — drop it to its own
   full-width row below the tiles rather than letting it ride as a grid cell. */
.algorithm-tiles-with-arrows .algorithm-arrows {
  grid-column: 1 / -1;
  margin-top: 10px;
}

.algorithm-arrows {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 14px 0 4px;
}

.algorithm-arrow {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--forward);
  padding: 4px 0;
}

/* Arrow text (human labels + relation) is set by the renderer; mutual pairs
   carry the warm/feedback color. */
.algorithm-arrow[data-kind="mutual"] {
  color: var(--backward);
}

/* Structural aside (Step 2 "social network ↔ DSM"). An inset callout in the
   book's concept-box register: soft paper-dark ground, machine-voice title. */
/* Box-less (2026-05-29): structural aside set off by a top hairline + its mono
   title, not a filled box. (A rule is fine; it's the boxes Xule wanted gone.) */
.algorithm-popout {
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
}

.algorithm-popout-title {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--muted);
  margin-bottom: 6px;
}

.algorithm-popout-body {
  margin: 0;
  font-size: 0.95rem;
  color: var(--ink-light);
  line-height: 1.55;
}

/* ---------------------------------------------------- shared matrix grids --- */
/* Steps 3, 5, 6, 7, 8, 9 all render an NxN grid of .algorithm-matrix-cell. */

/* Viewport-bound square (matches the figure plate's sizing idiom): grows with
   the centre column but caps at the fold so the whole dense matrix is visible
   without a zoom-out. Centred in the stage. */
.algorithm-matrix {
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  width: 100%;
  max-width: min(640px, calc(100vh - var(--algo-matrix-chrome, 200px)));
  aspect-ratio: 1;
  margin: 4px auto 0;
}

.algorithm-matrix-cell {
  background: var(--bg);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: clamp(7px, 1.3vw, 12px);
  color: var(--muted);
  transition: background-color 320ms ease, color 320ms ease, transform 300ms ease-out;
}

.algorithm-matrix-cell.diagonal {
  background: var(--diagonal-bg);
  color: var(--diagonal-ink);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(7px, 1.1vw, 11px);
  letter-spacing: 0.01em;
  padding: 0 2px;
  white-space: nowrap;
}

.algorithm-matrix-cell.dependency.direct {
  color: var(--ink);
  font-weight: 700;
}

.algorithm-matrix-cell.dependency.indirect {
  color: var(--muted);
}

/* Cluster (Step 7) + Core (Step 8) block shading. The renderer tags every
   cell inside the diagonal block; we tint the whole square so the knot reads
   as a region, and ring the diagonal members. Warm tints track --warm. */
.algorithm-matrix-cell.in-cluster {
  background: var(--warm-tint-2);
}

.algorithm-matrix-cell.in-core {
  background: var(--warm-tint-3);
}

.algorithm-matrix-cell.in-core.diagonal,
.algorithm-matrix-cell.in-cluster.diagonal {
  background: var(--color-core);
  color: var(--paper);
}

/* Region-colored diagonal cells (Step 9 four-square + Step 11 final TSM). */
.algorithm-matrix-cell.diagonal.region-core,
.algorithm-final-tsm-cell.diagonal.region-core {
  background: var(--color-core);
  color: var(--paper);
}
.algorithm-matrix-cell.diagonal.region-shared,
.algorithm-final-tsm-cell.diagonal.region-shared {
  background: var(--color-shared);
  color: var(--paper);
}
.algorithm-matrix-cell.diagonal.region-control,
.algorithm-final-tsm-cell.diagonal.region-control {
  background: var(--color-control);
  color: var(--paper);
}
.algorithm-matrix-cell.diagonal.region-peripheral,
.algorithm-final-tsm-cell.diagonal.region-peripheral {
  background: var(--color-peripheral);
  color: var(--paper);
}

.algorithm-matrix-legend {
  color: var(--muted);
}

.algorithm-legend-item[data-kind="direct"] { color: var(--ink); }
.algorithm-legend-item[data-kind="indirect"] { color: var(--muted); }

/* ----------------------------------------------- Step 4: dependency chains --- */

.algorithm-step-4,
.algorithm-step-content {
  font-size: 15px;
}

/* Box-less (2026-05-29): chains were a box containing boxed tiles (box-in-box).
   Now the chain is just spacing + its mono label; the nodes read as text with
   coloured arrows between them. */
.algorithm-chain {
  margin: 0 0 16px;
}

.algorithm-chain-label {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  margin-bottom: 10px;
}

.algorithm-chain-tile {
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--ink);
}

.algorithm-chain-arrow {
  color: var(--forward);
  font-family: var(--font-mono);
  font-weight: 700;
}

.algorithm-chain-indirect {
  margin-top: 12px;
  padding-top: 10px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--warm);
}

.algorithm-step-annotation {
  margin: 14px 0 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-light);
}

/* --------------------------------------- Step 6: VFI/VFO counting layout --- */

.algorithm-vfi-vfo-layout {
  --vfivfo-ink: var(--muted);
}

.algorithm-vfo-cell,
.algorithm-vfi-cell {
  font-family: var(--font-mono);
  font-size: clamp(8px, 1.2vw, 12px);
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-variant-numeric: tabular-nums;
}

/* Axis headers (Fan-Out over the right column, Fan-In beside the bottom row).
   Machine voice — the margins are data, so they're labelled in mono. */
.algorithm-axis-header {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  white-space: nowrap;
  align-self: center;
}

/* Plain-terms key: spells out what VFO / VFI count and where the margin lives.
   A top hairline sets it off from the matrix; two mono lines, no box. */
.algorithm-vfivfo-key {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}

.algorithm-vfivfo-key-item {
  margin: 0 0 4px;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink-light);
}

.algorithm-vfivfo-key-term {
  font-weight: 600;
  color: var(--ink);
}

.algorithm-vfivfo-key-abbr {
  font-family: var(--font-mono);
  font-size: 0.78em;
  color: var(--muted);
}

/* Box-less (2026-05-29): the VFI/VFO annotations were another left-rail "pill".
   Now a leading semantic dot (same idiom as the tiles + verdict bullets), no
   box, no rail. The lead phrase ("Highest Fan-In —") picks up the dot colour so
   the coloured dot reads as a cue, not a riddle (2026-05-30). */
.algorithm-annotations .algorithm-annotation {
  position: relative;
  margin: 0;
  padding: 6px 0 6px 16px;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--ink-light);
}

.algorithm-annotation-lead {
  font-weight: 600;
}

.algorithm-annotations .algorithm-annotation::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--rule);
}

.algorithm-annotation[data-kind="high-vfi"]::before { background: var(--color-control); }
.algorithm-annotation[data-kind="high-vfo"]::before { background: var(--warm); }
.algorithm-annotation[data-kind="high-vfi"] .algorithm-annotation-lead { color: var(--color-control); }
.algorithm-annotation[data-kind="high-vfo"] .algorithm-annotation-lead { color: var(--warm); }

/* ----------------------------------------------- Step 7: cycle reveal --- */

.algorithm-cycle-cluster {
  color: var(--color-core);
  border-radius: 2px;
  background: var(--warm-tint-1);
  line-height: 1.45;
}

.algorithm-cycle-cluster.algorithm-no-cycles {
  color: var(--muted);
  background: transparent;
}

.algorithm-cycle-inset {
  color: var(--color-core);
}

/* Box-less (2026-05-29): cycle members read as text with coloured arrows
   between them (matching the de-boxed chain tiles), not bordered chips. */
.algorithm-cycle-node {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--ink);
}

.algorithm-cycle-arrow {
  color: var(--color-core);
  font-family: var(--font-mono);
  font-weight: 700;
}

/* Ellipsis node when a large cycle's loop is capped (Step 7). */
.algorithm-cycle-ellipsis {
  color: var(--muted);
  font-family: var(--font-mono);
}

/* ----------------------------------------------- Step 8: Core block --- */

.algorithm-core-block {
  color: var(--color-core);
  border-radius: 2px;
  background: var(--warm-tint-1);
  line-height: 1.45;
}

.algorithm-core-label {
  background: var(--color-core);
  color: var(--paper) !important;
  border-radius: 2px;
}

.algorithm-core-label.algorithm-no-core {
  background: transparent;
  color: var(--muted) !important;
}

/* ----------------------------------------------- Step 9: four-square --- */

.algorithm-regions {
  color: var(--muted);
}

/* Leading-dot idiom (matching Step 10's verdict bullets + the scatter key):
   text in AA-passing --ink-light, region hue on the dot — replaces the inline
   currentColor "chip" border, which both failed text-contrast AA in region hue
   and read as a box in a box-less view. */
.algorithm-region,
.algorithm-region-empty {
  position: relative;
  padding-left: 16px;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--ink-light);
}

.algorithm-region::before,
.algorithm-region-empty::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
}

.algorithm-region[data-region="core"]::before       { background: var(--color-core); }
.algorithm-region[data-region="shared"]::before     { background: var(--color-shared); }
.algorithm-region[data-region="control"]::before    { background: var(--color-control); }
.algorithm-region[data-region="peripheral"]::before { background: var(--color-peripheral); }

/* Scatter inset — dots use inline `background: currentColor`, so we drive hue
   via `color:` per region. */
.algorithm-scatter-inset {
  color: var(--rule);
  border: 1px solid var(--rule); /* moved off the inline currentColor */
  border-radius: 2px;
  background: var(--bg);
}

/* Per-region count key under the scatter (round swatches = family tag idiom). */
.algorithm-scatter-key {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 10px;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  color: var(--ink-light);
}

.algorithm-scatter-key-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.algorithm-scatter-key-swatch {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--muted);
  flex: none;
}

.algorithm-scatter-key-item[data-region="core"]       .algorithm-scatter-key-swatch { background: var(--color-core); }
.algorithm-scatter-key-item[data-region="shared"]     .algorithm-scatter-key-swatch { background: var(--color-shared); }
.algorithm-scatter-key-item[data-region="control"]    .algorithm-scatter-key-swatch { background: var(--color-control); }
.algorithm-scatter-key-item[data-region="peripheral"] .algorithm-scatter-key-swatch { background: var(--color-peripheral); }

.algorithm-scatter-dot {
  box-shadow: 0 0 0 2px var(--bg);
}

.algorithm-scatter-dot.region-core       { color: var(--color-core); }
.algorithm-scatter-dot.region-shared     { color: var(--color-shared); }
.algorithm-scatter-dot.region-control    { color: var(--color-control); }
.algorithm-scatter-dot.region-peripheral { color: var(--color-peripheral); }
.algorithm-scatter-dot[data-region="unassigned"] { color: var(--muted); }

.algorithm-scatter-axis {
  color: var(--muted);
  font-family: var(--font-mono);
}

.algorithm-four-square-notice {
  color: var(--muted);
  line-height: 1.5;
}

/* ----------------------------------------------- Step 10: verdict --- */

.algorithm-verdict-headline {
  font-family: var(--font-body);
  font-size: 1.4rem;
  font-weight: 500;
  color: var(--ink);
}

.algorithm-verdict-bullet {
  position: relative;
  padding-left: 18px !important;
  font-size: 0.95rem;
  line-height: 1.5;
}

.algorithm-verdict-bullet::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--muted);
}

.algorithm-verdict-bullet[data-region="core"]::before       { background: var(--color-core); }
.algorithm-verdict-bullet[data-region="shared"]::before     { background: var(--color-shared); }
.algorithm-verdict-bullet[data-region="control"]::before    { background: var(--color-control); }
.algorithm-verdict-bullet[data-region="peripheral"]::before { background: var(--color-peripheral); }

.algorithm-verdict-sentence {
  font-size: 1.05rem;
  line-height: 1.6;
  color: var(--ink-light);
  max-width: 60ch;
  padding-top: 6px;
}

/* ----------------------------------------------- Step 11: final TSM --- */

/* Leading-dot idiom (see .algorithm-region): ink-light label, region hue on the
   dot, no chip border. */
.algorithm-final-tsm-region-band {
  position: relative;
  padding-left: 15px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--ink-light);
}

.algorithm-final-tsm-region-band::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
}

.algorithm-final-tsm-region-band[data-region="core"]::before       { background: var(--color-core); }
.algorithm-final-tsm-region-band[data-region="shared"]::before     { background: var(--color-shared); }
.algorithm-final-tsm-region-band[data-region="control"]::before    { background: var(--color-control); }
.algorithm-final-tsm-region-band[data-region="peripheral"]::before { background: var(--color-peripheral); }

.algorithm-final-tsm-grid {
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  width: 100%;
  max-width: min(640px, calc(100vh - var(--algo-matrix-chrome, 200px)));
  aspect-ratio: 1;
  margin: 0 auto;
}

.algorithm-final-tsm-cell {
  background: var(--bg);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: clamp(7px, 1.3vw, 12px);
  color: var(--muted);
}

.algorithm-final-tsm-cell.diagonal {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(7px, 1.1vw, 11px);
  background: var(--diagonal-bg);
  color: var(--diagonal-ink);
  padding: 0 2px;
  white-space: nowrap;
}

.algorithm-final-tsm-cell.transfer.forward { color: var(--forward); font-weight: 700; }
.algorithm-final-tsm-cell.transfer.backward { color: var(--backward); font-weight: 700; }

.algorithm-final-tsm-summary {
  color: var(--muted);
}

/* Export button. */
.algorithm-export-btn {
  padding: 8px 16px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: var(--ink);
  color: var(--paper);
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease;
}

.algorithm-export-btn:hover {
  background: var(--bloom);
  border-color: var(--bloom);
}

.algorithm-export-status {
  color: var(--muted);
}

/* ----------------------------------------------- Step 12: try your own --- */

.algorithm-try-your-own-headline {
  font-family: var(--font-body);
  font-size: 1.4rem;
  font-weight: 500;
  color: var(--ink);
}

.algorithm-drop-zone {
  color: var(--ink-light);
  border-radius: 2px;
  background: var(--paper-dark);
  transition: background 200ms ease, border-color 200ms ease, color 200ms ease;
}

.algorithm-drop-zone:hover,
.algorithm-drop-zone[data-state="hover"] {
  color: var(--bloom);
  background: color-mix(in srgb, var(--bloom) 9%, transparent);
}

.algorithm-drop-zone[data-state="error"] { color: var(--warm); }
.algorithm-drop-zone[data-state="loaded"] { color: var(--color-shared); }

.algorithm-drop-zone-prompt {
  color: var(--ink);
  font-size: 0.95rem;
}

.algorithm-drop-zone-status {
  color: var(--muted);
}

.algorithm-input-format-explainer {
  color: var(--ink-light);
  line-height: 1.55;
}

.algorithm-input-format-sample {
  color: var(--ink-light);
  font-family: var(--font-mono);
  background: var(--paper-dark);
  line-height: 1.5;
}

.algorithm-resource-link {
  color: var(--ink-light);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  width: max-content;
  transition: color 200ms ease, border-color 200ms ease;
}

.algorithm-resource-link:hover {
  color: var(--bloom);
  border-bottom-color: var(--bloom);
}

/* The stub renderer (defensive fallback — no step uses it today). */
.algorithm-step-stub {
  color: var(--muted);
  font-style: italic;
  padding: 24px;
}

/* Persistent label key (shortLabel → full name). Built in index.js by
   reusing render/legend.js#renderTaskLegend. The wrapper owns the section
   rule + heading; the nested .task-legend is overridden to drop its own
   rule and flow its category blocks into responsive columns so the 26-row
   kimi-code key stays compact instead of running one tall column. Scoped
   under .algorithm-view so the walkthrough's legend is untouched. */
.algorithm-legend {
  max-width: 1380px; /* align the full-width key to the layout measure */
  margin: 32px auto 0;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
}

.algorithm-legend-heading {
  margin: 0 0 16px;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 400;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
}

.algorithm-view .task-legend {
  margin: 0;
  padding-top: 0;
  border-top: none;
  max-width: 100%;
  column-width: 240px;
  column-gap: 40px;
}

.algorithm-view .task-legend-category {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
}
