Collects the post-gate polish left uncommitted by the killed round-5 agent
(S1/S3 + review fixes N1/N3/N4) and completes the missing S2 half:
- S1: UiText multi-line transcript + colored-run label now submit EVERY
line/run's outline pass before ANY fill pass, matching retail's
UIElement_Text::DrawSelf @0x00467aa0 whole-block walk. DrawStringDatPass
is exposed for block-level batching; single lines keep DrawStringDat.
- S2 (completed this commit): authored outline 0x21/0x22 now reaches every
text-bearing widget — UiButton, UiDatElement, UiField, UiMeter, UiMenu,
UiCatalogSlot — seeded from the element's effective-default state exactly
like UiText (BuildButton lifts the label-bearing Text child's authored
value first, same chain as the label color). Per-STATE outline switching
(dialog/character/combat buttons author 0x21 in state 0x3 only) is NOT
ported — filed as register row AP-192 in this commit.
- S3: ChatWindowController reconciliation comment corrects the misread
indicator action ids 0x10000514-17 -> 0x10000114-17 and re-attributes the
id-coincidence to the pagination widget's m_prevButton/m_nextButton, not
gmFriendsUI; register + window-shell research doc corrected to match.
- N1: LayoutImporter's duplicate per-state any-state-first-wins 0x21 read is
deleted — ElementReader.ApplyCanonicalLegacyProjection's DirectState-then-
effective-default resolution is the single source (the duplicate would have
lit state-0x3-only outlines permanently once S2 widened consumption).
- N3: the outline pass tints with the outline color's OWN alpha, not the
fill's (retail tints m_curOutlineColor and m_curTextColor independently).
- N4: the outline-inflated glyph SOURCE rect is clamped to the atlas bounds
with matching dest shrink, porting CreateCharRectPair @0x00441480's edge
behavior — edge glyphs crop instead of sampling a neighbour's texels.
Full Release suite: 12,610 passed / 4 skipped / 0 failed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>