Phase D of the parity push:
- Radio player: fixed bottom-right widget (port of atom's radio-player.blade)
that streams the hotel radio via <audio>, with play/pause, volume, current
DJ / now-playing and live listener count, polling the public API every 15s.
A server gate (RadioPlayerGate) only mounts it when radio is enabled + a
stream URL is set, so no widget JS ships when off. Mounted in the layout.
- Logo generator (/logo): client tool — hotel name + font/colour/size pickers
with a live preview and "download PNG" via canvas.
- Public room page (/room/[id]): renders an emulator room (name, owner,
users/max, state, category) in a ContentCard.
Verified live (prod, amx_test): /logo renders the generator, /room/50 shows
the real room "Dark Elegant Bundle", and with radio enabled the player
mounts fixed bottom-right (audio + play/pause + Test FM); reverted the test
settings. tsc 0, vitest 49/49, next build 0.