The colors phase, shipped as Android-app#34. Seven notes, of which three are
departures the build forced rather than choices it made:
ColorScheme has no equals in material3 1.3.0, so AC-1's "full equality, not a
spot check" is a field-by-field compare by reflection over all 36 color roles,
against a verbatim copy of the pre-M12 scheme held in the test.
ShardPillFg is derived from --accent-bright rather than being a sixteenth
token, under the rule 5.1 already states for ShardOnCta.
An instance with an env accent and no theme_visual row loses its accented CTA
buttons, because brand.accent now seeds --accent alone. That is 5.1's "wrong
twice over" being corrected, and it is the one thing on screen that moves.
PLAN.md 9's M12 entry records phase 1 landed.
Co-Authored-By: Claude <noreply@anthropic.com>
Two records, one milestone.
Phase 7 (reading nav_admin / nav_player) is cancelled. Section 6.4 already
made the case against it and scheduled it last so the call could be taken on
its merits with the rest working: the two authenticated navs reach four app
rows between them, which does not pay for a new authenticated fetch, a
session-keyed cache and its teardown. The app therefore makes no authenticated
settings call at all, and the player and staff drawer rows keep their coded --
and so localized -- labels, which is the one thing given up. Section 4's locked
decision, section 3's endpoint row and section 5.5's lifecycle paragraph are
amended to match so the doc does not contradict itself, and section 8 gains
the standing "Phase 7, cancelled" note.
Phase 0 (the contract and the appearance store) landed as Android-app#33, and
its "as landed" notes record two departures from what section 8 specified:
- `theme` is modeled as a raw JsonElement rather than Map<String,String>?.
kotlinx fails the decode of the whole object on a value of an unexpected
kind, and `theme` shares its payload with `brand` and `push` -- so one odd
token would have blanked the branding and dropped the push relay URL, the
opposite of section 2. It is coerced field-by-field instead.
- A failed refresh keeps the last good appearance rather than falling back to
NONE. Section 5.5 said best-effort; the distinction it did not draw is that
a moment of no connectivity on resume must not repaint a themed shard back
to the shipped defaults.
Co-Authored-By: Claude <noreply@anthropic.com>
The website merged runtime admin theming, brand assets and nav overrides to
main (website#126 / docs#109). The app reads exactly one field of it --
brand.accent -- and renders a hardcoded APP_MENU, so an admin who re-skins the
site and restructures the header sees none of it on the phone.
Adds docs/android/THEMING_AND_NAV.md as the design of record for M12, and the
PLAN.md §9 entry that anchors it. Plan only: no app code, no backend work.
Everything consumed is already live on website/main.
The points that shaped it:
- The app's ui/theme/Color.kt palette is already, value for value, the
runic-gateway preset -- M5 was drawn from the same theme.css the preset was
later extracted from. So "an untouched instance is unchanged" carries over as
a testable ColorScheme equality assertion, not an approximation.
- Radii apply as a ratio against that baseline, not as literal dp. The app's
Shapes came from the M5 mockup and genuinely differ (medium 12dp vs
--radius-card 10px); a literal mapping would restyle the untouched app the
day this ships, and copying the app's scale into the server would be a second
source of truth.
- Fonts are bundled, not downloadable: the Play Store font provider makes a
de-Googled device fall back silently. Seven families join the bundled Cinzel.
- Nav overrides are keyed by website paths, so the app needs a path -> route
table -- the one new cross-repo coupling here. An override for a path the app
does not surface in its menu is ignored: a nav override may never introduce
navigation.
- The gates are untouched. MenuAccess and MenuEntry.feature still run after the
merge, so hidden:false cannot un-hide what a role or the shard's visibility
config withholds.
- Read the resolved theme/brand fields, never the raw theme_visual/brand_assets
rows that ride along in the same payload -- re-deriving a palette from them
would be a second resolveThemeTokens in Kotlin, guaranteed to drift.
Nine phases into a fresh edge in both repos, reaching main as one edge -> main
merge, the same shape the website side used. Phase 0 must change nothing on
screen. Phase 7 (the authenticated navs) is marked optional: nav_player reaches
two app rows and nav_admin two, which is a thin return for a new authenticated
fetch and its cache teardown.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgfKv5cz5pbY3dPeofSE5a