Both bugs had the same cause: light colours were set with inline style
attributes, which outrank the theme rules in base.html and so survived the
dark theme. Text that inherits --text-color then became light-on-light.
* manage_player.html: the delete confirmation modal used an inline
background-color of #fefefe with the body's dark-mode text colour, making
the message unreadable in dark mode. Rebuilt it with .modal-* classes
driven by the base.html CSS variables (and dark-mode variants for the
title, warning and player name).
* admin/maintenance.html: the "Automatic reset interval" panel, table
headers and JS-rendered rows/tables hardcoded #f8f9fa/#e2e8f0/#dee2e6.
Switched them to --bg-color / --card-bg / --border-color /
--text-secondary and added a themed .maint-badge-pending.
Verified with computed styles in both themes; light mode is unchanged.
Admin-only page reachable from a new card on the admin panel (replacing the
Quick Actions card) that centralises housekeeping operations:
* Database integrity: PRAGMA integrity_check / quick_check / foreign_key_check,
plus VACUUM + ANALYZE to reclaim free space.
* Leftover records: detects and removes orphaned rows left behind by deleted
players/content (player_feedback, player_edit, playlist_content, dangling
player.playlist_id) and orphaned edited-media folders on disk.
* Player authentication tokens: manual reset (single or all), a configurable
automatic reset interval, and cancellation of a pending reset.
Resetting a token rotates player.auth_code and sets auth_reset_required, so the
next heartbeat (POST /api/player-feedback) answers 401 + auth_required and the
client restarts its authentication flow. A successful authentication clears the
flag and stamps auth_token_issued_at, from which the interval is measured.
New: PlayerAuthConfig model, add_player_auth_reset migration (registered in
docker-entrypoint.sh), admin/maintenance.html.