3bc169533a
Real Teams/Signal frames exposed a geometry bug: estimating a tile's SIZE from its name width (×3) produces a tiny box on big real tiles, so the speaking border ring fell entirely outside it → zero points → 'not speaking' (Joe Payne's clear blue border went undetected). Pure nearest-name fails too (the top edge of a lower tile is closer to the upper tile's bottom-anchored name). Fix: cluster the highlight pixels into connected RINGS (GridCallAnalyzer.connectedComponents, spatial-hashed union-find), then attribute each ring to the OCR'd name inside its bounding box. The ring *is* the tile, so detection is independent of tile-size estimation, and multiple simultaneous borders (lag/persist/crosstalk) become separate rings naturally — exactly the multi-ring case Grant flagged. minRingSpan rejects specks. Validated on real frames: Teams now detects 'Joe Payne' (was empty); Signal detects 'JA' in the group grid. (Signal _002 has a border but no rendered name that frame — inherent Signal intermittency; voice + reconciliation cover it.) 59/59 synthetic XCTest still green (white + coloured, single + crosstalk).