# HTML-Inspired Compose TV Shell (2026-06-02)

## Package: `com.unspooled.app.ui.html`

Clean-slate Compose TV shell built from the HTML reference at `/home/rurouni/I want this ui/preview.html` + `part2.html`. Zero legacy imports. Zero deprecated patterns.

## Files (7)

| File | Purpose |
|------|---------|
| `HtmlDesignTokens.kt` | All CSS variables as Kotlin constants: colors, spacing, radiuses, focus specs |
| `HtmlGlassSidebar.kt` | Glass sidebar: 80dp/240dp, centered icons, focus ring on container |
| `HtmlPosterCard.kt` | 2:3 aspect poster card, rank badge, scale 1.075 + white border on focus |
| `HtmlCatalogRow.kt` | LazyRow + focusGroup + focusRestorer, per-card FocusRequesters |
| `HtmlHomeScreen.kt` | Static hero section + catalog rows with button focus chain |
| `HtmlSettingsShell.kt` | Two-column: left category rail + right content panel |
| `HtmlInspiredTvScaffold.kt` | Root: sidebar + content, ambient gradient, content focus blocking |

## Design Specs (from HTML CSS)

- Sidebar: 80dp collapsed, 240dp expanded, items 56dp, icon 24dp
- Glass: `rgba(255,255,255,0.065)` background, `0.11` stroke, gradient + border
- Accent: `#E3193E` (`HtmlTokens.Accent`)
- Focus: scale 1.06–1.075, white border 3dp, accent glow
- Background: radial gradient mesh (red + purple + blue spots)

## Key Patterns

### Focus ring on same composable that owns focus
```kotlin
Box(
    modifier = Modifier
        .focusRequester(focusRequester)
        .focusable(interactionSource = interactionSource)
        .focusProperties { ... }
        .border(if (isFocused) 3.dp else 1.dp, ...)
        .graphicsLayer { scaleX = scale; scaleY = scale }
)
```

### Brush/Color type unification
When `background()` receives mixed Brush/Color branches from `if/else`, use `SolidColor(color)` to wrap Color into Brush:
```kotlin
val bg: Brush = if (isPrimary)
    Brush.linearGradient(...)
else
    SolidColor(Color(0x10FFFFFF))
```

### Haze 0.7.3
No `rememberHazeState()` — use `val hazeState = remember { HazeState() }`.

## Migration Path

1. Wire `HtmlInspiredTvScaffold` into `UnspooledNavHost`
2. Replace `UnspooledHomeScreen` with `HtmlHomeScreen`
3. Replace `PremiumContentCard` with `HtmlPosterCard` (card-by-card in `HtmlCatalogRow`)
4. Replace `SettingsScreen` with `HtmlSettingsShell`
5. Replace `GlassSidebar` → `HtmlGlassSidebar`

Old legacy code remains untouched during migration — dual-path safe.
