Tabs per tile (phase 5c): persist layout + selection to localStorage
Each vault's tile layout and tabs now survive an app restart, along with
the selected vault and (pre-existing) workspace kind.
- tilingPersistence: serializeLayout / buildInitialTileTabs / maxIdSuffix
(pure + tested) and load/save to localStorage under
textile.tiling.<vaultId>. Persists the split tree, active tile, and
each tile's documents + active index; not handles or load state.
- useTilingDocumentSlots: accept initialTiles, seed the tab map with
loading tabs, and re-open the documents in a mount-only effect
(cancelled on unmount). Exposes tileTabs for serialization.
- TilingWorkspace: lazy-init tree/activeTile/id-counter from the
persisted layout (keyed by instanceKey = vault provider id) and write
on change (skipping no-op rewrites).
- App: persist + restore selectedProviderId (textile.selectedVault); the
registry loads vaults synchronously so the restored vault survives the
auto-select effects.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>