diff --git a/docs/superpowers/specs/2026-04-24-web-ui-player-design.md b/docs/superpowers/specs/2026-04-24-web-ui-player-design.md
new file mode 100644
index 00000000..d0bb44bc
--- /dev/null
+++ b/docs/superpowers/specs/2026-04-24-web-ui-player-design.md
@@ -0,0 +1,423 @@
+# Web UI Player — Design Spec
+
+**Date:** 2026-04-24
+**Status:** Design approved
+**Follows:** [Web UI Library Views](2026-04-23-web-ui-library-views-design.md) — tracks surfaced by the library plan finally become playable.
+
+## Goal
+
+Let an authenticated user click any track on an album page and hear it — plus skip/seek/shuffle/repeat/volume, a persistent bottom-bar UI, and OS-level media controls via the MediaSession API. After this lands, the web client is a functional music player for sequential playback through the library.
+
+## Non-goals
+
+Explicit YAGNI — kept out of this plan so scope stays tight:
+
+- **No server-side listen-history recording.** The spec's `play_events` / `sessions` tables exist in the server design but no `/api/*` endpoints are implemented yet. Once those land, a follow-up "session reporting" sub-plan wires the player to POST events.
+- **No scrobbling to ListenBrainz.** Dependent on server event endpoints + scrobble queue — later plan.
+- **No contextual likes or "like this vibe".** Out of scope until session reporting exists.
+- **No cross-refresh persistence.** Reload drops playback state (queue, position, current track). Volume is the only thing that persists.
+- **No queue UI / "up next" panel.** The user sees the current track in the bar; they don't get a separate list view of what's coming. Queue visibility is a natural follow-up.
+- **No keyboard shortcuts.** Space/arrow keys don't control playback in this plan — a separate "keyboard shortcuts" sub-plan will add them.
+- **No crossfade, gapless playback, replay-gain, equalizer.** Baseline HTMLAudio only.
+- **No cast / AirPlay / Chromecast.** Browser-local playback only.
+- **No keyboard-driven seeking beyond the native `` behavior.**
+
+## Architecture
+
+**Single global player store** as a Svelte 5 rune module — imported by `+layout.svelte`, `Shell`, `PlayerBar`, and `TrackRow`. The store is pure state + action functions; it never touches the `