91aeacbe46
Both halves of the boot ran in one effect: `api.me()` and the photo handover, with the handover not waiting for the answer. Which file may open is a tier question — `loadFile` turns a RAW away unless the account is PRO — and the tier came from the render that effect closed over, which was the FIRST one, where `user` is still null. So a PRO's own RAW was read as a guest's, `promptPro` raised the sign-in modal, and because the handover had already cleared `?lib=` out of the URL with `history.replaceState`, there was nothing left to retry: signing in landed on an empty workspace, with the frame the visitor clicked sitting in the library behind it. The account and a new `authReady` flag now land in ONE batch, and the handover is an effect of its own that returns until the flag is set. Both the batch and the wait matter: one setState per render is what lets the handover effect see a render that already carries `user`, and the flag is what says so. Checked against a stubbed `api.me()` answering after 800ms (scratchpad bug1-probe.mjs, a PRO opening `/app?lib=probe-frame`): on the old bundle the `?lib=` is gone at the first sample, 765ms BEFORE the answer, and the session photo opens on the wrong tier; here it survives until 193ms AFTER the answer. The catalogue itself cannot be stood up in a check — its frames are real FileSystemFileHandles in IndexedDB — so the RAW actually opening is a manual step on a real catalogue. Skipped: a GUEST who clicks a RAW still loses it across the sign-in — the handover has run by then and the `?lib=` is gone. Add when someone reports it; the tier that can open a RAW is the operator's own account, which is the case this fixes.