--- name: theatrical-html-reader description: Design system and code patterns for turning a long literary/theatrical text (play, poem, libretto, script) into a polished, standalone, single-file HTML reading edition — with light/dark/system theming, selectable accent colors, a collapsible table-of-contents drawer, draggable floating controls, and localStorage-based preference persistence. Use this whenever the user wants to convert a manuscript, play script, or long-form text into a styled HTML page, especially if they mention a reading theme, dark mode, a table of contents menu, or want the result to feel like a designed reading app rather than a plain document. Also use when asked to add theme pickers, hamburger/TOC menus, draggable UI controls, or "remember my settings" behavior to an existing HTML artifact — the patterns and known pitfalls here (see gotchas.md) apply broadly, not just to plays. --- # Theatrical HTML reader A reusable design system for converting long structured texts (plays, poems, libretti) into single-file, distraction-light HTML reading editions. Built and refined over several iterations — reuse it rather than re-deriving these choices from scratch. ## When to use this - "Convert this play/script/poem into HTML" - "Make this a nice reading page with dark mode" - "Add a table of contents menu" / "hamburger menu" - "Let users pick a color theme" - "Make the floating buttons draggable" / "remember user preferences" Even for a request that only touches one piece (e.g. "just add dark mode"), check `references/gotchas.md` first — several of these patterns have subtle failure modes that are easy to reintroduce. ## Design decisions (apply by default unless the user says otherwise) **Typography**: pair a serif for reading (`Newsreader`) with a sans for UI chrome — buttons, labels, TOC entries (`Inter`). Base size ~18–19px, line-height 1.7–1.75. Don't shrink body font on mobile; only display headlines shrink via `clamp()`. **Color**: a small variable set, not a full design-token system — `--ink`, `--ink-soft`, `--bg`, `--bg-panel`, `--accent`, `--rule`. Default to a light, warm-neutral background (not stark white, not the generic cream `#F4F1EA`) with near-black ink, one restrained accent color used sparingly (speaker names, act/scene numbers) rather than decorating everything. **Theming**: three states — Light / Dark / System (`Auto`) — via `data-theme` attribute on ``, plus a small set of selectable accent colors via `data-accent`. Dark-mode accents need their own brighter values (don't reuse the light-mode hex on a dark background — contrast breaks). Full CSS variable structure: `assets/theme-system.css`. **Floating controls**: keep navigation (TOC) and preferences (theme/accent) as two separate, discreet corner icon buttons — don't combine them into one menu. Each opens on tap/click; a real drag (past a ~6px threshold) instead repositions the button. Both are draggable so a user can move a control off of content it happens to overlap. See `assets/drag-reposition.html` and `references/gotchas.md` (#1, #2, #7) before touching this — there's a click-eating bug that's easy to reintroduce. **Navigation pattern**: a full-height off-canvas drawer sliding from the left edge for TOC/contents, with a dimming backdrop; closes on backdrop click, ✕ button, Escape, or selecting a link. See `assets/toc-drawer.html`. **Preferences panel pattern**: a small dropdown card anchored to its trigger button, position recalculated on every open via `getBoundingClientRect()` so it never overflows the viewport even after the trigger has been dragged. See `assets/settings-dock.html`. **Persistence**: `localStorage`, wrapped in `try/catch` with an in-memory fallback, namespaced under one JSON blob (not many separate keys). Restore theme/accent in a blocking `