Add a CharacterDetail MVI stack (State/Action/Event/ViewModel + CharacterDetailUi)
to the UI-agnostic :feature:characters:presentation. The detail ViewModel reads the
typed characterId from SavedStateHandle (populated by the type-safe CharacterDetailRoute),
so the module keeps zero navigation/Compose deps.
Add CharacterDetailScreen (Root/Screen, image header, attribute rows, loading/error)
and CharacterDetailRoute to :presentation-compose; refactor charactersGraph to drive
list->detail via NavController and expose About / Views entries as callbacks. Extract
shared CharacterStatus label/colour helpers; add an overflow menu to the list app bar.
Add material-icons-core to the compose bundle for the app-bar icons.
- charactersPresentationModule: viewModelOf(::CharacterListViewModel) (in the UI-agnostic module).
- @Serializable CharacterListRoute + NavGraphBuilder.charactersGraph { composable<CharacterListRoute> }
in presentation-compose (serialization plugin added for type-safe routes).
- :app registers coreDataModule + charactersDataModule + charactersPresentationModule in startKoin,
and hosts a NavHost(startDestination = CharacterListRoute) calling charactersGraph.
- core:data manifest declares INTERNET (merges into :app) for live API calls.
- CharacterListRoot: koinViewModel(), ObserveAsEvents, forwards nav + shows snackbar via Context asString.
- CharacterListScreen: pure state+onAction; AppScaffold + LazyColumn (key=id), design-system
NetworkImage (contentDescription)/AppCard, loading/error/empty states, snapshot-based
scroll-to-end -> OnLoadNextPage (ViewModel guards duplicates).
- Loaded + error previews wrapped in AppTheme.
- feature:characters:presentation now exposes kotlinx-immutable as api (ImmutableList is in the state API).