Phase 6, step 5, first half. Every one of the 40 screens rendered a single column
that filled whatever width it was given, so on a 1800dp desktop window a
paragraph became a 1800dp line -- long enough that the eye loses the start of the
next one -- and a six-character text field stretched to 1700dp.
M3: *"across all breakpoints, adjust margins and type styles to keep text between
40–60 characters per line."*
**The measure is derived, not written down.** `readableContentWidth()` is
`bodyLarge`'s font size converted through the current density, times half an em
per character, times sixty: 480dp at the default text size. Writing `480.dp`
instead would be the same number today and wrong for anybody who has turned text
size up -- at 200% the same column holds thirty characters, silently, because the
text still fits. Deriving it means the column widens with the type and keeps its
sixty. `AverageCharacterAdvance` is the one estimate in it, named and documented,
because a proportional face has no character width and half an em is the standard
figure for mixed-case Latin prose.
Only the ceiling is enforced. The floor needs nothing: a 400dp compact window
less its two 16dp margins holds about 46 characters, which is inside the range,
and no cap can add characters to a window that has none. There is a test for
exactly that, so the claim is checked rather than asserted in a comment.
**The column is centred; the text is not.** Those are opposite things and it is
worth being explicit, because "centre it" is how the second one gets done by
accident. A centred column still has one straight leading edge for every row,
avatar and icon to align to, which is what the grids-and-spacing page asks for.
Centred text has none. The 91 `TextAlign.Center` uses are a separate question and
a separate commit.
**Applied at 49 sites in one pass**, at the point every screen consumes its
`Scaffold`'s padding -- the one place in each file that is reliably the top of the
content. Below 480dp it is not a cap, an inset or a centring; it is nothing, so
no phone layout moves.
**Verified by measuring a real composition, not by reading the code.**
`readableContent()` is `fillMaxWidth` then `wrapContentWidth` then `widthIn`, and
every permutation of those three compiles and renders something that looks right
in a phone-width preview. This needed `compose.desktop.uiTestJUnit4` in `jvmTest`
-- pinned to the same 1.11.1 as the rest of Compose Multiplatform, test-only --
and `runDesktopComposeUiTest(width = 1400)`, which gives a window that genuinely
is 1400 pixels across at density 1.
Four assertions, and they bite: swapping the last two modifiers makes the
1400dp case report `Actual width is 1400.0.dp, expected 480.0.dp`, which is the
"centred but never capped" failure the doc comment names. The same test also
pins `currentBreakpoint()` to the real window at all five widths -- 400, 700,
1000, 1400, 1800 -- with the screen margin following. A version of it that
measured the parent's constraints rather than the window would answer `Compact`
everywhere and pass every unit test in the suite.
37 theme tests green; android and desktop both compile.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>