- splitLines(): join .codeline blocks with "" not "\n" — newline text nodes under pre-wrap rendered an extra line box per logical line, so every gutter number drifted one row per line - renumber(): geometry-driven placement — one gutline per visual row of the code body, each number assigned to the row matching its line's measured offsetTop; verified second pass re-runs if a partially-filled last wrapped row reflows after the gutter rebuild - app.css: mobile media query gives .code .gutter the same 13px font as .code so gutter rows and code rows share one line box at 375px Verified in local build with headless chromium (long unbroken token on line 5, wrap ON): all numbers align with line starts, no misalignment, no horizontal scroll at 1400x900 and 375x812.