fix(chat): render typing-indicator elapsed hint as horizontal text
Build and Push Containers / build-and-push-app (push) Successful in 1m43s
Build and Push Containers / build-and-push-db (push) Successful in 15s

The phase-87 ".typing-elapsed" dot-geometry reset (specificity 0,1,0)
lost every shared declaration to the ".typing span" dot rule
(0,1,1): the hint rendered as an 8x8px bouncing dot and the "Ns" text
wrapped one character per line below the bubble (overflow-wrap:
anywhere on .bubble). Phase 87's e2e checked text values only, so the
squish shipped unseen.

- retarget the reset at ".typing span.typing-elapsed" (0,2,1) so it
  actually wins; center the dots while the hint line is taller
- unit: pin the reset's selector context (specificity regression guard)
- e2e: layout pin on the live hint — no dot animation, not an 8px box,
  horizontal single-line bounding box
- before/after verification screenshots in
  .agents/reports/87_big_read_progress/

Verified: unit 41 passed, phase-87 e2e 4 passed (isolated), ruff +
pyright clean.
This commit is contained in:
2026-09-08 10:03:10 -04:00
parent 5abe8871e3
commit 10fd367962
5 changed files with 58 additions and 7 deletions
+14 -3
View File
@@ -111,10 +111,21 @@ def test_typing_elapsed_css_rule_is_the_aa_pairing() -> None:
language as every status line. Plain text — ``animation: none`` +
no background, and the dot-geometry reset (the span is a sibling of
the dots inside the .typing bubble, so without the reset it would
render as an 8px bouncing dot, not a hint)."""
render as an 8px bouncing dot, not a hint).
The reset's SELECTOR is pinned too (phase-87 regression, 2026-09):
a bare ``.typing-elapsed`` (specificity 0,1,0) loses every shared
declaration to the dot rule ``.typing span`` (0,1,1) — the hint
then rendered as an 8×8px bouncing dot with the "Ns" text wrapping
one character per line below the bubble. The reset must carry the
span context (``.typing span.typing-elapsed``, 0,2,1) to win."""
css = _css()
block = re.search(r"\.typing-elapsed \{([\s\S]*?)\n\}", css)
assert block, "styles.css must style .typing-elapsed"
assert ".typing span.typing-elapsed {" in css, (
"the dot-geometry reset must target the span in .typing context "
"(bare .typing-elapsed loses the specificity war to .typing span)"
)
block = re.search(r"\.typing span\.typing-elapsed \{([\s\S]*?)\n\}", css)
assert block, "styles.css must style .typing span.typing-elapsed"
body = block.group(1)
for prop in (
"font-family: var(--mono)",