the symptom, in your words

"Glyph corruption (text renders as solid blocks) is also text-count dependent"

✓ verified on 26.07.08e
lane Building UIposted updated

▸ > **⚠️ SUPERSEDED (OWNER-SETTLED, ENGINE 26.07.22).** THE GLYPH-ATLAS-BUDGET THEORY BELOW WAS

root-caused entirely from camera_screenshot evidence. The owner subsequently confirmed that sized panels render pin-sharp on the physical screen, so the glyph-block corruption is a capture-path artifact only, produced somewhere in the MCP camera_screenshot pipeline, not by the UI, the font, or any stylesheet property. Three independent sessions each generalized a different wrong "fix" from capture evidence (strip font-size / capture ≥2200 px wide / bisect font-size per selector) and none survived owner verification.

Operative rules that replace the recipe below:

  • Do not trim, combine, or ration text runs to make a capture legible; the live render is already correct.
  • Verify geometry (layout, color, shape, shadow, animation-settled state) from a capture, never text fidelity. Text-block corruption in a capture is not evidence of anything about the panel.
  • The owner's eyeball on the real game window is the only valid typography check. See An MCP camera_screenshot cannot verify font faces or text legibility.

Mechanism found (engine 26.07.22, 2026-07-31, controlled single-variable A/B in one live scene), and it agrees with the settled verdict: the trigger is the root panel's scale, not text-run count. A ScreenPanel left on its default AutoScreenScale renders at a fractional scale, and at a fractional scale the capture path rasterizes glyph runs as solid grey blocks. Set AutoScreenScale = false and Scale = 1 on that same ScreenPanel, capture again, and every glyph is pin sharp. That also explains the "positional" behaviour recorded below: element and capture size were both proxies for which panel's scale happened to be fractional.

The historical account is preserved below as the dated investigation record only.

▸ SYMPTOM

On a text-dense Razor panel with zero font-size or letter-spacing declarations, the last-rendered text element renders as solid filled blocks while identical sibling elements above it render as clean text. The content is irrelevant: even a plain string literal blocks. The corruption is positional: it hits the bottom/last-rendered text runs first, not specific classes or content.

This appears even when following the known rule of avoiding multiple font-size declarations. No errors are logged; compile_status reports Success = true.

▸ CAUSE

The documented glyph-corruption rule ("beyond a low threshold of distinct font-size or letter-spacing declarations, all text on the panel becomes blocks") has a second trigger: cumulative mono text-run count. Each text run on a ScreenPanel contributes to an internal glyph-atlas budget. When the total count of rendered text runs exceeds a threshold (observed around ~19+ mono runs on a single panel), the corruption manifests even with zero font-size declarations.

Unlike the font-size variant (which corrupts the entire panel), the text-count variant corrupts positionally: the last-rendered runs hit the threshold first, so bottom-of-panel text blocks while top-of-panel text stays clean. Expanding a collapsed section (which swaps the corrupt span for different markup) can render fine because the swap changes which run hits the threshold.

▸ FIX

The recipe recorded here was "treat mono text-run count as a budget and trim the least-important text". Do not follow it; see the banner at the top. Nothing about the panel needs changing; the live render was always correct.

To make text legible in a capture at all, pin the panel under test to AutoScreenScale = false, Scale = 1 at runtime (an MCP set_component on the ScreenPanel, no code change, gone at play-stop), then capture. That also makes geometry measurable with a ruler instead of a scale factor. The owner's eyeball on the real game window remains the acceptance route for typography.

▸ WHY IT WORKS

The fixed-capacity glyph-atlas explanation was inferred from capture evidence alone, and capture-evidence conclusions about font and glyph rendering are unreliable by demonstrated history: three sessions produced three different wrong generalizations. The controlled A/B that finally settled it changed one variable, the root panel's scale. Two panels in one frame proved it independently: a HUD on an auto-scaled ScreenPanel came out as blocks while a modal on a scale-1 ScreenPanel beside it came out crisp, and flipping the HUD's panel to scale 1 made it crisp too.

Verified on engine 26.07.08e: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Owner-settled (26.07.22): the text-run-count causation is a capture-path artifact. Added a superseded banner and neutralized the trim-text-runs recipe. Added the root-panel-scale mechanism.

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord