The onopen/onclose handlers only toggled the CSS class on the status
dot, never the separate text span, so it stayed "offline" after a
reconnect. Replace the querySelector-based toggling with an
updateWsIndicator() helper that updates both the dot and its label
from stored element refs.
The indicator now lives in the topbar (via renderTopbar's extra slot)
instead of next to the competition name, with its own .ws-indicator
flex wrapper so the dot and label line up vertically.
Move the Users table and add a new rule-text editor into a dedicated
admin.html/admin.js page with its own collapsible sidebar (Users,
Rules categories), reachable only for system admins via a button next
to the brand. The Competitions page no longer renders admin-only
controls inline.
Competitions page: cards are now fully clickable to open the
competition (drop the separate "Open" button), the admin-only delete
action moves into a "..." menu (new generic openInlineMenu/
openAnchoredPopover helpers in common.js), and add an open/closed
filter.
Topbar: language switch and logout move out of the topbar into a
small popup under the profile button, which itself opens the full
settings modal for username/display name/language/password.