UiText
Platform-agnostic text holder so ViewModel state/effects never carry raw, pre-resolved strings — the UI edge resolves a UiText to an actual String (via stringResource / moko-resources for Res, or directly for Dynamic). Domain/data layers stay locale-free.
Dynamic wraps a literal, runtime-built string.
Res names a string-resource key (with optional args) resolved at the UI edge. Without a shared resource table in
commonMain, asString falls back to the key.Empty is an explicit "no text" so a caller never has to reach for
Dynamic("").