73dcd75afe
Review follow-ups on the compositor spinner and the invalidation scoping. Spinner CSS: - Clip each frame to its own box. Braille renders from a system fallback face (JetBrains Mono has no U+2800 block), whose metrics are not guaranteed to fit the 1em frame, so neighbouring ink could bleed into the viewport. - Name descendants explicitly in the selection guard. The competing `[data-selectable-text='true'] *` rule has the same (0,1,0) specificity, so relying on inheritance made the winner depend on stylesheet order. - Scope the compositor promotion to spinners that are actually running. A permanently promoted layer per parked spinner is pure memory at fan-out breadth, where many sit mounted and paused at once. - Give every var() the braille default as its fallback, so a missing custom property degrades to a working spinner rather than an invalid declaration. Spinner component: replace the bare `as CSSProperties` cast on the inline style with an exported GlyphSpinnerVars contract, so a typo in a custom property name is a compile error rather than a silently dead declaration. Assistant message: - Render the inter-agent collapse as a CHILD of the normal body instead of a competing root. The settled case previously returned a different element type than the running case, so settling unmounted the whole row and mounted a fresh one — discarding the DOM the scroll anchor held. One component, one root, children vary; the truth table is unchanged, including the collapsed row carrying no tapback listener. - Collapse AssistantStatusSlot's separate subscriptions into one selector returning a stable string. The inputs always move together on a status flip, so reading them separately just multiplied the wake-ups. - Give StreamingMarker a stable `data-slot` and assert on that rather than on `span.hidden`. Repro script: count settled rows by subtracting streaming markers from message roots instead of `:not(:has(...))`. The selector walked every row's subtree on each evaluation, inside the very latency window the probe measures. Comments: drop the stale translateY(-100%) description, name both pause triggers, replace hard-coded line-number citations with selector/symbol ones, note that only the primary window arms the renderer-pause attribute, and move the forensic trace numbers out of source comments into the PR. Delete the three tests that asserted on stylesheet TEXT. AGENTS.md bans reading source in tests outright, and they demonstrated exactly why: a var()-fallback edit that changed no rendered pixel broke one of them. Replacements that exercise the CSS in a real browser follow. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwTc9XqUjhbay446VjugHZ