# TeamsISO v2 — Studio Terminal (approved shape brief) **Date approved:** 2026-05-13 **Approver:** Zac (operator + product owner) **Host:** WPF .NET 8 (`src/TeamsISO.App/`). WinUI 3 rebuild is abandoned. **Predecessor:** the WPF rollback at `1d1ce6a` (recording axed, settings pane tab fix, settings button wired). ## Why this redesign The v1 GUI failed the "AI made that" test. Quote from the operator: "its cluttered, screams that AI made it - and relatively inefficient to navigate." The PRODUCT.md anti-references — card-grid-of-icons, always-visible side panel, footer-as-theatre — all describe the current build. v2 commits to a different aesthetic register entirely. ## Aesthetic register **Broadcast-engineering instrument.** Not a SaaS dashboard. Not Material. Not Fluent default. Reference proximity: Linear's keyboard-first density × Avid S6 console legibility × Blackmagic ATEM's information hierarchy. The operator mental model is "I'm sitting at an audio mixer; every region has a job, no region is theatre." ## What goes away - The 72px left rail (no actual navigation — there's only one screen) - The 380px always-visible settings pane (settings change rarely, shouldn't claim permanent real estate) - The 6-column footer status row (theatre, not information) - The custom chromeless title-bar caption buttons (look worse than system chrome, break on DPI scaling) - The "by Wild Dragon" pill and the always-visible "TeamsISO" wordmark as decorative chrome - The in-call control bar as a permanent strip (only relevant in-call; should appear conditionally) - The seven identical ghost buttons in the in-call bar (textbook card-grid anti-pattern) ## What replaces it ``` ┌─ system Windows title bar [_ □ ✕] ─────────────────────┐ │ 🐉 TeamsISO [⌘K] [☾] [⚙] │ 32px header — mark + wordmark left, 3 icons right ├────────────────────────────────────────────────────────┤ │ ● 02:14:32 PART 4 · LIVE 2 DISK 482g CTRL :9755 │ transport strip — single mono line, replaces footer ├────────────────────────────────────────────────────────┤ │ │ │ ▮ alice ▮▮▮▮ t:5ms alice [LIVE] │ │ ▯ bob ▮▮ t:8ms bob [— OFF]│ participants table = the canvas │ ▮ carlos ▮▮▮▮▮ t:9ms carlos [LIVE] │ (cyan-tinted row bg = active speaker) │ ▮ guest 4 -- NO SIG guest_4 [ERROR]│ │ │ ├────────────────────────────────────────────────────────┤ │ IN CALL · Daily standup [mute] [cam] [leave] │ conditional — only renders when in call └────────────────────────────────────────────────────────┘ ``` ### Header (32px) Left: Wild Dragon mark (~20px) + "TeamsISO" wordmark in Inter 13 Medium. Click on mark opens About. Right: three icon buttons. - `⌘K` (Tabler `ti-command`) — opens command palette (also Ctrl+K, Ctrl+P shortcut) - `☾` / `☀` (Tabler `ti-moon` / `ti-sun`) — cycles theme dark ↔ light. Tooltip "Theme (System / Dark / Light)" — long-press could open the tri-state, but for v2 just a one-click cycle. - `⚙` (Tabler `ti-settings`) — opens settings drawer That's all the chrome. No nav rail because there's nothing to navigate to. ### Transport strip Single horizontal line. Mono type (JetBrains Mono 12). Replaces the entire footer. Fields: - `● 02:14:32` — green dot + session timer when at least one ISO is live; both hidden otherwise - `PART 4 · LIVE 2` — participant count and live-ISO count; "PART" / "LIVE" in Inter 11 SemiBold UPPER tracking 0.06em, numbers in mono - `DISK 482g` — free disk space on the working volume; coral text if <10GB, hidden if no relevant volume is configured - `CTRL :9755` — control surface bind; cyan text when active, hidden when off No icons. No badges. No backgrounds. Just typed status — a console heads-up display. ### Participants table — the canvas Five columns: | # | Width | Content | Type | |---|---|---|---| | 1 | 24px | State LED — 8×8 filled cyan/coral or hollow neutral | hard-edged square, no rounding | | 2 | * | Name (Inter 13/Medium) + codec/latency caption (Mono 11/Regular, tertiary fg) | "Alice Wong" / "NDIV5 · t:5ms" | | 3 | 110px | Audio meter — 5 vertical bars, instantaneous level | hard-edged, cyan when LIVE, neutral when OFF | | 4 | 130px | Output name | Mono 12 | | 5 | 100px | ISO toggle pill | LIVE = cyan fill / OFF = hollow neutral / ERROR = coral outline | Row height: 52px (was 56). Active speaker: full-row background tint `bg.active-speaker` (cyan-tinted muted neutral). NOT a left-edge stripe — that trips the impeccable "side-stripe border" ban. Each row reacts to: - Click anywhere → focuses the row, keyboard-actions apply - Click the pill → toggle ISO - Right-click → context menu (preview, custom name, copy NDI source name, save snapshot) - Hover → reveals a kebab affordance in column 5 right edge for less-frequent actions ### Conditional meeting bar Renders below the table only when `TeamsControlBridge.DetectCallState().IsInCall == true`. Slides up from below on transition (~120ms ease-out-quart on `RenderTransform.Y` + `Opacity`). Content: `IN CALL` label (Inter 11 SemiBold UPPER, cyan accent) + meeting title (Mono 12, truncated with ellipsis) + three buttons right-aligned (Mute / Cam / Leave). Share and Notes do NOT live here — they move to ⌘K, where they're invocable any time without the bar fighting for attention. Width matches the table — not full-bleed; respects the page padding. ### Ctrl+K command palette The redesign's navigation move. Replaces ~80% of what's in the v1 rail + tabbed settings. Behavior: - `Ctrl+K` (also `Ctrl+P`) opens a centered floating window over the main shell, 560×360px - Search input at the top, results list below - Empty input → frequent + recent commands - Typing → fuzzy-matches across command label + category + keywords - ↑/↓ navigates, Enter invokes, Esc closes Command categories (each command has icon, label, optional value preview, optional shortcut hint): - **Quick** — Enable all online, Stop all ISOs, Refresh discovery, Drop snapshot of all - **Teams** — Launch Teams, Hide / show Teams windows, Mute, Toggle camera, Open share, Leave call - **Presets** — Apply … (one row per saved preset), Save current as preset, Manage presets - **Output** — Framerate 24 / 30 / 60, Resolution 1080p / 720p, Aspect Pillarbox / Letterbox / Stretch - **Network** — Apply transcoder topology, Restore default NDI groups, Edit output name template - **App** — Theme dark / light / system, Open settings, About TeamsISO, Help (F1) This is the keyboard-first surface broadcasters with Stream Decks already mentally use. ### Settings — slide-over drawer Triggered from the header gear icon, or from `Open settings` in the palette, or hotkey `,` (comma). - 420px wide, slides in from the right - 40% canvas scrim behind - Three tabs: **OUTPUT** (framerate / resolution / aspect / audio + Reset to defaults), **NETWORK** (discovery / output groups + Apply transcoder topology + Restore defaults + output name template), **APP** (theme tri-state, minimize to tray, sort order, Launch Teams on startup, Auto-hide Teams windows) - Apply Changes button pinned to drawer footer; Esc dismisses; click outside the drawer dismisses DISPLAY tab from v1 gets renamed APP and absorbs the theme tri-state. ### Empty states - No participants yet: a single centered mono sentence, "no ndi sources yet — open teams and start a meeting", and one tertiary button "Refresh discovery (Ctrl+R)". No illustration, no mascot. - Not in a call: meeting bar simply doesn't render. No placeholder. - Discovery degraded: amber dot in transport strip's session timer position, mono text "NDI discovery — restarting". No banner. ## Color, theme, motion **Color strategy:** Restrained (impeccable product default). Cyan accent earns its place — reserved for LIVE state, focus ring, active speaker tint. Coral reserved for destructive + error. Status amber for warnings. Green NOT used (would compete with cyan for "ok / live" semantics). **Theme default:** Follow Windows. Theme persists per-operator via `UIPreferences.Theme`. Implementation: split `WildDragonTheme.xaml` into a single style + token-shape file plus two color-only ResourceDictionary files (`Theme.Dark.xaml`, `Theme.Light.xaml`). At runtime `ThemeManager` swaps the merged dictionary entry. WPF analog of WinUI's `ThemeDictionary`. **Motion:** - 120ms `cubic-bezier(0.16, 1, 0.3, 1)` (ease-out-quart) on the meeting bar slide-in/out - 200ms ease-out on the drawer slide - 180ms cross-fade on theme swap - 90ms on focus + hover transitions - No bounce, no elastic, no spring overshoots. Animate `RenderTransform` and `Opacity` only — never layout properties. ## Typography commitments | Token | Family | Size | Weight | Used for | |---|---|---|---|---| | `text.timer` | JetBrains Mono | 14 | Medium | Session timer in transport strip — instrument-grade | | `text.caption` | Inter | 11 | SemiBold (600) | UPPER + tracking 0.06em — transport-strip labels, "IN CALL", "SPEAKING" | | `text.display` | Inter | 22 | SemiBold | Settings drawer headings only | | `text.title` | Inter | 13 | Medium | Wordmark, table column headers | | `text.body` | Inter | 13 | Regular | Participant display names | | `text.mono.code` | JetBrains Mono | 12 | Regular | Output names, NDI IDs, meeting title | | `text.mono.tech` | JetBrains Mono | 11 | Regular | Latency readouts, codec captions, transport-strip values | ## What this is NOT - Not Fluent-styled. Default Fluent accent integration is generic Windows; TeamsISO is a broadcaster's tool. - Not minimalism for its own sake. The participants table is *dense*. Density is the broadcaster's virtue. - Not chromeless. Default system title bar stays. Chromeless windows break embarrassingly at 4K + DPI scaling. - Not vanity-branded. The Wild Dragon mark sits small in the header as a quality cue, never as decoration. ## Migration path The view-model surface in `src/TeamsISO.App/ViewModels/` is the contract. The redesign rewrites `MainWindow.xaml` and `Themes/*` but leaves view-models, the engine, the control surface server, and the OSC bridge untouched. Order of operations (each step builds clean before the next): 1. **Theme split** — Refactor `WildDragonTheme.xaml` → `Themes/Theme.Tokens.xaml` (styles + key shape) + `Themes/Theme.Dark.xaml` + `Themes/Theme.Light.xaml` (color resources only). Port `ThemeManager` from the deleted WinUI project; wire system app-mode detection via registry (`HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize\AppsUseLightTheme`). 2. **Main window shell** — Replace MainWindow.xaml's outer Grid. Add 32px header, transport strip, full-width content area, conditional meeting bar. Delete the 72px rail, the 380px right pane, the footer. 3. **Participants table redesign** — 5 columns, LED state, instantaneous audio meter, ISO pill. 4. **Settings drawer** — Slide-over from right, dismissable; reuses existing settings view-model. 5. **Command palette** — `Ctrl+K` floating window with fuzzy command list. Each step is a self-contained commit so the v1 build remains shippable at any rollback point. ## Anti-references — explicit on the "AI made that" failure These are the failure modes the redesign defends against: - Card-grid-of-icons (the v1 in-call bar's seven identical ghost buttons) - Always-visible side panel (the v1 380px settings sidebar) - Decorative chrome (the v1 "by Wild Dragon" pill, the 72px nav rail, the six-column footer) - Generic Inter at 13 for everything - Default WPF DataGrid (Excel) - Custom chromeless title bars that look generic - Gradient text, glassmorphism, side-stripe borders (impeccable absolute bans) - "Hero metric + supporting stats + gradient" SaaS dashboards - Mascots, "Welcome!" copy, illustrated onboarding cards