# TvLayoutMetrics Spacing Audit (2026-06-03)

## Discovery

`TvLayoutMetrics` is a 3-tier responsive layout system (720p/1080p/4K) with fluid poster sizing, dynamic hero heights, and resolution-aware typography. **It exists but is barely wired** — only 4 files call `rememberTvLayoutMetrics()`.

## Responsive Breakpoints (TvLayoutMetrics.kt)

| Property | < 960dp (720p) | < 1280dp (1080p) | ≥ 1280dp (4K) |
|----------|---------------|-------------------|---------------|
| posterColumns | 5 | 6 | 7 |
| settingsRailWidth | 200dp | 220dp | 260dp |
| contentPadding | 16dp | 24dp | 28dp |
| posterWidth | fluid (96-190) | fluid (96-190) | fluid (96-190) |
| heroHeight | fluid (280-460) | fluid (280-460) | fluid (280-460) |
| titleSp | 22 | 26 | 28 |
| bodySp | 13 | 14 | 15 |
| inputHeight | 44dp | 48dp | 52dp |
| contentMaxWidthFraction | 0.96 | 0.92 | 0.88 |
| dialogMaxHeightFraction | 0.88 | 0.85 | 0.82 |

Poster width formula: `(width - rail - pad*2) / (columns + 0.6)` clamped to [96, 190]dp — the 0.6 leaves a "peek" of the next card.

## Adoption: Only 4 Files

```
ui/theme/TvLayoutMetrics.kt          — definition
ui/screens/search/SearchScreen.kt    — uses metrics.inputHeight, contentPadding, posterWidth
ui/screens/settings/DebridServicesScreen.kt  — uses 4 metrics properties
ui/screens/profiles/ProfileCreateScreen.kt   — uses 2 metrics properties
```

## What Uses Hardcoded dp Instead

### Cards — all 7 CardSpec presets are hardcoded dp

```
CardSpec.Standard    142×213  poster      ← home screen uses this
CardSpec.Compact     110×165
CardSpec.Cinematic   140×210
CardSpec.Banner      268×150
CardSpec.Landscape   260×148
CardSpec.WideBanner  480×160
CardSpec.Square      160×160
```

`TvLayoutMetrics.posterWidth` (dynamically computed) is never passed into the card system.

### Home Row Layout — all hardcoded

```
Row bottom padding     24.dp
Row left margin        52.dp   (start padding)
Row title bottom pad   12.dp
Horizontal card gap    14.dp   (Arrangement.spacedBy)
Horizontal edge pad    52.dp   (contentPadding)
```

### Hero — hardcoded 400.dp

```
heroHeight = 400.dp               ← hardcoded at call site
Hero spacer below     24.dp
Filter ↔ content gap  16.dp
```

`TvLayoutMetrics.heroHeight` computes `(height * 0.62f).coerceIn(280f, 460f)` but is unused.

### Sidebar — hardcoded via CinematicTheme

```
SidebarExpanded       252.dp       ← close to TvLayoutMetrics 4K rail (260.dp) but static
SidebarCollapsed       82.dp
```

### Text Sizes — all static from Type.kt

`TvLayoutMetrics.titleSp`/`bodySp` are defined but never consumed. Everything uses `buildNuvioTypography()` static values. Card titles: `titleSmall` (14.sp). Card description: `bodySmall` (12.sp). Card metadata: `labelMedium` (12.sp).

### Spacing Frequency Inventory

| Value | Usage count | Where | Responsive? |
|-------|-------------|-------|-------------|
| `16.dp` | 38 | Spacers, padding, item gaps | No |
| `8.dp` | 36 | Inner padding, icons | No |
| `12.dp` | 34 | Card inner, section gaps | No |
| `24.dp` | 25 | Row bottom, section gaps | No |
| `4.dp` | 19 | Tight gaps | No |
| `52.dp` | 17 | Row left margin | No |
| `14.dp` | 14 | Card horizontal gap | No |
| `48.dp` | 8 | Button/input heights | No |
| `400.dp` | 1 | Hero height | No |
| `96.dp` | 1 | Backdrop overlay height | No |

### Unused Constants

- `TvContentInset` = 24.dp — defined in `TvContentInset.kt` but **never imported**. All rows use 52.dp instead.

### Focus Halo — Mixed

```
Focus ring border     3.dp focused / 1.dp unfocused   (hardcoded in PremiumContentCard)
Shadow elevation     18.dp                              (hardcoded)
Glow radius          12.f                               (passed to adaptiveFocusHalo)
```

## What Needs Rewiring (Phase 11 Reality)

The constitution Phase 11 (Responsive) was marked complete based on `TvLayoutMetrics` existing. In reality, the responsive infrastructure is built but not applied:

| System | Defined | Wired |
|--------|---------|-------|
| `TvLayoutMetrics.posterWidth` | ✅ | ❌ — cards use `CardSpec.Standard` (142dp) |
| `TvLayoutMetrics.heroHeight` | ✅ | ❌ — hero uses `400.dp` |
| `TvLayoutMetrics.contentPadding` | ✅ | ❌ — rows use `52.dp` |
| `TvLayoutMetrics.settingsRailWidth` | ✅ | ❌ — sidebar uses `CinematicTheme.SidebarExpanded` (252dp) |
| `TvLayoutMetrics.titleSp/bodySp` | ✅ | ❌ — text uses static `Type.kt` |
| `TvLayoutMetrics.posterColumns` | ✅ | ❌ — home doesn't use it to lay out visible cards |
| `TvLayoutMetrics.inputHeight` | ✅ | ✅ (2 screens) |
| `CinematicTheme` tokens | ✅ | ✅ (sidebar only) |
| `TvContentInset` constant | ✅ | ❌ — never imported, shadowed by 52dp |
