Replace the single long scrolling v3 settings screen with a horizontal tab
bar (Gameplay / Audio / Graphics / Keybinds / Progression / Mic / Plugins /
System) over card rows (icon + title + description, control on the right) with
a per-category Reset.
- static/v3/index.html: tab bar + card-row markup (ids keep hydrating through
the unchanged app.js loadSettings()/persistSetting() path).
- static/v3/settings.js (new): tab switching + active-tab persistence
(localStorage 'v3-settings-tab'), per-category reset, read-only Keybinds
reference from window.getAllShortcuts().
- static/v3/v3.css: plain CSS, no Tailwind rebuild.
- Per-plugin settings tab: new optional settings.category in plugin.json →
plugins/__init__.py surfaces settings_category; app.js mounts each plugin
<details> into #plugin-settings-<category> (fallback: Plugins tab).
highway_3d ships category: "graphics".
- New gameplay settings: countdown_before_song (wired end-to-end, default off);
miss_penalty + fail_behavior (persist-only stubs); "Note highway speed"
surfaces existing master_difficulty.
- New POST /api/settings/reset clears whitelisted keys back to defaults.
Tests: test_settings_api.py, test_plugins.py::test_settings_category_parsed_from_manifest,
tests/browser/settings-tabbed.spec.ts. 179 passed locally.
Ported from the pre-rename feat/v3-settings-tabbed WIP onto current main
(slopsmith→feedBack rename applied; settings-screen markup conflict resolved
in favour of the new tabbed layout — all prior setting ids preserved).
Closes#579
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The highway showed two overlapping note-detection scoreboards at once: the
core v3 live-performance HUD (#v3-live-performance-hud) and the note_detect
plugin's own HUD (.nd-hud). Both auto-render off the same note:hit/note:miss
events and neither suppressed the other.
Add a Settings → Visualization "Scoreboard" selector (Streak / Detailed /
Off, default Streak) backed by a single source of truth on
<html data-scoreboard>. CSS shows exactly one:
core (default) → core HUD; hide .nd-hud
detailed → .nd-hud; hide the core HUD
off → hide both
CSS-based suppression keys the default off ":not(detailed):not(off)", so the
correct HUD is right even before the pref script runs (no flash) and it
robustly hides any .nd-hud regardless of how many note_detect instances load.
Detection itself is untouched — only the duplicate scoreboard panel is hidden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>