## SHARED SCREEN CONTRACT — fixed by the orchestrator, IDENTICAL in both wave-3
## prompts. Do NOT change these signatures. E1 writes BookshelfNavHost against them;
## E2 writes the screens to match. If you deviate, the other worker's code stops
## compiling and the wave fails.

Routes (string constants live in ui/nav/Routes.kt, owned by E1):
  "setup" | "library" | "library?shelfId={shelfId}" | "detail/{bookId}" |
  "scan" | "locations" | "settings"

Screen composable signatures:

  // E2 owns
  @Composable fun LibraryScreen(
      shelfIdFilter: String?,
      onBookClick: (String) -> Unit,
      onScanClick: () -> Unit,
      onLocationsClick: () -> Unit,
      onSettingsClick: () -> Unit,
      container: AppContainer,
  )
  @Composable fun DetailScreen(
      bookId: String,
      onBack: () -> Unit,
      container: AppContainer,
  )
  @Composable fun ScanScreen(
      onBack: () -> Unit,
      container: AppContainer,
  )

  // E1 owns
  @Composable fun SetupScreen(onSetupComplete: () -> Unit, container: AppContainer)
  @Composable fun LocationsScreen(
      onBack: () -> Unit,
      onShelfClick: (String) -> Unit,   // navigates to library?shelfId=...
      container: AppContainer,
  )
  @Composable fun SettingsScreen(
      onBack: () -> Unit,
      onSignedOut: () -> Unit,          // navigates back to "setup"
      container: AppContainer,
  )

All screens take `container: AppContainer` and construct their own ViewModel from it
(manual DI per SPEC — NO Hilt). Package = ui.<screen>, e.g. ui.library.LibraryScreen.
