Commit Graph
9 Commits
Author SHA1 Message Date
gramps 70fcf89f9e feat(topbar): the recording lives in the pill — green pulse, REC clock, Stop Recording
Build 730 (creator):

- Left pill while recording: solid #2ECC71 dot pulsing 1.0 <-> 0.2 on the existing one-second timer, and
  "REC: hh:mm:ss" in Consolas so the digits cannot jitter the pill's width. Idle face unchanged.
- Right pill while recording: a stop square and "Stop Recording"; clicking it runs the normal stop, which
  halts and resets the clock and returns the pair to "Local MP4" / "Start Recording".
- The separate reality line (dot + REC/LIVE + elapsed + End) is now LIVE-ONLY: a recording would otherwise
  print the same three facts twice. RunningVisible is IsLive, and ShowOutputStage no longer hides itself
  for a recording (it must be on screen to carry the clock and the stop).

Two rules collided and are now separated rather than merged: a creator's Stop on a recording restores the
Local MP4 pair (build 730), while a pipeline FAILURE still clears both pills (the 2026-09-01 zombie rule).
StopStream(afterFailure:) carries the difference, and the pump-failure path passes it.

RealAppHost.Run was rethrowing with `throw failure;`, which destroyed the original stack — a failing
assertion inside the action reported the wrapper's line instead of its own. ExceptionDispatchInfo now
preserves it; that is how the two failures above were located in one pass instead of five.

680 pass (one audio-pipe instance flake under full-suite load, passes alone), 0 warnings.
Scope justification: Assets/starting-background.jpg is outside this unit — the creator's replacement art,
still awaiting their visual check.
2026-11-12 16:52:36 -08:00
gramps 6b4aa99863 feat(topbar): the segmented mode switcher, to the mock
Implements the creator's mock (2026-11-12) for the world segment: pill track (#1E222B, radius 12,
padding 4) holding two equal halves; the active half sits on a lighter pill (#2E3440, radius 8) with
#E2E8F0 bold text and a coral (#F26D6D) icon; the inactive half is #8892A4 on a one-alpha black face so
the whole area hit-tests; hover tints #252A34 on the inactive half only, so the active one never looks
clickable-but-dim. Labels are "Build scenes" / "Record / go live".

Two deliberate deviations from the pasted recipe, both to honour this repo:
- State is the existing BarWorld binding plus a command, not a code-behind SetActiveMode — one source of
  truth, and the change still raises the same property-changed notification a mode event would.
- Styles live in Themes/Controls.xaml (SegmentHalf, SegmentIcon) with colours as tokens in Tokens.xaml,
  rather than inline properties on the elements: AGENTS requires shared styles, and one DataTrigger on
  each element's own Tag serves both halves.

DesignTokensTests caught the one raw literal (#01000000) and it is now Brush.SegmentHitArea, which is the
rule working as intended.

680 pass, 0 warnings. Scope justification: Assets/starting-background.jpg is outside this unit — the
creator's replacement art, still awaiting their visual check.
2026-11-12 16:20:25 -08:00
gramps d25dbf58dc design: white ink on any accent fill (on-accent token)
The EDIT button's armed face used on-tertiary (#0b1326 navy) on blue — the creator read it as grey
on blue and could not read it. Same problem, latent, on the armed REC/ON-AIR pills, which used the
error ink.

One rule instead of two exceptions: a saturated accent fill carries WHITE ink. New token
on-accent #ffffff, used by the EDIT trigger and RecordPillToggle; on-tertiary stays for large blue
surfaces where dark ink is right. UiShellTests pins the EDIT foreground to it.
2026-10-30 10:34:19 -07:00
gramps 4841c27514 feat(ui): the creator's six corrections
1. Stream Info + YPP rails are YouTube surfaces → new `youtube` token #ff0000. It is documented
   as brand-only: live state stays `primary`, so the two reds never mean the same thing.
2. EDIT toggle: the checked trigger set the SAME colour as the resting face, so clicking it
   changed nothing visible. Resting is now the neutral surface with muted text; armed is blue with
   dark text, and the label follows the fill.
3. Active scene outline is orange again (`attention`) — it marks the scene you work on, not a
   selection; blue made it read as "selected". Live stays red.
4. Scene names wear the same pill as the hotkey chips (black, 10px radius, 8×2 padding), so both
   labels stay readable over any thumbnail.
5. REC / ON-AIR pills and the running stop button read red while armed/live — including test
   mode, where the top bar is gold. New `RecordPillToggle` style (its own template, because
   SegmentToggle hard-codes a transparent face); the stop button's grey `#333` literal is gone.
6. The properties list had `MaxHeight="420"` inside an Auto row, so it scrolled while the window
   had space left. The row is `*` now and the cap is gone.

Guard: UiShellTests pins all six to the markup and names the one that regresses.
2026-10-30 10:27:11 -07:00
gramps ec01a7deb8 design: the last VM-side colours come from tokens (ThemeBrush)
The state colours the view-models hand to bindings — top bar, REC/ON-AIR dots, health banner,
meter bands, toast tints — were hex literals in C#. They now resolve from Themes/Tokens.xaml
through `Helpers/ThemeBrush`, so the values live in one place. Without an Application (unit tests)
the helper returns a neutral grey: visibly wrong rather than silently plausible.

Four tokens the code needed and the document lacked, added to DESIGN.md (so the doc-is-the-contract
guard demanded their brushes): info-container #3a3b52, success-container #1d5c38,
warning-container #b8860b, test-container #9c6f1c (the test-stream gold bar).

Also fixed by this: the top bar still painted the RETIRED brand red #e94560 when live — the
standard's #ff5451 now, and `OnAirSignTests` (which pinned the old value) says so. BarOn/BarOff
became properties rather than static fields, because a static field would resolve tokens before
the Application exists.

Verified: DesignTokensTests, GameMeterHonestyTests, NotificationAreaIntegrationTests,
OnAirSignTests, SessionTeardownTests — 38 tests green.
2026-10-30 09:58:52 -07:00
gramps 3edb0d10be design: three tokens the sweep needed — positive, scrim-dark, scrim-dark-strong
The palette had no green for status and no black scrim, so two surfaces were about to either
invent literals or misuse an accent. Creator's call (2026-10-30): give green a token rather
than painting "connected" blue, which already means five other things.

- `positive` #22c55e — STATUS ONLY (connected, applied, healthy). Never an accent, never a
  button fill; the doc says so and the guard parses the doc.
- `scrim-dark` #26000000 (15% black) and `scrim-dark-strong` #00000080 (50%) — the preview's dim
  strips and heavy overlays. 18 sites justify a token, and they are structural, not decoration.
- LeftPanel's ✓ confirm now wears `positive` instead of the interactive accent, matching the
  status rule the new token states.

DesignTokensTests still green: the doc is the contract, so the three new rows demanded three
new brushes and got them.
2026-10-30 08:03:18 -07:00
gramps 4ef84f2a97 design: convert Themes/Controls.xaml to tokens (surface 1 of the sweep)
The theme file that every control inherits is now token-driven: 73 hardcoded colours became
Brush.* references, and the two role changes the standard requires landed here first.

- Red leaves the chrome. The seven #e94560 sites (base button, focus borders, checked box and
  segment backgrounds, the selected-layer accent strip) were all interactive/selection roles,
  so they are blue now. Red stays for live/record only.
- The slider was green: its fill and gloss knob are blue now, with the track on
  SurfaceContainerLowest. The old green fill predated the standard.
- The pill toggle was ON = green, OFF = red — a settings control using the live colour. It is
  now OFF = neutral surface, ON = blue.
- Added scrim-soft/scrim-strong tokens (#22FFFFFF/#26FFFFFF) for the existing white washes, and
  Color.* resources for the two gradients (a GradientStop needs a Color, not a Brush).

Guard: DesignTokensTests gains Converted_surfaces_carry_no_raw_colour — a declared list of
converted files, so each sweep commit is guarded as it lands instead of waiting for one global
grep at the end. Pure white/black highlights are the only allowed literals.

No layout, spacing or behaviour change: this unit is colour only.
2026-10-30 07:47:00 -07:00
gramps 84c335a929 design: bundle Inter + JetBrains Mono (OFL-1.1) as the standard typefaces
The DESIGN.md type standard needs the fonts actually present — the machine's installed faces
are not a design system. Four Inter weights (400/500/600/700) and two JetBrains Mono weights
(500/600) ship as WPF resources from Assets/Fonts; the token families resolve them with the
`/Assets/Fonts/#Family` pack form, so nothing depends on an install or a network fetch.

Licensing (recorded in docs/ai/product.md): OFL-1.1 is a free licence but is NOT GPL-compatible
in the linking sense. These are separate .ttf files loaded through WPF's font stack — an
aggregate, not linked code — so they coexist with the GPL-3.0 app. Obligations carried:
copyright line in THIRD-PARTY-NOTICES.txt (new items 13-14), the OFL text beside the files
(Assets/Fonts/OFL-*.txt), no modification, no reserved-name reuse.

Guard: BundledFontsTests — files exist and are real binaries, the csproj ships them, the theme
uses pack URIs (a bare family name would silently fall back), the notice and both OFL texts are
present, and no third font family sneaks in.

Pending visual confirmation: the first launch should render panel text in Inter and telemetry
in JetBrains Mono.
2026-10-30 07:45:19 -07:00
gramps f2bf577f34 design: Themes/Tokens.xaml — one place a raw value may live, guarded by DESIGN.md
Tokens.xaml carries every colour, type size, spacing step, radius and motion duration from
DESIGN.md; App.xaml merges it BEFORE Controls.xaml so styles can resolve tokens.

Guard (DesignTokensTests, 4 facts): the test PARSES DESIGN.md — the colour tables under
"## Colour" are the contract — and fails if a documented token has no brush, if the hex
disagrees, if the meter bands drift, if Tokens ever merges after Controls, or if the retired
brand red #e94560 comes back as a token. Adding a colour to the standard now requires
implementing it, and changing the theme without the document is caught.

Inter/JetBrains Mono are declared as token families with system fallbacks; the bundled font
assets are the next unit.

No surface consumes tokens yet — this unit is the foundation only.
2026-10-30 07:43:17 -07:00