opencd/BUGFIX_PLAN.md

488 lines
No EOL
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# BUGFIX_PLAN.md — OpenCD CSS Overhaul
> **Author:** Colonel John Hannibal Smith (A-Team command)
> **Status:** Approved — execute per work breakdown
> **Context:** Bug analysis of opencd.css + 3 templates against Ludo's 8 critical bugs
> **Date:** 2026-05-25
---
## Table of Contents
1. [Bug-by-Bug Analysis](#1-bug-by-bug-analysis)
2. [CSS to Cut — Line-Level Audit](#2-css-to-cut--line-level-audit)
3. [CD Dimension Recalculation](#3-cd-dimension-recalculation)
4. [Reset Strategy](#4-reset-strategy)
5. [Work Breakdown](#5-work-breakdown)
---
## 1. Bug-by-Bug Analysis
### Bug #1 — Inline `<style>` blocks in all 3 templates
**Current state:** Each template has an inline `<style>` block containing demo page chrome:
| Template | Lines | What's in the block |
|----------|-------|---------------------|
| jewel-case.html | 855 | `body` flex layout, `.demo-controls`, `.demo-footnote` |
| back-tray.html | 860 | Same body + `.demo-tray-container` wrapper |
| leaflet.html | 886 | Same body + `.leaflet-content--multi`, `.leaflet-pages` |
**Verdict:** These are demo scaffolding, not framework component CSS. Removing `<style>` entirely without moving this chrome somewhere breaks the demos. There are two clean approaches:
**Option A (recommended):** Create `templates/demo.css` — a shared demo chrome file imported by all 3 templates. This gets <style> out of the HTML without polluting the framework. Move all common body/control/footnote styles there. Template-specific overrides (`.leaflet-content--multi`, `.leaflet-pages`) stay close to their template but still in `demo.css`.
**Option B:** Move everything into `opencd.css` under `.demo-*` namespaced classes and import from there. This keeps a single stylesheet but bloats the framework with demo-only code.
**Decision:** Option A. Demo chrome is not framework. `demo.css` lives in `templates/` alongside the HTML.
**What moves to `demo.css`:**
- `body` block (min-height, display:flex, align-items:center, gap, padding, background) — deduplicated across all 3
- `.demo-controls` — deduplicated (leaflet has extra button + page-indicator styles, those separate)
- `.demo-footnote` — deduplicated
- `.demo-tray-container` — back-tray only
- `.leaflet-content--multi`, `.leaflet-pages` — leaflet only
**Result after fix:** Each template has `<link rel="stylesheet" href="demo.css">`, zero `<style>` blocks.
---
### Bug #2 — No comprehensive CSS user-agent reset
**Current state:** opencd.css lines 191195 has:
```css
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
```
This resets box-sizing, margin, and padding — which is good. But it's missing:
| Missing | Why it matters |
|---------|---------------|
| `font-family: inherit` | Prevents inconsistent form inputs inheriting browser default fonts |
| `font-size: 100%` | Prevents `<h1>``<h6>` and `<small>` from breaking the type scale |
| `line-height: 1.5` | Normalizes vertical rhythm across browsers |
| `border: 0` on common elements | Prevents fieldset/button/input default borders |
| `background: transparent` on buttons | Prevents default button backgrounds |
| `list-style: none` on `<ul>` / `<ol>` | Only needed if using list reset (currently `.tray-credits ol` does this) |
| `text-decoration: none` on `<a>` | For framework-styled links |
**Verdict:** Expand the existing reset to cover font inheritance, line-height, and form element defaults. Not a full `normalize.css` — just the basics that affect the jewel case layout.
---
### Bug #3 — back-tray.html renders as ~280×1305px (unreadable vertical slab)
**Root cause:** The back tray has no height constraint.
The `.back-tray` grid uses `grid-template-columns: var(--cd-spine-width) 1fr var(--cd-spine-width)` but no row template — the grid auto-creates rows per content item. The `.tray-credits` section contains 8 tracklist items, 3 production credit paragraphs, and technical info text — all flowing vertically without bound.
Physical back tray paper is 151×118mm. At 2× scale that's ~302×236px. The standalone demo should show the back tray at roughly that proportion.
**Fix strategy:**
1. **Add `--cd-tray-height`** calculated from physical dimensions:
```
--cd-tray-height: calc(236px * var(--cd-scale)); /* 118mm × 2 */
```
2. **Constrain `.back-tray` height** with `max-height: var(--cd-tray-height)` and `overflow-y: auto` (matching the real paper footprint — content that overflows physical space gets scrollable, just like a real multi-page tray insert).
3. **Tighten the content.** Back tray should show a compact tracklist + credits, not verbose paragraphs. This is a content reduction, not a CSS reduction — but B.A. should audit the template text.
4. **Fix `.demo-tray-container`** — currently `width: var(--cd-jewel-width)` but no height constraint. Add `max-height: var(--cd-tray-height)` so the demo wrapper also constrains.
---
### Bug #4 — jewel-case.html too narrow
**Root cause:** The `.cd-jewel-case` has `width: var(--cd-jewel-width)` = 280px at default scale. This IS the correct physical dimension at 2× (142mm × 2 = 284px, rounded to 280px). The issue is that the container doesn't respond to viewport width on large screens — it sits as a tiny box center-aligned.
The body centers it with flexbox, so on a 1920px screen you get a 280px box in the middle of a sea of cream background. It looks "too narrow" because there's no visual connection to viewport scale.
**Fix:**
- Add a `max-width` constraint rather than a fixed `width` on `.cd-jewel-case`:
```
width: min(var(--cd-jewel-width), 100% - 2rem);
```
This lets it fill smaller viewports while capping at CD dimensions on larger ones.
- Keep the center-alignment, but the jewel case will feel proportional rather than dwarfed.
---
### Bug #5 — leaflet.html width completely broken
**Root cause:** Inline styles override the entire layout structure:
```html
<main class="cd-jewel-case" style="width: auto; box-shadow: none; background: transparent;">
<div class="cd-jewel-inner" style="grid-column:1/-1; gap: var(--cd-space-inset);">
```
`width: auto` on the jewel case destroys the CD dimension constraint. The inner div's `grid-column: 1/-1` spans past the content column into the spine column. The `.leaflet-content` has `max-width: var(--cd-leaflet-size)` (240px) but the wrapper is now unconstrained.
**Fix:**
- Remove inline `width: auto` — use `.cd-jewel-case--leaflet` modifier class instead:
```css
.cd-jewel-case--leaflet {
width: var(--cd-leaflet-size);
box-shadow: none;
background: transparent;
}
```
- Remove inline `grid-column: 1/-1` — the `.cd-jewel-inner` already lives in grid-column 2 via the base CSS. The leaflet template doesn't have a spine, so just hide the spine grid area or use grid-template-columns differently.
- All the inline style overrides become `.cd-jewel-case--leaflet` and `.cd-jewel-case--leaflet .cd-jewel-inner` rules in opencd.css.
---
### Bug #6 — 711 lines is ~80% bloat
**Audit of current opencd.css (previously hardened — already less bloated than original):**
| Section | Lines | Verdict |
|---------|-------|---------|
| 1. Custom properties (`:root`) | 169 | **Accept as-is** — all `--cd-*` are semantic tokens per DESIGN.md. No magic numbers. |
| 2. Reset | 5 | Accept — minimal, effective |
| 3. Jewel Case | 35 | Accept — core layout |
| 4. Spine | 35 | Accept — core layout |
| 5. Leaflet | 60 | Could trim ~15 lines of redundant comments |
| 6. Disc Art | 65 | Could trim ~20 lines — `.disc-art--sheen` gradient is very verbose |
| 7. Human Advisory | 55 | Could trim ~10 lines — `.advisory-row--*` variants use only 3 of 6 defined |
| 8. Back Tray | 70 | Accept — core layout + tracklist styling |
| 9. Grid Overlay | 45 | Accept — 4 variants, all in use |
| 10. Open/Closed | 10 | Accept — state management |
| 11. Responsive | 55 | Accept — container queries for 3 breakpoints |
| 12. Print | 30 | Accept — needed |
| 13. Grain | 20 | Accept — texture utility |
**Target after trimming:** ~640 lines (trim ~70 lines of verbose comments and disc art gradient).
**Specific cuts:**
1. Lines 1820, 3840, 4952, 7073, 8386, 9093, 9899, 106109, 117119, 131134, 147149, 155157, 162164, 169171, 178180 — decorative ASCII comment separators between sections. Replace with simple `/* Section name */` comments. Saves ~45 lines.
2. Lines 386406 — `.disc-art--sheen` gradient — the 3-layer radial gradient with repeating ring is over-engineered for a disc gradient. Can be simplified to a 2-layer radial gradient. Saves ~15 lines.
3. Lines 444452 — `.advisory-row--red` and `.advisory-row--white` background variants. Only 3 of 6 advisory variants are used. Keep `.advisory-row--black` and `.advisory-row--white`. Saves ~10 lines.
---
### Bug #7 — Design tokens inconsistent across templates
**Current state analysis:** All 3 templates link to `opencd.css`, so `--cd-*` tokens ARE consistent at the framework level. However:
1. Each template's inline `<style>` block references Open Props directly (`var(--gray-6)`, `var(--red-6)`, `var(--radius-2)`, `var(--font-sans)`) instead of using `--cd-*` tokens.
2. Different font sizes used in demo controls across templates (`.875rem` in jewel-case, `.75rem` in back-tray footnotes).
**Fix:** Once `<style>` blocks are moved to `demo.css` (Bug #1), convert all direct Open Props references to `--cd-*` tokens:
- `var(--gray-6)` → `var(--cd-text-muted)` or `var(--cd-text-secondary)`
- `var(--red-6)` → `var(--cd-advisory-red)`
- `var(--radius-2)` → `var(--cd-jewel-radius)`
- `var(--font-sans)` → `var(--cd-font-label)`
- `var(--font-mono)` → `var(--cd-font-mono)`
This ensures every CSS reference across all files uses the `--cd-*` semantic layer — never raw Open Props tokens.
---
### Bug #8 — `.cd-spine--side` renders wrong
**Root cause analysis:**
```css
.cd-spine {
writing-mode: vertical-rl; /* text reads top-to-bottom */
flex-direction: column; /* items stack vertically */
}
.cd-spine--side {
writing-mode: horizontal-tb; /* text reads left-to-right */
flex-direction: row; /* items sit side-by-side */
}
```
In `back-tray.html`, the `.back-tray` grid is:
```css
grid-template-columns: var(--cd-spine-width) 1fr var(--cd-spine-width);
/* = 14px + auto + 14px */
```
The side spines (`.cd-spine--side`) sit in 14px-wide columns with `writing-mode: horizontal-tb`. Text like "OPENCD" or "TRENTUNA" in a 14px horizontal column overflows — it's illegible.
**Physical reference:** On a real CD back tray, the side spines (~7mm each) have text printed VERTICALLY — reading top-to-bottom on the left spine, bottom-to-top on the right. The text runs along the spine's length, not across its width.
**Fix:** The `.cd-spine--side` variant should NOT change writing mode — it should keep `writing-mode: vertical-rl` from the base. Instead, it should just adjust positioning:
```css
.cd-spine--side {
/* Keep base vertical writing mode but adjust layout */
writing-mode: vertical-rl; /* inherit from base — DON'T override */
}
```
Remove `writing-mode: horizontal-tb` and `flex-direction: row` from `.cd-spine--side`. The side spine will read vertically along its height, which fits within the 14px × 236px column perfectly.
For left-vs-right orientation: the back-tray.html already places `cd-spine--side` elements in columns 1 and 3 of the grid. Both will read top-to-bottom. If RTL support is needed later, add `cd-spine--side--r-t-b` for right-to-bottom (inverted vertical).
---
## 2. CSS to Cut — Line-Level Audit
### From opencd.css
| Lines | Content | Action | Saves |
|-------|---------|--------|-------|
| 17 | File header banner | Keep — project identity | 0 |
| 1116 | Section header for variables | Simplify to `/* 1. Tokens */` | -3 |
| 1820, 3840, etc. | Decorative `══════` comment blocks | Remove decorative lines, keep one-line headers | ~45 |
| 191192 | Section header for reset | Keep | 0 |
| 197198 | Section header for jewel case | Keep | 0 |
| 386406 | `.disc-art--sheen` 3-layer gradient | Simplify to 2-layer | ~15 |
| 443, 448, 453 | `.advisory-row--red`, `.advisory-row--white` unused background variants | Consolidate to `.advisory-row--black` and `.advisory-row--white` classes with `--red` via modifier | ~10 |
| 694711 | `.cd-grain` texture | Keep — used for tray paper texture | 0 |
| **Total trim target** | | | **~70 lines** |
**Target final size:** ~640 lines (from 711)
### From templates (inline `<style>` blocks)
Each template's inline `<style>` block ranges 3060 lines. After moving to `demo.css`:
| Template | Lines removed | Destination |
|----------|--------------|-------------|
| jewel-case.html | 855 (48 lines) | `templates/demo.css` |
| back-tray.html | 860 (53 lines) | `templates/demo.css` |
| leaflet.html | 886 (79 lines) | `templates/demo.css` |
### From leaflet.html inline style attributes
| Inline style | Action |
|--------------|--------|
| `style="width: auto; box-shadow: none; background: transparent;"` on `<main>` | Move to `.cd-jewel-case--leaflet` class |
| `style="grid-column:1/-1; gap: var(--cd-space-inset);"` on `.cd-jewel-inner` | Move to `.cd-jewel-case--leaflet .cd-jewel-inner` |
| `style="position:static; align-self:flex-end;"` on `.human-advisory` | Consider `.human-advisory--inline` variant |
| `style="margin-left:1rem; color:var(--cd-text-secondary); line-height:1.6;"` on `<ul>` | Move to opencd.css: `.leaflet-page ul` rule |
| `style="margin-top:.5rem; display:grid; gap:.25rem; font-size:var(--size-fluid-1);"` on `<dl>` | Move to opencd.css: `.leaflet-page dl` rule |
| `style="font-family:var(--font-mono); color:var(--gray-6);"` on `<dt>` | Move to opencd.css: `.leaflet-page dt` rule |
| `style="color:var(--gray-7);"` on `<dd>` | Move to opencd.css: `.leaflet-page dd` rule |
| `style="margin-top:.5rem;"` on `<p>` | `.leaflet-page p + p` sibling rule in CSS |
---
## 3. CD Dimension Recalculation
### Current dimension tokens
| Token | Current value | Physical | Ratio |
|-------|--------------|----------|-------|
| `--cd-jewel-width` | calc(280px × scale) | 142mm | 1.97px/mm |
| `--cd-jewel-height` | calc(245px × scale) | 125mm | 1.96px/mm |
| `--cd-jewel-open-width` | calc(560px × scale) | 284mm | 1.97px/mm |
| `--cd-spine-width` | calc(14px × scale) | ~7mm | 2.0px/mm |
| `--cd-disc-diameter` | calc(240px × scale) | 120mm | 2.0px/mm |
| `--cd-leaflet-size` | calc(240px × scale) | 120mm | 2.0px/mm |
| `--cd-tray-width` | calc(260px × scale) | ~130mm | 2.0px/mm |
| `--cd-tray-height` | **MISSING** | 118mm | — |
### Correction needed
**Add `--cd-tray-height`:**
```
--cd-tray-height: calc(236px * var(--cd-scale)); /* 118mm × 2 */
```
**This dimension drives Bug #3 fix** — the back tray height constraint.
### `--cd-scale` semantics (already correct in current code)
Current implementation: `--cd-scale: 1` = default 2× display scale. The formulas use the 2× px value multiplied by scale. This is unambiguous:
```
Default (scale=1): width = 280px
1× physical (scale=0.5): width = 140px
4× display (scale=2): width = 560px
```
Document this clearly in `_variables.css` comment. No changes needed — the current approach matches RECON.md recommendation.
### Template width fixes
| Template | Current width | Fixed width | Rationale |
|----------|--------------|-------------|-----------|
| jewel-case.html | 280px (fixed) | `min(280px, 100% - 2rem)` | Responsive on small, accurate on large |
| back-tray.html | 280px (via `.demo-tray-container`) | `min(280px, 100% - 2rem)` with `max-height: var(--cd-tray-height)` | Physical constraints |
| leaflet.html | `auto` (broken) | `min(var(--cd-leaflet-size), 100% - 2rem)` via `.cd-jewel-case--leaflet` | CD leaflet size + responsive |
---
## 4. Reset Strategy
### Target: Minimal but complete
The existing reset covers: box-sizing, margin, padding on all elements.
**Expanded reset:**
```css
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 100%;
line-height: 1.5;
-webkit-text-size-adjust: 100%;
}
body {
font-family: inherit; /* Each template sets its own family via demo.css */
}
img, svg, video, canvas {
display: block;
max-width: 100%;
}
button, input, select, textarea {
font: inherit;
border: 0;
background: transparent;
}
a {
color: inherit;
text-decoration: none;
}
ul, ol {
list-style: none;
}
h1, h2, h3, h4, h5, h6 {
font-size: inherit;
font-weight: inherit;
}
```
This is ~35 lines — lean, covers all the gaps identified in Bug #2. No external normalize, no `@import` of reset. The reset is self-contained.
---
## 5. Work Breakdown
### Phase 1 — Murdock: `templates/demo.css` (Bug #1, #7)
**Task:** Extract all inline `<style>` blocks into `templates/demo.css`.
**Steps:**
1. Create `templates/demo.css` with all common demo chrome (body flex layout, `.demo-controls`, `.demo-footnote`)
2. Convert all raw Open Props references to `--cd-*` tokens
3. Add template-specific sections for leaflet's `.leaflet-content--multi`, `.leaflet-pages` styles
4. Update all 3 templates to: remove `<style>` blocks, add `<link rel="stylesheet" href="demo.css">`
5. Verify all 3 templates render identically in a browser
**Files:** `templates/demo.css` (new), `templates/jewel-case.html` (edit), `templates/back-tray.html` (edit), `templates/leaflet.html` (edit)
---
### Phase 2 — Murdock: Leaflet inline styles to CSS (Bug #5)
**Task:** Replace all inline `style="..."` attributes in leaflet.html with proper CSS classes.
**Steps:**
1. Add `.cd-jewel-case--leaflet` modifier in opencd.css
2. Add `.cd-jewel-case--leaflet .cd-jewel-inner` override
3. Add `.human-advisory--inline` variant for leaflet's positioned static advisory
4. Add `.leaflet-page ul`, `.leaflet-page dl`, `.leaflet-page dt`, `.leaflet-page dd`, `.leaflet-page p + p` rules in opencd.css leaflet section
5. Update leaflet.html: remove all inline style attributes, add classes
**Files:** `opencd.css` (edit), `templates/leaflet.html` (edit)
---
### Phase 3 — B.A.: CSS trim + spine fix (Bug #6, #8)
**Task:** Trim bloat from opencd.css and fix `.cd-spine--side`.
**Steps:**
1. Strip decorative comment blocks, replace with simple `/* Section */` headers
2. Simplify `.disc-art--sheen` gradient to 2-layer
3. Consolidate `.advisory-row--*` variants
4. Fix `.cd-spine--side`: remove `writing-mode: horizontal-tb` and `flex-direction: row` overrides
5. Verify `.cd-spine--side` renders vertically in back-tray.html
**Files:** `opencd.css` (edit)
---
### Phase 4 — B.A.: Reset expansion + dimension fixes (Bug #2, #3, #4)
**Task:** Expand the reset in opencd.css, add tray height, fix jewel case width strategy.
**Steps:**
1. Replace existing 5-line reset with ~35-line expanded reset
2. Add `--cd-tray-height` token in `:root`
3. Add `max-height: var(--cd-tray-height)` to `.back-tray` with `overflow-y: auto`
4. Change `.cd-jewel-case` width from fixed to `min(var(--cd-jewel-width), 100% - 2rem)`
5. Add `max-height: var(--cd-tray-height)` to `.demo-tray-container` (in demo.css)
6. Tighten back-tray.html content — condense verbose paragraphs
**Files:** `opencd.css` (edit), `templates/demo.css` (edit), `templates/back-tray.html` (edit)
---
### Phase 5 — Amy: Validation (after BA completes Phases 3 & 4)
**Task:** Visual regression check on all 3 templates.
**Checklist:**
- [ ] jewel-case.html renders at ~280×245px, centered, responsive on small viewports
- [ ] jewel-case.html `data-jewel-state="open"` doubles width, back-tray appears
- [ ] back-tray.html renders at ~280×236px, not a vertical slab
- [ ] back-tray.html side spines show vertical text, readable
- [ ] leaflet.html renders at ~240×240px, not stretched to full viewport
- [ ] leaflet.html multi-page navigation works (prev/next buttons)
- [ ] No `<style>` blocks in any HTML template
- [ ] No raw Open Props tokens (`var(--gray-*)`, `var(--font-*)`, etc.) in any file except opencd.css `:root` definitions
- [ ] All 3 templates look identical to current renders after the refactor
---
## Execution Order
```
┌─────────────────────┐
│ PHASE 1 (Murdock) │
│ demo.css extraction │
│ + token conversion │
└─────────┬───────────┘
┌─────────▼───────────┐
│ PHASE 2 (Murdock) │
│ leaflet inline→CSS │
└─────────┬───────────┘
┌───────────────┼───────────────┐
│ │ │
┌────────▼───────┐ ┌────▼───────┐ │
│ PHASE 3 (BA) │ │ PHASE 4 │ │
│ CSS trim + │ │ (BA) │ │
│ spine fix │ │ Reset + │ │
└────────┬───────┘ │ dimensions │ │
│ └────┬───────┘ │
│ │ │
└───────────────┼───────────────┘
┌─────────▼───────────┐
│ PHASE 5 (Amy) │
│ Visual validation │
└─────────────────────┘
```
Murdock handles content extraction (Phases 12). B.A. handles structural CSS (Phases 34). Amy validates (Phase 5). I oversee and sign off.
---
*"I love it when a plan comes together."*
— Colonel John Hannibal Smith, A-Team Commander