diff --git a/docs/superpowers/plans/2026-03-16-tv-dpad-fixes.md b/docs/superpowers/plans/2026-03-16-tv-dpad-fixes.md
new file mode 100644
index 0000000..43d6144
--- /dev/null
+++ b/docs/superpowers/plans/2026-03-16-tv-dpad-fixes.md
@@ -0,0 +1,531 @@
+# TV-App D-Pad & Usability Fixes - Implementierungsplan
+
+> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** 5 Fernbedienungs-/Usability-Probleme der TV-App auf Samsung Tizen beheben.
+
+**Architecture:** Reine Frontend-Änderungen an 4 Dateien — JavaScript (FocusManager + Template-Scripts), CSS (Episode-Grid, Mark-Button, neuer Button), HTML (Templates). Kein Backend-Change. Bestehender i18n-Key `status.mark_series` wird wiederverwendet.
+
+**Tech Stack:** Vanilla JavaScript, CSS3, Jinja2-Templates, aiohttp
+
+**Spec:** `docs/superpowers/specs/2026-03-16-tv-dpad-fixes-design.md`
+
+---
+
+## Dateiübersicht
+
+| Datei | Änderung |
+|-------|----------|
+| `video-konverter/app/static/tv/js/tv.js` | FocusManager: Sidebar-Navigation, focusin-Handler |
+| `video-konverter/app/static/tv/css/tv.css` | Episode-Grid größer, Mark-Button sichtbar, neuer Button-Style |
+| `video-konverter/app/templates/tv/series.html` | Alphabet-IIFE: entfernen statt dimmen |
+| `video-konverter/app/templates/tv/series_detail.html` | Mark-Button fokussierbar, "Serie als gesehen"-Button + JS |
+
+---
+
+## Task 1: Alphabet-Sidebar — nur verfügbare Buchstaben anzeigen
+
+**Files:**
+- Modify: `video-konverter/app/templates/tv/series.html:243-253`
+
+- [ ] **Step 1: IIFE ändern — `el.remove()` statt `el.classList.add('dimmed')`**
+
+In `series.html`, Zeile 243-253, das bestehende IIFE anpassen:
+
+```javascript
+// Buchstaben ohne Treffer komplett entfernen (statt nur dimmen)
+(function() {
+ var avail = {};
+ document.querySelectorAll('.tv-view-grid [data-letter], .tv-view-list [data-letter], .tv-view-detail [data-letter]').forEach(function(item) {
+ var raw = item.dataset.letter;
+ avail[/^[A-Z]$/.test(raw) ? raw : '#'] = true;
+ });
+ document.querySelectorAll('.tv-alpha-letter').forEach(function(el) {
+ if (!avail[el.dataset.letter]) el.remove();
+ });
+})();
+```
+
+Konkret: Zeile 251 ändern von:
+```javascript
+ if (!avail[el.dataset.letter]) el.classList.add('dimmed');
+```
+zu:
+```javascript
+ if (!avail[el.dataset.letter]) el.remove();
+```
+
+- [ ] **Step 2: Manuell testen**
+
+Browser öffnen → TV-Serien-Seite → prüfen dass nur Buchstaben angezeigt werden, die tatsächlich Serien haben.
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add video-konverter/app/templates/tv/series.html
+git commit -m "fix(tv): Alphabet-Sidebar zeigt nur verfügbare Buchstaben"
+```
+
+---
+
+## Task 2: FocusManager — Sidebar per D-Pad erreichbar
+
+**Files:**
+- Modify: `video-konverter/app/static/tv/js/tv.js:38-43` (focusin-Handler)
+- Modify: `video-konverter/app/static/tv/js/tv.js:230` (nach ArrowUp-Nav-Block, vor Nearest-Neighbor)
+- Modify: `video-konverter/app/static/tv/js/tv.js:240-243` (searchEls-Filter)
+
+**WICHTIG:** Alle 3 Änderungen sind atomar — zusammen einfügen!
+
+- [ ] **Step 1: focusin-Handler anpassen — Sidebar aus Content-Tracking ausschließen**
+
+In `tv.js`, Zeile 38-43, die Bedingung erweitern. Aktuell:
+
+```javascript
+ if (e.target && e.target.hasAttribute && e.target.hasAttribute("data-focusable")) {
+ if (!e.target.closest("#tv-nav")) {
+ // Nur echte Content-Elemente merken (nicht Filter/Controls)
+ if (e.target.closest(".tv-grid, .tv-list-compact, .tv-detail-list, .tv-folder-view, .tv-row, .tv-episode-list, .tv-episode-grid, .tv-tabs, .tv-detail-actions, .tv-alpha-sidebar, .tv-view-switch, .tv-filter-bar, .tv-season-actions, .profiles-grid")) {
+ this._lastContentFocus = e.target;
+ }
+ }
+ }
+```
+
+Ändern zu (`.tv-alpha-sidebar` aus der Content-Areas-Liste entfernen UND Sidebar explizit in äußerer Bedingung ausschließen):
+
+```javascript
+ if (e.target && e.target.hasAttribute && e.target.hasAttribute("data-focusable")) {
+ if (!e.target.closest("#tv-nav") && !e.target.closest(".tv-alpha-sidebar")) {
+ // Nur echte Content-Elemente merken (nicht Nav/Sidebar)
+ if (e.target.closest(".tv-grid, .tv-list-compact, .tv-detail-list, .tv-folder-view, .tv-row, .tv-episode-list, .tv-episode-grid, .tv-tabs, .tv-detail-actions, .tv-view-switch, .tv-filter-bar, .tv-season-actions, .profiles-grid")) {
+ this._lastContentFocus = e.target;
+ }
+ }
+ }
+```
+
+- [ ] **Step 2: Sidebar-Navigationslogik einfügen — nach ArrowUp-Block (Zeile 230)**
+
+In `tv.js`, nach Zeile 230 (dem Ende des `if (!inNav && direction === "ArrowUp")` Blocks), VOR dem Nearest-Neighbor-Block (Zeile 232: `const currentRect = ...`), folgenden Code einfügen:
+
+```javascript
+ // ===== Alphabet-Sidebar Navigation =====
+ const inSidebar = active.closest(".tv-alpha-sidebar");
+
+ if (inSidebar) {
+ if (direction === "ArrowLeft") {
+ // Zurueck zum Content
+ if (this._lastContentFocus && document.contains(this._lastContentFocus)) {
+ this._lastContentFocus.focus();
+ } else {
+ const firstCard = document.querySelector(".tv-grid [data-focusable], .tv-card[data-focusable]");
+ if (firstCard) firstCard.focus();
+ }
+ e.preventDefault();
+ return;
+ }
+ if (direction === "ArrowUp" || direction === "ArrowDown") {
+ // Sequentiell durch Buchstaben
+ const letters = Array.from(document.querySelectorAll(".tv-alpha-letter[data-focusable]"))
+ .filter(el => el.offsetHeight > 0);
+ const idx = letters.indexOf(active);
+ const next = direction === "ArrowDown" ? idx + 1 : idx - 1;
+ if (next >= 0 && next < letters.length) {
+ letters[next].focus();
+ letters[next].scrollIntoView({ block: "nearest", behavior: "smooth" });
+ }
+ e.preventDefault();
+ return;
+ }
+ }
+
+ // ArrowRight am rechten Grid-Rand -> Sidebar
+ if (!inNav && !inSidebar && direction === "ArrowRight") {
+ const sidebar = document.getElementById("alpha-sidebar");
+ if (sidebar && sidebar.offsetHeight > 0) {
+ // Pruefen ob es noch ein Element rechts im Content gibt
+ const contentEls = focusables.filter(el => !el.closest("#tv-nav") && !el.closest(".tv-alpha-sidebar"));
+ const currentRect_r = active.getBoundingClientRect();
+ const rightNeighbor = contentEls.some(el => {
+ const r = el.getBoundingClientRect();
+ return r.left > currentRect_r.right + 5 && Math.abs(r.top - currentRect_r.top) < 100;
+ });
+ if (!rightNeighbor) {
+ // Kein Content rechts -> zur Sidebar springen
+ const sidebarLetters = Array.from(sidebar.querySelectorAll("[data-focusable]"))
+ .filter(el => el.offsetHeight > 0);
+ if (sidebarLetters.length > 0) {
+ // Naechstgelegenen Buchstaben vertikal finden
+ const cy_r = currentRect_r.top + currentRect_r.height / 2;
+ let best = sidebarLetters[0];
+ let bestDist_r = Infinity;
+ sidebarLetters.forEach(l => {
+ const lr = l.getBoundingClientRect();
+ const d = Math.abs(lr.top + lr.height / 2 - cy_r);
+ if (d < bestDist_r) { bestDist_r = d; best = l; }
+ });
+ this._lastContentFocus = active;
+ best.focus();
+ e.preventDefault();
+ return;
+ }
+ }
+ }
+ }
+```
+
+- [ ] **Step 3: Nearest-Neighbor searchEls-Filter erweitern — Sidebar ausschließen**
+
+In `tv.js`, die Zeilen mit dem `searchEls`-Filter (ca. Zeile 240-243, nach Einfügung verschoben) ändern von:
+
+```javascript
+ const searchEls = inNav
+ ? focusables.filter(el => el.closest("#tv-nav"))
+ : focusables.filter(el => !el.closest("#tv-nav"));
+```
+
+zu:
+
+```javascript
+ const searchEls = inNav
+ ? focusables.filter(el => el.closest("#tv-nav"))
+ : focusables.filter(el => !el.closest("#tv-nav") && !el.closest(".tv-alpha-sidebar"));
+```
+
+- [ ] **Step 4: Manuell testen**
+
+Browser/Tizen-Emulator → Serien-Seite:
+1. D-Pad rechts am Grid-Rand → Sidebar bekommt Focus
+2. D-Pad hoch/runter in Sidebar → sequentiell durch Buchstaben
+3. D-Pad links in Sidebar → zurück zur letzten Card
+4. Enter in Sidebar → filtert Serien nach Buchstabe
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add video-konverter/app/static/tv/js/tv.js
+git commit -m "fix(tv): Alphabet-Sidebar per D-Pad/Fernbedienung navigierbar"
+```
+
+---
+
+## Task 3: Episoden-Cards vergrößern + Laufzeit-Badge
+
+**Files:**
+- Modify: `video-konverter/app/static/tv/css/tv.css:1817-1821` (Episode-Grid Basis)
+- Modify: `video-konverter/app/static/tv/css/tv.css:2019-2020` (1200px Breakpoint)
+
+- [ ] **Step 1: Basis-Grid vergrößern**
+
+In `tv.css`, Zeile 1819 ändern von:
+
+```css
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
+```
+
+zu:
+
+```css
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
+```
+
+Zeile 1820 ändern von:
+
+```css
+ gap: 0.8rem;
+```
+
+zu:
+
+```css
+ gap: 1rem;
+```
+
+- [ ] **Step 2: 1200px-Breakpoint anpassen**
+
+In `tv.css`, Zeile 2020 ändern von:
+
+```css
+ .tv-episode-grid { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
+```
+
+zu:
+
+```css
+ .tv-episode-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
+```
+
+- [ ] **Step 3: Laufzeit-Badge anpassen**
+
+In `tv.css`, die `.tv-ep-duration`-Regel finden (Zeile 452-461) und `white-space: nowrap;` hinzufügen sowie Font/Padding anpassen:
+
+Aktuell:
+```css
+.tv-ep-duration {
+ position: absolute;
+ bottom: 6px;
+ right: 6px;
+ background: rgba(0,0,0,0.75);
+ color: #fff;
+ font-size: 0.7rem;
+ padding: 2px 6px;
+ border-radius: 3px;
+}
+```
+
+Ändern zu:
+```css
+.tv-ep-duration {
+ position: absolute;
+ bottom: 6px;
+ right: 6px;
+ background: rgba(0,0,0,0.75);
+ color: #fff;
+ font-size: 0.8rem;
+ padding: 3px 8px;
+ border-radius: 3px;
+ white-space: nowrap;
+}
+```
+
+- [ ] **Step 4: Manuell testen**
+
+Browser → Serien-Detail-Seite → prüfen dass Episoden-Cards größer sind und die Laufzeit vollständig sichtbar ist.
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add video-konverter/app/static/tv/css/tv.css
+git commit -m "fix(tv): Episoden-Cards vergrößert, Laufzeit-Badge vollständig sichtbar"
+```
+
+---
+
+## Task 4: "Gesehen"-Button auf Episode-Cards fokussierbar machen
+
+**Files:**
+- Modify: `video-konverter/app/templates/tv/series_detail.html:129-132` (HTML)
+- Modify: `video-konverter/app/static/tv/css/tv.css:1864-1899` (CSS)
+
+- [ ] **Step 1: HTML — `tabindex="-1"` entfernen, `data-focusable` hinzufügen**
+
+In `series_detail.html`, Zeile 129-132 ändern von:
+
+```html
+
+```
+
+zu:
+
+```html
+
+```
+
+- [ ] **Step 2: CSS — Mark-Button auf TV sichtbar machen (hover:none Media-Query)**
+
+In `tv.css`, nach der bestehenden `.tv-ep-tile-mark`-Regel (Zeile 1882, nach `z-index: 2;` und vor der hover/focus-Regel), folgende Media-Query einfügen:
+
+```css
+/* TV-Geraete (kein Hover): Mark-Button immer leicht sichtbar */
+@media (hover: none) {
+ .tv-ep-tile-mark {
+ opacity: 0.5;
+ }
+}
+```
+
+- [ ] **Step 3: CSS — Focus-Ring für Mark-Button**
+
+Die bestehende Regel in `tv.css`, Zeile 1894-1899 ist bereits vorhanden:
+
+```css
+.tv-ep-tile-mark:hover, .tv-ep-tile-mark:focus {
+ border-color: var(--accent);
+ color: var(--accent);
+ outline: none;
+ opacity: 1;
+}
+```
+
+Diese enthält `outline: none` — für D-Pad-Navigation brauchen wir stattdessen einen sichtbaren Focus-Ring. Ändern zu:
+
+```css
+.tv-ep-tile-mark:hover, .tv-ep-tile-mark:focus {
+ border-color: var(--accent);
+ color: var(--accent);
+ opacity: 1;
+}
+.tv-ep-tile-mark:focus {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+}
+```
+
+- [ ] **Step 4: Manuell testen**
+
+Browser → Serien-Detail → D-Pad auf Episode-Card → dann D-Pad hoch/links zum Mark-Button → Enter drückt "Gesehen". Prüfen:
+1. Button ist leicht sichtbar (auf TV/touch)
+2. Button bekommt Focus-Ring bei D-Pad-Navigation
+3. Enter toggled gesehen/ungesehen
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add video-konverter/app/templates/tv/series_detail.html video-konverter/app/static/tv/css/tv.css
+git commit -m "fix(tv): Gesehen-Button per D-Pad fokussierbar, auf TV sichtbar"
+```
+
+---
+
+## Task 5: "Serie als gesehen markieren"-Button
+
+**Files:**
+- Modify: `video-konverter/app/templates/tv/series_detail.html:57-66` (HTML)
+- Modify: `video-konverter/app/templates/tv/series_detail.html` (JS am Ende des Script-Blocks)
+- Modify: `video-konverter/app/static/tv/css/tv.css` (neues Styling)
+
+- [ ] **Step 1: HTML — Button im Header-Aktionsbereich einfügen**
+
+In `series_detail.html`, nach dem Watchlist-Button (Zeile 65, vor `` auf Zeile 66), einfügen:
+
+```html
+
+
+```
+
+- [ ] **Step 2: JavaScript — `markSeriesWatched()` Funktion hinzufügen**
+
+In `series_detail.html`, im `