Theme CSS had no supported way to style a chat switch: t3-code-theme's
installSwitchFade watched the focus store, polled transcript rows and
scroll position in a rAF loop and toggled its own root attribute — DOM
reads catalog rule 8 now refuses.
Core already knows both phases of a switch, so it publishes them: the
chat surface root ([data-chat-surface], per pane) carries
data-session-switching="true" while a routed session is loading
(Thread loading === 'session') and while the thread list's scroll
restore places the new rows, removed on settle, user input, failed
resume or unmount. Each phase holds a token; the attribute goes when the
last holder releases, so the load ending never clears the restore's
mark mid-switch. An attribute (not a view-transition or motion token)
because the need is "know when", the duration is core's real settle
time, and CSS composes it with any theme without JS.