docs(android): M12 phase 3 as landed #115

Merged
whitlocktech merged 1 commits from docs/android-theming-nav-phase-3 into edge 2026-08-08 10:51:25 +00:00
Member

§5.3 rewritten against what the build measured rather than what the plan estimated, plus a "Phase 3 as landed" section and the in §8. Targets edge, like every M12 phase.

Three corrections to the drafted §5.3

1. The APK estimate was wrong by more than 3×. "Roughly 1.5–2.5 MB" becomes a measured before/after table — unsigned release, R8 full-mode + resource shrink, on edge at the phase 2 merge:

added (compressed) release APK
before phase 3 5,031,411 B — 4.80 MiB
after phase 3 8,543,292 B — 8.15 MiB 13,574,703 B — 12.94 MiB

Merriweather is 6.08 MiB of the 8.15 on its own: upstream ships it as a three-axis [opsz,wdth,wght] variable font, 4.6 MB per style, deflating only 31% where the others manage 50–60%. The section records the two cheaper options the org lead costed and declined — Google's own static 400/700 builds (whole app ≈ 6.8 MiB) and not bundling it at all (≈ 6.2 MiB, at the price of a serif option that silently does nothing on Android) — so the number is not re-litigated from scratch in six months.

2. Family lookup must be global, never scoped to the role's option list. The server validates an admin-entered font against FONT_OPTIONS[role], but a preset's tokens are copied verbatim by resolveThemeTokens and never pass through that dropdown: modern publishes --display: 'Work Sans', Arial, sans-serif and fantasy publishes --sans: 'EB Garamond', Georgia, serif, neither of which its own role offers. A per-role lookup would have missed the display face of one preset and the label face of the other. This is the same bypass §5.4 already records for --shadow-card, in a different token group.

3. Italics mirror the website's four, rather than being skipped — EB Garamond, IM Fell English, Merriweather and Playfair Display, exactly the set client/index.html requests one for. And every bundled family supplies the four weights the scale asks for (400 body, 500/700 labels, 600 display), because a family is not confined to the role its dropdown lives in. Two documented exceptions, both upstream facts: IM Fell English has one weight per style, and Cinzel keeps M5's 500/600/700 since the server offers it in the display role alone.

Also

"Phase 3 as landed" records the Typography-implements-equals finding (like phase 2's Shapes, unlike phase 1's ColorScheme), why there is deliberately no LocalShardTypeface, that licences live in app/licenses/ and never res/font/, and that three of the seven families carry a Reserved Font Name — a further reason the binaries are taken verbatim rather than subsetted locally.

Android-app: RunicGateway/Android-app#36.


  • AI-assisted: written with Claude Code (Claude Opus 5)
§5.3 rewritten against what the build measured rather than what the plan estimated, plus a "Phase 3 as landed" section and the ✅ in §8. Targets `edge`, like every M12 phase. ### Three corrections to the drafted §5.3 **1. The APK estimate was wrong by more than 3×.** "Roughly 1.5–2.5 MB" becomes a measured before/after table — unsigned release, R8 full-mode + resource shrink, on `edge` at the phase 2 merge: | | added (compressed) | release APK | |---|---|---| | before phase 3 | — | 5,031,411 B — 4.80 MiB | | after phase 3 | 8,543,292 B — 8.15 MiB | 13,574,703 B — **12.94 MiB** | **Merriweather is 6.08 MiB of the 8.15** on its own: upstream ships it as a three-axis `[opsz,wdth,wght]` variable font, 4.6 MB per style, deflating only 31% where the others manage 50–60%. The section records the two cheaper options the org lead costed and declined — Google's own static 400/700 builds (whole app ≈ 6.8 MiB) and not bundling it at all (≈ 6.2 MiB, at the price of a serif option that silently does nothing on Android) — so the number is not re-litigated from scratch in six months. **2. Family lookup must be global, never scoped to the role's option list.** The server validates an *admin-entered* font against `FONT_OPTIONS[role]`, but a preset's tokens are copied verbatim by `resolveThemeTokens` and never pass through that dropdown: `modern` publishes `--display: 'Work Sans', Arial, sans-serif` and `fantasy` publishes `--sans: 'EB Garamond', Georgia, serif`, neither of which its own role offers. A per-role lookup would have missed the display face of one preset and the label face of the other. This is the same bypass §5.4 already records for `--shadow-card`, in a different token group. **3. Italics mirror the website's four**, rather than being skipped — EB Garamond, IM Fell English, Merriweather and Playfair Display, exactly the set `client/index.html` requests one for. And every bundled family supplies the four weights the scale asks for (400 body, 500/700 labels, 600 display), because a family is not confined to the role its dropdown lives in. Two documented exceptions, both upstream facts: IM Fell English has one weight per style, and Cinzel keeps M5's 500/600/700 since the server offers it in the display role alone. ### Also "Phase 3 as landed" records the `Typography`-implements-`equals` finding (like phase 2's `Shapes`, unlike phase 1's `ColorScheme`), why there is deliberately no `LocalShardTypeface`, that licences live in `app/licenses/` and never `res/font/`, and that three of the seven families carry a Reserved Font Name — a further reason the binaries are taken verbatim rather than subsetted locally. Android-app: RunicGateway/Android-app#36. --- - [x] AI-assisted: written with Claude Code (Claude Opus 5)
wtclaude added 1 commit 2026-08-08 10:46:52 +00:00
§5.3 rewritten against what the build measured rather than what the plan
estimated, plus a "Phase 3 as landed" section and the  in §8.

Three corrections to the drafted section:

- The APK estimate was wrong by more than 3×. "Roughly 1.5-2.5 MB" becomes a
  measured before/after table: 5,031,411 B → 13,574,703 B, +8.15 MiB. The
  section now records that Merriweather is 6.08 MiB of that on its own, and the
  two cheaper options the org lead costed and declined, so the number is not
  re-litigated from scratch later.
- Family lookup must be global, never scoped to the role's option list. Two of
  the three presets publish a font their own role's dropdown does not offer,
  because resolveThemeTokens copies preset tokens verbatim — the same bypass
  §5.4 already records for --shadow-card.
- Italics mirror the website's four rather than being skipped, and every
  bundled family supplies the four weights the scale asks for (with IM Fell
  English's single weight and Cinzel's untouched 500/600/700 as the two
  documented exceptions), because a family is not confined to the role its
  dropdown lives in.

Android-app: RunicGateway/Android-app#TBD

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit 6526f32a42 into edge 2026-08-08 10:51:25 +00:00
whitlocktech deleted branch docs/android-theming-nav-phase-3 2026-08-08 10:51:27 +00:00
Sign in to join this conversation.
No description provided.