From 565b8dbd6f95b322f70a64f3916c84099ca88d64 Mon Sep 17 00:00:00 2001 From: gramps Date: Fri, 30 Oct 2026 07:41:43 -0700 Subject: [PATCH] docs(design): DESIGN.md becomes the visual standard (tokens merged, controls rejected) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merges the 2026-10-29 Stitch export into the existing 2026-10-26 token sheet and promotes the file from "redesign exploration" to the normative standard: - type scale (32→10px), spacing, radii and elevation levels — the three scales the old DESIGN.md listed as missing - meter thresholds: cyan ≤ -12 dB, amber -12..-3, red > -3 - interaction rules: focus ring, hover step, 150ms/90ms easing, no springs Four export tokens rejected as Material-3 warm-seed artifacts (recorded with reasons): tertiary #4cd7f6 (kept #38bdf8), outline #ab8986, outline-variant #5b403e, on-surface-variant #e4beba (kept slate #94a3b8). Product rulings recorded: #e94560 retired as the app's general accent (blue takes every interactive role, red is live/record only, wordmark artwork untouched); error gets its own surface (#93000a) so it cannot be mistaken for on-air red. The export's dock, four bays, page-nav sidebar, CPU/GPU/NVENC readouts and acrylic blur are explicitly marked exploratory, not spec — the design principle is a simpler surface, not hardware cosplay. On-stream output styling stays outside this theme. Falsified facts fixed in the same commit: product.md brand section now points at DESIGN.md for UI tokens (MARCOM.md stays the marketing palette), and ui-surface.md no longer calls DESIGN.md an unreconciled exploration. Docs-only unit: scope-check run, no build. --- DESIGN.md | 160 +++++++++++++++++++++++++++++++++++------- docs/ai/product.md | 10 ++- docs/ai/ui-surface.md | 2 +- 3 files changed, 143 insertions(+), 29 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 8c956dc..f5028ab 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,10 +1,16 @@ -# DESIGN.md — LlamaCasty visual design tokens (redesign exploration) +# DESIGN.md — LlamaCasty visual design standard -> Source: Google Stitch export, 2026-10-26, from the proposed edit-screen mockup. Colors and type -> only — no layout decisions are captured here. This is a design reference for the UX redesign -> in progress; it is not yet wired into the app's theme (`Themes/Controls.xaml`). +> **Status: the standard** (decided 2026-10-30). Token values here are normative; +> `Themes/Tokens.xaml` is the implementation, and no other file may hardcode a hex once the sweep +> lands. Two Google Stitch exports feed it (2026-10-26 edit screen, 2026-10-29 audio dock). +> +> **The exports' layouts and control drawings are exploratory, not spec.** The dock, the four +> bays, the page-nav sidebar and the skeuomorphic faders are *not* adopted — the product's design +> principle is a surface so obvious that a right-brained person can use it without a manual, and +> hardware cosplay is the opposite of that. Only the colour, type, spacing, radius and elevation +> system is adopted. -## Color +## Colour ### Surfaces (dark navy scale, darkest to lightest) @@ -18,7 +24,7 @@ | `surface-container-highest` | `#2d3449` | Selected/active row background | | `surface-bright` | `#31394d` | Lightest surface, rare use (strong hover) | | `outline` | `#334155` | Borders, dividers | -| `outline-variant` | `#1e293b` | Subtle dividers, inactive VU meter segments | +| `outline-variant` | `#1e293b` | Subtle dividers, inactive meter segments | ### Text @@ -26,42 +32,146 @@ |---|---|---| | `on-surface` | `#dae2fd` | Primary text | | `on-surface-variant` | `#94a3b8` | Secondary / label text | +| `on-surface-disabled` | `#5b6478` | Disabled text and icons | ### Accent — one role each, never mixed | Token | Hex | Role | |---|---|---| -| `tertiary` (electric blue) | `#38bdf8` | The one interactive accent: selection, focus, sliders, primary buttons, transform handles | -| `primary` (red) | `#ff5451` | **Reserved for on-air/recording state only** — LIVE badge, program border, End/Go Live | +| `tertiary` (electric blue) | `#38bdf8` | **The** interactive accent: selection, focus, sliders, primary buttons, transform handles | +| `on-tertiary` | `#0b1326` | Text/icon on a blue fill | +| `primary` (red) | `#ff5451` | **On-air / recording only** — LIVE badge, program border, End/Go Live | | `primary-container` | `#b91a24` | Red pressed/hover state | | `secondary` (amber) | `#ffb95f` | Game audio channel, Super Chat highlight | | `secondary-container` | `#ee9800` | Amber pressed/hover state | -| `error` | `#ef4444` | Error states only (distinct from the on-air red) | +| `attention` (orange) | `#ff8c3a` | Dropped frames, the live-screen indicator, blinking warnings | +| `error` | `#ef4444` | Error text and icons | +| `error-container` | `#93000a` | Error surface (health banner, toast) — keeps error visually distinct from on-air red | +| `on-error` | `#ffdad6` | Text on an error surface | -**Rule carried from the critique sessions:** red must mean "live or recording" and nothing else. -Don't reuse it for a Send button, a delete action, or any other control — that was the defect in -the first Stitch draft of the live screen. +**The rule:** red means "live or recording" and nothing else. Never a Send button, a delete action, +a brand flourish, or a general accent — that was the defect in the first Stitch draft. + +**`#e94560` is retired** as the app's general accent (it was in 15 files). Blue takes over every +interactive role; red keeps only live/record. The brand/wordmark *artwork* is unchanged — those +assets are the creator's art, not a theme value. + +### Meter thresholds (both meters, all bays) + +| Band | Range | Brush | +|---|---|---| +| Nominal | −∞ … −12 dB | `#38bdf8` | +| Caution | −12 … −3 dB | `#ffb95f` | +| Peak / clip | −3 … 0 dB+ | `#ff5451` | + +Meters are **measured, never decorative** (see `docs/ai/output.md`): the ladder shows the live +level scaled by the current gain, not the gain setting. ## Typography | Token | Family | Use | |---|---|---| | `sans` | Inter (400/500/600/700) | All UI text — labels, buttons, panel titles | -| `mono` | JetBrains Mono (500/600) | All numeric/telemetry values — bitrate, FPS, dB, coordinates, timers. Keeps digits from shifting width as values change. | +| `mono` | JetBrains Mono (500/600) | Numeric/telemetry values — bitrate, FPS, dB, coordinates, timers. Tabular figures stop digits shifting width as values change | -Icons: Material Symbols Outlined. +Icons: Material Symbols Outlined (bundled, not fetched). -## Color roles (decided 2026-10-26) +### Scale -- **Red `#ff5451`:** YouTube references, on-air/GO LIVE, and record only. -- **Attention orange `#ff8c3a`:** dropped packets, the live screen indicator, and blinking warning lights. -- **Amber `#ffb95f`:** game audio and Super Chat only. -- **`error` `#ef4444`:** unchanged for now; it sits close to the on-air red and may need revisiting. +| Token | Size / line | Weight | Tracking | Use | +|---|---|---|---|---| +| `headline-lg` | 32 / 40 | 700 | −0.02em | Landing/empty-state titles only | +| `headline-md` | 24 / 32 | 600 | −0.015em | Dialog titles | +| `headline-sm` | 18 / 24 | 600 | −0.01em | Panel and section headers | +| `body-lg` | 15 / 22 | 400 | — | Default body, chat | +| `body-md` | 13 / 18 | 400 | — | Panel rows, form text | +| `body-sm` | 12 / 16 | 400 | — | Secondary text, hints | +| `label-lg` | 13 / 16 | 600 | 0.02em | `mono` — primary telemetry values | +| `label-md` | 11 / 14 | 500 | 0.04em | `mono` — labels, hotkey chips | +| `label-sm` | 10 / 12 | 500 | 0.05em | `mono` — dense telemetry only | -## Open questions for the next pass +**Floors and implementation notes** -- These tokens have not been reconciled against the app's current WPF theme - (`Themes/Controls.xaml`). That comparison should happen once the redesign direction is locked, - not before — do not retrofit the current theme to these values yet. -- No elevation/shadow scale, corner-radius scale, or spacing scale has been captured yet. Add them - here as they're decided, rather than letting them live only in Stitch exports. +- **11px is the default label size; 10px is the absolute floor** and only for dense readouts that + sit beside a larger value. Nothing readable at 100% zoom may be smaller than 10px. +- **WPF has no letter-spacing.** Tracking values above are design intent, not a property; implement + as-is (no tracking) rather than faking it with padded strings. +- Mono numerics use `Typography.NumeralAlignment="Tabular"` so widths stay stable. + +## Spacing + +| Token | px | Use | +|---|---|---| +| `space-xs` | 4 | Inside a chip, icon-to-text | +| `space-sm` | 8 | Between related controls | +| `space-md` | 12 | Default gap inside a panel | +| `space-lg` | 16 | Panel padding, section separation | +| `space-xl` | 24 | Dialog padding, major separation | +| `gutter` | 12 | Between page columns | +| `margin` | 16 | Window edge to content | +| `margin-docked` | 8 | Edge to content when a rail/drawer is docked | + +## Shape + +| Token | px | Use | +|---|---|---| +| `radius-sm` | 4 | Chips, badges, keycap tags | +| `radius-md` | 8 | Buttons, inputs, cards, scene tiles | +| `radius-lg` | 16 | Preview viewport, drawers, dialogs | +| `radius-full` | pill | Status chips (LIVE, EDIT), toggles | + +Recessed controls (fader wells, inputs) use the same outer radius as their housing so the seams +line up — do not mix a 4px well inside an 8px card. + +## Elevation + +| Level | Use | Implementation | +|---|---|---| +| −1 recessed | Fader wells, input fields, table headers | inset top shadow + `surface-container-lowest` | +| 0 panel | The default chassis | `surface-container*` + **1px `outline` border**, no shadow | +| 1 raised | Scene tiles, floating chips, action buttons | subtle drop shadow, 0 1px 2px | +| 2 floating | Drawers, popups, dialogs | larger spread + 1px top highlight | + +**Budget rule:** `DropShadowEffect` is software-rendered in WPF. Shadows on small controls only — +**never** on the preview viewport, the scene strip, or either wing. Depth on large surfaces comes +from the surface scale and the 1px border, not from effects. + +## Interaction + +- Focus ring: 1px `#38bdf8` outside a 1px gap — visible against every surface level. +- Hover: step one surface level up; active: step two. No colour change on hover except for + destructive actions. +- Motion: 150ms `CubicEase(EaseOut)` for drawers/popovers; 90ms for hover/press. No springs — + WPF has no spring easing and hand-rolled overshoot reads as jank at 60Hz. +- Every action produces a visible outcome. No dead ends, no silent failures. + +## Not in this standard + +- The audio dock, its four bays, per-bay faders, 24-segment ladders, transport controls, lip-sync + slider and master telemetry strip — **exploratory**. The controls they re-house already exist in + the app; whether any of them gets a dock is a separate product decision. +- The page-nav sidebar (Broadcast Studio / Audio Mixer / Scene Matrix / Telemetry / Hotkeys) — the + app is one surface with an EDIT toggle and drawers, not a page router. +- CPU / GPU / NVENC readouts — no telemetry exists, and none of it changes a live decision. +- Acrylic/backdrop blur — WPF has no sub-region backdrop blur; panels are solid. +- **On-stream output** (chat box, social bar, alerts, brand flash) is styled by its own renderers, + not by this theme. Do not apply UI tokens to the broadcast picture. + +## Rejected from the 2026-10-29 export + +The export is a Material-3 dump from a warm seed; four tokens came out tinted by that seed and are +rejected in favour of the values above. + +| Export value | Token | Why rejected | +|---|---|---| +| `#4cd7f6` | `tertiary` | Neon cyan beside the amber reads "toy"; `#38bdf8` is calmer and already used in-app | +| `#ab8986` | `outline` | Warm pink borders from the seed — wrong for a navy chassis | +| `#5b403e` | `outline-variant` | Same seed artifact | +| `#e4beba` | `on-surface-variant` | Pink secondary text; slate `#94a3b8` is legible and neutral | + +## Implementation status + +- **Not yet wired.** `Themes/Controls.xaml` still carries the legacy palette and the dozens of + hardcoded hexes; `Themes/Tokens.xaml` lands next, then surfaces are converted one at a time. +- Target end state: every colour, radius and spacing value resolves from `Tokens.xaml`; a guard + test fails on any raw `#hex` outside it. diff --git a/docs/ai/product.md b/docs/ai/product.md index 4f3be7d..b89e914 100644 --- a/docs/ai/product.md +++ b/docs/ai/product.md @@ -5,9 +5,13 @@ Read before branding, marketing, pricing, licensing or packaging work. ## Brand -Brand palette and official assets live in `MARCOM.md` (gitignored — read it for hex values, -asset file names, and marketing copy). The brand red `#e94560` is the primary accent used -throughout the UI. +**The UI design standard is [`DESIGN.md`](../../DESIGN.md)** — colours, type scale, spacing, radii +and elevation, all normative, implemented by `Themes/Tokens.xaml`. Accent blue `#38bdf8` is the only +interactive accent; red `#ff5451` means live/record and nothing else. The old brand red `#e94560` is +retired from app chrome (the wordmark/logo artwork is unchanged). + +Marketing palette, official assets and copy live in `MARCOM.md` (gitignored — read it before any +branding or marketing work). ### Product name vs repo/assembly branding (2026-09-14) diff --git a/docs/ai/ui-surface.md b/docs/ai/ui-surface.md index ea17ec1..6eb3e26 100644 --- a/docs/ai/ui-surface.md +++ b/docs/ai/ui-surface.md @@ -110,7 +110,7 @@ The app is a **director's control surface**, not an editor. This replaces the OB - **Edit safety:** edit availability follows `EditingActive`; it is no longer a hard lock derived from "offline and not recording." Keep the explicit toggle and output/edit behavior distinct. - **Selected-layer preview access:** a draggable layer selected from the list temporarily gets the highest preview `Panel.ZIndex` and first priority in the preview's custom hit test, so it can be grabbed even underneath a higher scene layer. Clearing/replacing selection restores the preview stack; `Scene.Elements` order is untouched, so output and saved z-order do not change. Guard: `ytLive.Tests/SelectedLayerPreviewHitTestingTests.cs`. -**Scene thumbnails:** `Scene.Snapshot` is a 320×180 compositor render. The strip uses per-scene `ThumbnailAssetId`, then background art, then a placeholder; existing saved `OnAirImageAssetId` can still replace the staged tile. The old hardcoded CRT-thumbnail and on-air seed paths are empty, so a fresh layout no longer imports that artwork. Minis never render live captures. `DESIGN.md` records exploratory Stitch color/type tokens only; it is not a layout spec and has not been reconciled into `Themes/Controls.xaml`. +**Scene thumbnails:** `Scene.Snapshot` is a 320×180 compositor render. The strip uses per-scene `ThumbnailAssetId`, then background art, then a placeholder; existing saved `OnAirImageAssetId` can still replace the staged tile. The old hardcoded CRT-thumbnail and on-air seed paths are empty, so a fresh layout no longer imports that artwork. Minis never render live captures. `DESIGN.md` is the visual standard (tokens — `Themes/Tokens.xaml` implements them); it is not a layout spec. ## Global hotkeys (TASK 20 — step 1 shipped 2026-08-24)