A failed join returns 1 to the FE, which QUITS the exe -- so every
rejection so far was a log line plus "the game just closed" (#68's exact
complaint). New LobbyNotice() = same text in the day log (flattened, still
greppable) + blocking MessageBox. Wired to every join-side bail:
- BUILD MISMATCH: when the version-filtered search is empty, probe once
without the version filter; if a lobby IS up, the box names the host's
build vs ours (lobby data rides the list result -- no join needed).
Post-entry verify mismatch gets the same box.
- NO LOBBY FOUND: probe empty too -> plain no-lobby box naming our build.
- STEAM UNAVAILABLE: transport install failed.
- LEFT BEHIND: host launched without us (no token in btl4map).
Old exes still exit silently on rejection -- nothing shipped today can
add text to a binary players already have; the host's roster marker +
REJECT log line remain the operator's view of those.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>