diff --git a/.impeccable/design.json b/.impeccable/design.json
new file mode 100644
index 0000000..0bec707
--- /dev/null
+++ b/.impeccable/design.json
@@ -0,0 +1,105 @@
+{
+ "schemaVersion": 2,
+ "generatedAt": "2026-05-05T00:00:00Z",
+ "title": "Design System: MAL",
+ "extensions": {
+ "colorMeta": {
+ "background": { "role": "neutral", "displayName": "Void Black", "canonical": "#080808" },
+ "background-sidebar": { "role": "neutral", "displayName": "Deep Charcoal", "canonical": "#0f0f0f" },
+ "background-header": { "role": "neutral", "displayName": "Elevated Black", "canonical": "#141414" },
+ "background-surface": { "role": "neutral", "displayName": "Surface Gray", "canonical": "#202020" },
+ "background-button": { "role": "neutral", "displayName": "Button Dark", "canonical": "#1a1a1a" },
+ "background-button-hover": { "role": "neutral", "displayName": "Button Hover", "canonical": "#252525" },
+ "foreground-muted": { "role": "neutral", "displayName": "Muted Gray", "canonical": "#6a6b70" },
+ "foreground": { "role": "neutral", "displayName": "Off White", "canonical": "#f8f9fa" },
+ "accent": { "role": "primary", "displayName": "Soft Violet", "canonical": "#9f7aea" },
+ "danger": { "role": "accent", "displayName": "Red Alert", "canonical": "#dc2626" }
+ },
+ "typographyMeta": {
+ "body": { "displayName": "Body", "purpose": "Standard text, descriptions" },
+ "title": { "displayName": "Title", "purpose": "Page headings" },
+ "label": { "displayName": "Label", "purpose": "Navigation, buttons, form labels" }
+ },
+ "shadows": [],
+ "motion": [
+ { "name": "ease-default", "value": "cubic-bezier(0.4, 0, 0.2, 1)", "purpose": "Default transition easing" }
+ ],
+ "breakpoints": []
+ },
+ "components": [
+ {
+ "name": "Primary Button",
+ "kind": "button",
+ "refersTo": "button-primary",
+ "description": "Main action button with purple background",
+ "html": "",
+ "css": ".ds-btn-primary { background: #9f7aea; color: #080808; padding: 8px 16px; border: none; font-weight: 500; transition: background 0.2s; } .ds-btn-primary:hover { background: #b79ef5; }"
+ },
+ {
+ "name": "Secondary Button",
+ "kind": "button",
+ "refersTo": "button-secondary",
+ "description": "Secondary action with dark background",
+ "html": "",
+ "css": ".ds-btn-secondary { background: rgba(255,255,255,0.05); color: #f8f9fa; padding: 8px 16px; border: none; transition: background 0.2s; } .ds-btn-secondary:hover { background: rgba(255,255,255,0.1); }"
+ },
+ {
+ "name": "Anime Card",
+ "kind": "card",
+ "refersTo": "card-anime",
+ "description": "Anime poster card with hover reveal",
+ "html": "

Title
",
+ "css": ".ds-card { position: relative; aspect-ratio: 2/3; background: rgba(255,255,255,0.05); overflow: hidden; } .ds-card img { width: 100%; height: 100%; object-fit: cover; } .ds-card-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.8); opacity: 0; padding: 12px; transition: opacity 0.3s; display: flex; flex-direction: column; } .ds-card:hover .ds-card-overlay { opacity: 1; }"
+ },
+ {
+ "name": "Navigation Item",
+ "kind": "nav",
+ "refersTo": "nav-item",
+ "description": "Sidebar navigation link with active indicator",
+ "html": "Home",
+ "css": ".ds-nav-item { display: flex; align-items: center; padding: 12px 28px; color: #6a6b70; text-decoration: none; transition: color 0.2s, background 0.2s; position: relative; } .ds-nav-item:hover { background: rgba(255,255,255,0.05); } .ds-nav-item.active { color: #9f7aea; } .ds-nav-item.active::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); height: 32px; width: 2px; background: #9f7aea; }"
+ },
+ {
+ "name": "Dropdown Menu",
+ "kind": "custom",
+ "refersTo": "dropdown",
+ "description": "Custom dropdown with dark background",
+ "html": "",
+ "css": ".ds-dropdown { position: relative; } .ds-dropdown-content { position: absolute; top: 100%; right: 0; background: #1a1a1a; box-shadow: 0 8px 24px rgba(0,0,0,0.4); padding: 4px 0; display: none; min-width: 160px; } .ds-dropdown-content button { display: block; width: 100%; padding: 10px 20px; text-align: left; background: none; border: none; color: #f8f9fa; } .ds-dropdown-content button:hover { background: rgba(255,255,255,0.1); }"
+ }
+ ],
+ "narrative": {
+ "northStar": "The Personal Theater",
+ "overview": "A dark, intimate interface for watching anime. Built for long viewing sessions in low-light environments. The aesthetic rejects the loud, gamified look of mainstream anime trackers. No flashy animations, no glassmorphism, no gradient text.",
+ "keyCharacteristics": [
+ "Dark by default; light mode secondary",
+ "Minimal chrome; content first",
+ "Purple accent ≤10% of any screen",
+ "No rounded corners",
+ "DM Sans system fonts"
+ ],
+ "rules": [
+ { "name": "The One Accent Rule", "body": "Purple appears on ≤10% of any given screen. Its rarity is the point.", "section": "colors" },
+ { "name": "The Weight Contrast Rule", "body": "Headings use font-semibold (600), body uses font-normal (400). Avoid flat weight hierarchies.", "section": "typography" },
+ { "name": "The Flat-By-Default Rule", "body": "Surfaces are flat at rest. No shadows. Depth conveyed through tonal layering.", "section": "elevation" }
+ ],
+ "dos": [
+ "Do use accent purple for primary actions and active states only",
+ "Do keep interfaces dark by default",
+ "Do use weight contrast for hierarchy",
+ "Do reveal detail on hover",
+ "Do include back buttons on detail pages"
+ ],
+ "donts": [
+ "Don't use rounded corners anywhere",
+ "Don't use color to differentiate toast types",
+ "Don't use gradient text",
+ "Don't use glassmorphism",
+ "Don't use hero metric layouts",
+ "Don't use identical card grids with no variation",
+ "Don't use modals as first thought",
+ "Don't use side-stripe borders",
+ "Don't use green accent—violet is the one and only"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644
index 0000000..37a0496
--- /dev/null
+++ b/DESIGN.md
@@ -0,0 +1,155 @@
+---
+name: MAL
+description: Personal anime streaming & watchlist service
+colors:
+ background: "#080808"
+ background-sidebar: "#0f0f0f"
+ background-header: "#141414"
+ background-surface: "#202020"
+ background-button: "#1a1a1a"
+ background-button-hover: "#252525"
+ foreground-muted: "#6a6b70"
+ foreground: "#f8f9fa"
+ accent: "#9f7aea"
+ danger: "#dc2626"
+typography:
+ body:
+ fontFamily: "'DM Sans', 'Segoe UI', system-ui, sans-serif"
+ fontSize: "14px"
+ fontWeight: 400
+ lineHeight: 1.5
+rounded:
+ default: "6px"
+spacing:
+ sm: "0.25rem"
+ md: "0.5rem"
+ lg: "1rem"
+ xl: "1.5rem"
+ 2xl: "2rem"
+components:
+ button-primary:
+ backgroundColor: "{colors.accent}"
+ textColor: "#080808"
+ padding: "8px 16px"
+ button-secondary:
+ backgroundColor: "{colors.background-button}"
+ textColor: "{colors.foreground}"
+ padding: "8px 16px"
+ button-secondary-hover:
+ backgroundColor: "{colors.background-button-hover}"
+---
+
+# Design System: MAL
+
+## 1. Overview
+
+**Creative North Star: "The Personal Theater"**
+
+A dark, intimate interface for watching anime. Built for long viewing sessions in low-light environments—think late-night streaming on a personal server. The aesthetic rejects the loud, gamified look of mainstream anime trackers. No flashy animations, no glassmorphism, no gradient text. Just content and controls.
+
+**Key Characteristics:**
+- Dark by default; light mode exists but is secondary
+- Minimal chrome; the anime artwork carries the visual weight
+- Purple accent used sparingly (<10% of any screen)
+- No rounded corners; sharp edges throughout
+- System fonts (DM Sans) for reliability across devices
+
+## 2. Colors
+
+The palette is intentionally restrained. Dark surfaces dominate to reduce eye strain during long sessions.
+
+### Primary
+- **Accent Purple** (`#9f7aea`): Navigation highlights, active states, primary actions. Used on active sidebar items, hover states on important buttons, current episode indicators.
+
+### Neutral
+- **Background** (`#080808`): Main page background. Deep black with a hint of warmth.
+- **Background Sidebar** (`#0f0f0f`): Slightly elevated surface for navigation panel.
+- **Background Header** (`#141414`): Sticky header surface, slightly brighter than page.
+- **Background Surface** (`#202020`): Cards, dropdowns, search inputs.
+- **Background Button** (`#1a1a1a`): Default button state, form fields.
+- **Background Button Hover** (`#252525`): Button hover state.
+- **Foreground Muted** (`#6a6b70`): Secondary text, icons, placeholders.
+- **Foreground** (`#f8f9fa`): Primary text, headings.
+
+### Named Rules
+**The One Accent Rule.** Purple appears on ≤10% of any given screen. Its rarity is the point. Navigation highlights use a subtle left border; primary buttons use the accent background.
+
+## 3. Typography
+
+**Body Font:** DM Sans (with Segoe UI, system-ui fallbacks)
+
+**Character:** Clean, legible, unremarkable. The typeface should be invisible—content first.
+
+### Hierarchy
+- **Title** (`600`, `20px`): Page headings.
+- **Body** (`400`, `14px`): Standard text, descriptions.
+- **Label** (`500`, `14px`, `0.025em`): Navigation items, buttons, form labels.
+- **Small** (`400`, `12px`): Metadata, episode numbers, timestamps.
+
+### Named Rules
+**The Weight Contrast Rule.** Headings use `font-semibold` (600), body uses `font-normal` (400). Avoid flat weight hierarchies.
+
+## 4. Elevation
+
+**Flat by default.** No shadows at rest. Depth is conveyed through tonal layering—different background colors rather than shadow layers.
+
+- **Hover state:** Background shifts from `#1a1a1a` to `#252525`.
+- **Active states:** Subtle accent tint (`bg-accent/20`) or accent left border.
+- **No shadows.** The interface is intentionally flat.
+
+### Shadow Vocabulary
+None used. If shadows are needed for overlays (modals, dropdowns), use `box-shadow: 0 8px 24px rgba(0,0,0,0.4)`.
+
+## 5. Components
+
+### Buttons
+- **Shape:** No rounded corners (sharp edges).
+- **Primary:** Purple background (`bg-accent`), dark text. Used for the most important action on each screen.
+- **Secondary:** Dark background (`bg-white/5`), light text. Used for prev/next episode, filters.
+- **Hover:** Background shifts lighter (`bg-white/10`). Transition duration 200ms.
+
+### Cards / Anime Grid
+- **Corner Style:** No radius. Square corners.
+- **Background:** None at rest. Dark image placeholder (`bg-white/5`) behind anime poster.
+- **Hover:** Overlay appears (`bg-black/80`) revealing title, synopsis, and watchlist button.
+- **Internal Padding:** 12px (main content), 8px (card hover overlay).
+
+### Navigation (Sidebar)
+- **Style:** Fixed width (256px), collapsible to icons only.
+- **Default:** Text in `foreground-muted` (`#6a6b70`), no background.
+- **Hover:** `bg-white/5`.
+- **Active:** Left accent border (`w-0.5 bg-accent`), accent text color. Subtle glow (`shadow-[0_0_8px_rgba(159,122,234,0.6)]`).
+
+### Dropdowns
+- **Background:** `#1a1a1a` with shadow.
+- **No radius.** Sharp corners.
+- **Items:** 12px vertical padding, hover `bg-white/10`.
+
+### Input Fields
+- **Style:** `bg-white/5`, `border-transparent`, 8px vertical padding.
+- **Focus:** Border shifts to accent color (`focus:border-accent`).
+
+### Toast Notifications
+- **Style:** Monochromatic, no color coding by type.
+- **Background:** `bg-white/10` with `border-white/20`.
+- **No rounded corners.**
+
+## 6. Do's and Don'ts
+
+### Do:
+- **Do** use accent purple for primary actions and active states only.
+- **Do** keep interfaces dark by default—lighter backgrounds are for special emphasis only.
+- **Do** use weight contrast (semibold headings, normal body) for hierarchy.
+- **Do** reveal detail on hover (anime cards, navigation).
+- **Do** include back buttons on detail pages.
+
+### Don't:
+- **Don't** use rounded corners anywhere.
+- **Don't** use color to differentiate toast types—all toasts look the same.
+- **Don't** use gradient text.
+- **Don't** use glassmorphism (blur backgrounds, transparency effects).
+- **Don't** use hero metric layouts (big number + small label).
+- **Don't** use identical card grids with no visual variation.
+- **Don't** use modals as a first thought—inline and progressive disclosure preferred.
+- **Don't** use side-stripe borders (colored left/right borders on cards).
+- **Don't** use the green accent—violet is the one and only accent.
\ No newline at end of file
diff --git a/DESIGN_SYSTEM.md b/DESIGN_SYSTEM.md
new file mode 100644
index 0000000..18e7fdc
--- /dev/null
+++ b/DESIGN_SYSTEM.md
@@ -0,0 +1,257 @@
+# MAL Design System
+
+## Overview
+
+This design system is for the MAL anime streaming service. It provides reusable components, design tokens, and patterns for building consistent UI.
+
+## Design Tokens
+
+### Colors
+
+| Token | Value | Usage |
+|-------|-------|-------|
+| `--color-background` | `#080808` | Main page background |
+| `--color-background-sidebar` | `#0f0f0f` | Sidebar background |
+| `--color-background-header` | `#141414` | Sticky header |
+| `--color-background-surface` | `#202020` | Cards, dropdowns |
+| `--color-background-button` | `#1a1a1a` | Button default state |
+| `--color-background-button-hover` | `#252525` | Button hover state |
+| `--color-foreground-muted` | `#6a6b70` | Secondary text, icons |
+| `--color-foreground` | `#f8f9fa` | Primary text |
+| `--color-accent` | `#9f7aea` | Primary accent (violet) |
+| `--color-danger` | `#dc2626` | Error states, delete actions |
+
+### Typography
+
+| Role | Font | Size | Weight |
+|------|------|------|--------|
+| Title | DM Sans | 20px | 600 |
+| Body | DM Sans | 14px | 400 |
+| Label | DM Sans | 14px | 500 |
+| Small | DM Sans | 12px | 400 |
+
+### Spacing
+
+| Token | Value |
+|-------|-------|
+| `--space-1` | 0.25rem |
+| `--space-2` | 0.5rem |
+| `--space-3` | 0.75rem |
+| `--space-4` | 1rem |
+| `--space-5` | 1.25rem |
+| `--space-6` | 1.5rem |
+| `--space-8` | 2rem |
+
+## Components
+
+### 1. Anime Card (`anime_card.gohtml`)
+
+A poster card with hover reveal.
+
+**Usage:**
+```gohtml
+{{template "anime_card" dict "Anime" . "WithActions" true "IsWatchlist" false}}
+```
+
+**Props:**
+- `Anime` - Anime data object
+- `WithActions` - Show hover overlay with actions (bool)
+- `IsWatchlist` - Show in-watchlist state (bool)
+- `Compact` - Hide metadata below (bool)
+- `HideTitle` - Hide title below image (bool)
+- `HasTopBadge` - Adjust overlay padding for badge (bool)
+
+**States:**
+- Default: Image with subtle dark placeholder
+- Hover: Black overlay (80%) reveals title, synopsis, watchlist button
+
+### 2. Navigation (`navigation.gohtml`)
+
+Sidebar navigation with active indicator.
+
+**Usage:**
+```gohtml
+{{template "navigation" dict "CurrentPath" .CurrentPath}}
+```
+
+**Props:**
+- `CurrentPath` - Current page path for active state
+
+**Items:**
+- Home (`/`)
+- Browse (`/browse`)
+- Discover (`/discover`)
+- Watchlist (`/watchlist`)
+
+**States:**
+- Default: Muted gray text
+- Hover: `bg-white/5`
+- Active: Accent text + left border (`w-0.5 bg-accent`) + subtle glow
+
+### 3. Dropdown (`dropdown.gohtml`)
+
+Custom dropdown using `` web component.
+
+**Usage:**
+```gohtml
+
+
+
+
+
+
+
+
+
+```
+
+**Attributes:**
+- `data-align` - `left` or `right` alignment
+- `data-width` - Width (Tailwind class)
+
+**Styling:**
+- Background: `#1a1a1a`
+- No border radius
+- Items: 10px vertical padding, hover `bg-white/10`
+
+### 4. Filter Bar (`filter_bar.gohtml`)
+
+Search and filter controls for browse page.
+
+**Usage:**
+```gohtml
+{{template "filter_bar" .}}
+```
+
+**Controls:**
+- Search input (text)
+- Genre dropdown (multi-select)
+- Status dropdown (airing, complete, upcoming)
+- Type dropdown (tv, movie, ova, special, ona)
+- Sort dropdown + order toggle
+
+### 5. Header (`header.gohtml`)
+
+Sticky header with logo, search, and user menu.
+
+**Usage:**
+```gohtml
+{{template "header" .}}
+```
+
+**Sections:**
+- Left: Mobile menu toggle, sidebar toggle, logo
+- Center: Search input (desktop only)
+- Right: User avatar dropdown
+
+### 6. Watchlist Actions (`watchlist_actions.gohtml`)
+
+Watchlist toggle button.
+
+**Usage:**
+```gohtml
+{{template "watchlist_actions" dict "MalID" 123 "IsWatchlist" true}}
+```
+
+**Props:**
+- `MalID` - Anime MAL ID
+- `IsWatchlist` - Current state
+
+**States:**
+- Not in watchlist: Outline icon, accent on hover
+- In watchlist: Filled icon (`fill: currentColor`)
+
+### 7. Video Player (`video_player.gohtml`)
+
+Video player container for episodes.
+
+**Usage:**
+```gohtml
+{{template "video_player" dict "WatchData" .WatchData "TotalEpisodes" .Anime.Episodes}}
+```
+
+**Props:**
+- `WatchData` - Video source data
+- `TotalEpisodes` - Total episode count
+
+### 8. Continue Watching (`continue_watching.gohtml`)
+
+Horizontal row for continue watching section.
+
+**Usage:**
+```gohtml
+{{template "continue_watching" .ContinueWatching}}
+```
+
+**Props:**
+- Array of anime with watch progress
+
+## Patterns
+
+### Button Variants
+
+**Primary:**
+```html
+
+```
+
+**Secondary:**
+```html
+
+```
+
+**Danger:**
+```html
+
+```
+
+### Empty State
+
+```html
+
+
+
Title
+
Description
+
+
+```
+
+### Card Grid
+
+```html
+
+
+
+```
+
+### Episode List Item
+
+```html
+
+ EP{{.MalID}}
+ {{.Title}}
+
+```
+
+## Migration Guide
+
+### Adding a New Component
+
+1. Create template in `templates/components/`
+2. Document props and usage in this file
+3. Add to component index above
+
+### Updating Existing Components
+
+1. Make changes in `templates/components/`
+2. Update this documentation
+3. Test across all usage sites
+
+### Design Token Changes
+
+1. Update in `static/style.css`
+2. Update YAML frontmatter in `DESIGN.md`
+3. Update this token reference
\ No newline at end of file
diff --git a/PRODUCT.md b/PRODUCT.md
new file mode 100644
index 0000000..0cf496e
--- /dev/null
+++ b/PRODUCT.md
@@ -0,0 +1,33 @@
+# MAL - Anime Streaming & Watchlist Service
+
+## Product Purpose
+Personal anime streaming service with watchlist management for me and my friends. Simple, functional, easy to navigate.
+
+## Users
+- **Primary**: Me (owner)
+- **Secondary**: Close friends with access
+- Technical comfort: Medium - comfortable with self-hosted services
+
+## Brand Tone
+- **Practical**: No fluff, just works
+- **Clean**: Minimal aesthetic, functional over decorative
+- **Personal**: Built for us, not for distribution
+
+## Design Principles
+1. **Easy to maneuver** - Clear navigation, predictable patterns
+2. **Content-first** - Anime artwork and details take precedence
+3. **Fast interactions** - HTMX for snappy partial updates
+4. **Dark theme default** - Easy on eyes for long viewing sessions
+
+## Anti-References
+- No anime list sites (MyAnimeList, AniList clones)
+- No generic SaaS dashboards
+- No "AI slop" aesthetics - gradient text, glassmorphism, hero metrics
+
+## Register
+**Product** - Design serves the utility, not the reverse.
+
+## Technical Stack
+- Go backend (HTMX for interactivity)
+- Tailwind CSS
+- No JavaScript framework - vanilla JS only
\ No newline at end of file
diff --git a/templates/components/README.md b/templates/components/README.md
new file mode 100644
index 0000000..b2b6e3c
--- /dev/null
+++ b/templates/components/README.md
@@ -0,0 +1,32 @@
+# Components Index
+
+## Available Templates
+
+| Component | File | Purpose |
+|-----------|------|---------|
+| Anime Card | `anime_card.gohtml` | Poster card with hover reveal |
+| Continue Watching | `continue_watching.gohtml` | Continue watching row |
+| Dropdown | `dropdown.gohtml` | Dropdown wrapper (also uses ``) |
+| Filter Bar | `filter_bar.gohtml` | Search + filters for browse |
+| Header | `header.gohtml` | Sticky header with nav |
+| Navigation | `navigation.gohtml` | Sidebar navigation |
+| Video Player | `video_player.gohtml` | Episode video container |
+| Watchlist Actions | `watchlist_actions.gohtml` | Add/remove watchlist button |
+| Watch Order | `watch_order.gohtml` | Watch order queue |
+
+## Usage
+
+All components are exposed as Go templates. Import by name:
+
+```gohtml
+{{template "anime_card" dict "Anime" .Data "WithActions" true}}
+{{template "navigation" dict "CurrentPath" .CurrentPath}}
+{{template "header" .}}
+```
+
+## Props Convention
+
+Components accept a `dict` with named keys:
+- `dict "Key" .Value "Key2" .Value2`
+
+This keeps prop names explicit and self-documenting.
\ No newline at end of file