/* ---------- Chapter 3 · Tokens become meaning ---------- */
.s3 { position: absolute; inset: 0; display: grid; }
.s3-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-3); box-shadow: var(--card-shadow);
  padding: clamp(10px, 1.6cqw, 22px); display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: clamp(8px, 1.2cqw, 14px); min-height: 0;
}
.s3-head { font: 650 var(--scene-meta)/1.2 var(--f-sans); letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 360px) { .s3-head { letter-spacing: .04em; } }
.s3-cap {
  margin: 0; min-height: calc(var(--scene-meta) * 2.8); font: 500 var(--scene-meta)/1.4 var(--f-sans); color: var(--text-muted);
}
.s3-cap.is-eq { font: 560 var(--scene-label)/1.4 var(--f-serif); color: var(--text); }
.s3-plot {
  position: relative; min-height: 0; border-radius: var(--radius-2); background: var(--surface-sunk);
  background-image: radial-gradient(color-mix(in srgb, var(--line-strong) 55%, transparent) 1px, transparent 1.5px); background-size: 22px 22px;
  overflow: hidden;
}

/* Clusters */
.s3-halo { position: absolute; border-radius: var(--radius-3); background: color-mix(in srgb, var(--c) 9%, transparent); border: 1px solid color-mix(in srgb, var(--c) 28%, transparent); opacity: 0; }
.s3-cname {
  position: absolute; transform: translateY(-50%); white-space: nowrap; opacity: 0;
  font: 650 var(--scene-meta)/1.2 var(--f-sans); letter-spacing: .08em; text-transform: uppercase; color: color-mix(in srgb, var(--c) 82%, var(--text));
}

/* Retrieval zone */
.s3-zone {
  position: absolute; left: 0; top: 0; border-radius: 50%; opacity: 0; transform-origin: 50% 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--you) 14%, transparent) 0%, color-mix(in srgb, var(--you) 9%, transparent) 70%, color-mix(in srgb, var(--you) 3%, transparent) 100%);
}

/* Lines and arrows */
.s3-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.s3-svg line, .s3-svg polygon { opacity: 0; }
.s3-arrow { stroke: var(--you-strong); stroke-width: 3; stroke-linecap: round; }
.s3-arrow.is-dashed { stroke-dasharray: 2 7; }
.s3-arrowhead { fill: var(--you-strong); }
.s3-qline { stroke: var(--model-mid); stroke-width: 2; }
.s3-sel { stroke: var(--text-muted); stroke-width: 2; }
.s3-note {
  position: absolute; left: 0; top: 0; opacity: 0; white-space: nowrap; pointer-events: none;
  font: 600 var(--scene-meta)/1.2 var(--f-sans); color: var(--you-strong); background: var(--surface-sunk); padding: 1px 4px; border-radius: var(--radius-1);
}

/* Points: a node is a zero-size anchor moved with transform; dot and label hang off it. */
.s3-n { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; }
.s3-dot {
  position: absolute; left: -7px; top: -7px; width: 14px; height: 14px; border-radius: 50%; opacity: 0;
  background: color-mix(in srgb, var(--c, var(--text-muted)) calc(var(--k, 1) * 100%), var(--line-strong));
}
.s3-l {
  --h: calc(var(--scene-label) * 1.25);
  position: absolute; white-space: nowrap; opacity: 0; font: 560 var(--scene-label)/1.25 var(--f-sans); color: var(--text);
}
.s3-n[data-side="r"] .s3-l { left: 13px; top: calc(var(--h) / -2); }
.s3-n[data-side="l"] .s3-l { right: 13px; top: calc(var(--h) / -2); text-align: right; }
.s3-n[data-side="t"] .s3-l { left: 0; bottom: 13px; transform: translateX(-50%); text-align: center; }
.s3-n[data-side="b"] .s3-l { left: 0; top: 13px; transform: translateX(-50%); text-align: center; }
.s3-name { display: block; }
.s3-tag { display: block; opacity: 0; font: 650 var(--scene-meta)/1.25 var(--f-sans); color: var(--you-strong); }
.s3-r .s3-dot { --c: var(--text); }
.s3-n.is-sel .s3-l { background: var(--surface); box-shadow: 0 0 0 3px var(--surface); border-radius: var(--radius-1); }
.s3-q .s3-dot { --c: var(--you); left: -9px; top: -9px; width: 18px; height: 18px; box-shadow: 0 0 0 5px color-mix(in srgb, var(--you) 24%, transparent); }
.s3-q .s3-l { color: var(--you-strong); }
.s3-d { --c: var(--model); }
.s3-d.is-missed .s3-dot { box-shadow: 0 0 0 4px color-mix(in srgb, var(--you) 28%, transparent); }
.s3-n.is-sel .s3-dot { box-shadow: 0 0 0 6px color-mix(in srgb, var(--c) 28%, transparent); }
.s3-n.is-near .s3-dot { box-shadow: 0 0 0 4px color-mix(in srgb, var(--c) 22%, transparent); }

/* Transitions only while the viewer is using the controls; story beats are driven frame by frame. */
.s3.is-interactive .s3-dot, .s3.is-interactive .s3-l, .s3.is-interactive .s3-halo, .s3.is-interactive .s3-cname,
.s3.is-interactive .s3-zone, .s3.is-interactive .s3-svg line, .s3.is-interactive .s3-tag {
  transition: opacity var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.s3-plot[data-in="words"] :is(.s3-halo, .s3-cname, .s3-w .s3-dot, .s3-w .s3-l),
.s3-plot[data-in="docs"] :is(.s3-zone, .s3-qline, .s3-d .s3-dot, .s3-d .s3-l, .s3-d .s3-tag, .s3-q .s3-dot, .s3-q .s3-l) {
  transition-delay: var(--dur-2);
}

/* Card controls: the picked word stays visibly pressed. */
.btn[data-s3-pick][aria-pressed="true"] { background: var(--text); color: var(--surface); border-color: var(--text); }
