diff --git a/Controls/TopBar.xaml b/Controls/TopBar.xaml
index 471360c..8a35538 100644
--- a/Controls/TopBar.xaml
+++ b/Controls/TopBar.xaml
@@ -66,141 +66,122 @@
question "which world am I in?" and "can I edit?" cannot disagree. Clicking the
highlighted half re-enters it, which is how a creator gets back to the layers
during a session. -->
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
0.5 ? 0.2 : 1.0;
OnPropertyChanged(nameof(RecDotOpacity));
- OnPropertyChanged(nameof(RecordChipText));
+ OnPropertyChanged(nameof(RecordActionLabel));
// TASK 55·3: the last useful warning before the encoder fails for a reason it won't explain.
if (IsRecording && !_lowDiskWarned && _recordFolder is { } folder
diff --git a/ViewModels/MainViewModel.Streaming.cs b/ViewModels/MainViewModel.Streaming.cs
index 699558d..37c22cc 100644
--- a/ViewModels/MainViewModel.Streaming.cs
+++ b/ViewModels/MainViewModel.Streaming.cs
@@ -87,7 +87,7 @@ public partial class MainViewModel : ViewModelBase
OnPropertyChanged(nameof(ShowChatInactiveMessage));
OnPropertyChanged(nameof(ShowPreviewPlaceholder));
RaiseTopBarModes();
- RaiseOutputStage(); // IsLive drives ShowOutputStage
+ RaiseActivityStage(); // IsLive drives ShowOutputStage
UpdateLiveVisuals();
}
}
@@ -118,7 +118,7 @@ public partial class MainViewModel : ViewModelBase
{
if (!SetProperty(ref _recordPillOn, value)) return;
if (value && _onAirPillOn) OnAirPillOn = false; // record-OR-live — arming REC drops ON-AIR
- RaiseOutputStage();
+ RaiseActivityStage();
OnPropertyChanged(nameof(ShowPrimaryStartButton));
OnPropertyChanged(nameof(PrimaryStartKind));
OnPropertyChanged(nameof(PrimaryStartButtonLabel));
@@ -138,7 +138,7 @@ public partial class MainViewModel : ViewModelBase
// intent, not reality; the Start face turns this into a sign-in.
if (!SetProperty(ref _onAirPillOn, value)) return;
if (value && _recordPillOn) RecordPillOn = false; // record-OR-live — arming ON-AIR drops REC
- RaiseOutputStage();
+ RaiseActivityStage();
OnPropertyChanged(nameof(ShowPrimaryStartButton));
OnPropertyChanged(nameof(PrimaryStartKind));
OnPropertyChanged(nameof(PrimaryStartButtonLabel));
@@ -171,7 +171,7 @@ public partial class MainViewModel : ViewModelBase
OnPropertyChanged(nameof(EndButtonText));
OnPropertyChanged(nameof(ShowTestButton));
RaiseTopBarModes();
- RaiseOutputStage(); // Start Recording <-> Stop Recording, and the REC clock
+ RaiseActivityStage(); // Start Recording <-> Stop Recording, and the REC clock
UpdateSessionTimer();
}
}
diff --git a/ViewModels/MainViewModel.TopBar.cs b/ViewModels/MainViewModel.TopBar.cs
index c729eae..e82d9b7 100644
--- a/ViewModels/MainViewModel.TopBar.cs
+++ b/ViewModels/MainViewModel.TopBar.cs
@@ -3,123 +3,115 @@ using ytLive.Helpers;
namespace ytLive.ViewModels;
-/// Which half of the top bar's dual segment is in force.
-public enum BarWorld
+/// What the app is doing (creator, 2026-11-13): build, record, or stream. Three activities,
+/// three buttons, always visible.
+/// Which YouTube stream is armed. Choosing does not start it — Start does.
+public enum StreamMode
{
- /// Build Scenes — the edit surface. The default at launch (creator ruling 2026-11-12).
- Build,
-
- /// Record / Go Live — the output surface: which output, and the one action that starts it.
- Output,
+ None,
+ Live,
+ Private,
+}
+
+public enum TopActivity
+{
+ Build,
+ YouTube,
+ Record,
}
-///
-/// The top bar's one decision (creator ruling 2026-11-12): [ Build Scenes ][ Record / Go Live ].
-/// Build Scenes is edit mode — there is no separate EDIT toggle any more, so "may I edit?" and
-/// "which world am I in?" cannot disagree.
-///
-/// Clicking the highlighted segment is not a no-op: it re-enters that world, which matters while a
-/// session runs because Build Scenes is the only way back to the layers (see
-/// ).
-///
public partial class MainViewModel
{
- private BarWorld _barWorld = BarWorld.Build;
+ private TopActivity _activity = TopActivity.Build;
- public BarWorld BarWorld => _barWorld;
+ public TopActivity Activity => _activity;
- public bool IsBuildWorld => _barWorld == BarWorld.Build;
- public bool IsOutputWorld => _barWorld == BarWorld.Output;
+ public bool IsBuildActivity => _activity == TopActivity.Build;
+ public bool IsYouTubeActivity => _activity == TopActivity.YouTube;
+ public bool IsRecordActivity => _activity == TopActivity.Record;
- /// The output stage belongs to the Record / Go Live world, and only while nothing is
- /// running — a live session cannot change its output, so its switch is not offered.
- // A recording KEEPS the stage visible: the pill carries REC, the elapsed time and the stop. A live
- // stream does not — its reality line takes over (see RunningVisible).
- public bool ShowOutputStage => IsOutputWorld && !IsLive;
+ // ─── Each activity's own flow ───
+ // Build: nothing to start. YouTube: Live or Private, then Stop. Record: Start, then Stop.
- // ─── The output stage's three states (creator, builds 728/729) ───
- // 1. nothing chosen: [YouTube] [Local MP4]
- // 2. YouTube chosen: [YouTube(red)] [Live Stream] [Private Stream] (Private = the test run)
- // 3. Local MP4 chosen: [Local MP4(red)] [Start Recording] -> [End Recording] while recording
- public bool ShowOutputChoice => ShowOutputStage && !RecordPillOn && !OnAirPillOn;
- public bool ShowYouTubeSelected => ShowOutputStage && OnAirPillOn;
- public bool ShowLocalMp4Selected => ShowOutputStage && RecordPillOn;
- /// The YouTube chip shows while nothing is chosen and while YouTube IS the choice; once
- /// Local MP4 is chosen the MP4 chip replaces it in the left slot (creator, build 729).
- public bool YouTubeChipVisible => ShowOutputChoice || ShowYouTubeSelected;
- public bool LocalMp4ChipVisible => ShowOutputChoice || ShowLocalMp4Selected;
+ // YouTube is two steps ON PURPOSE (creator, 2026-11-13): choosing Live or Private only ARMS it,
+ // because Start is the last moment to tell someone "check you are ready". Collapsing the two would
+ // trade that prompt for one fewer click.
+ private StreamMode _streamMode = StreamMode.None;
- /// The left chip reads "Local MP4" while idle and "REC: hh:mm:ss" while recording, so the
- /// tabular figure cannot jitter the pill's width.
- public string RecordChipText => IsRecording ? $"REC: {LiveElapsedText}" : "Local MP4";
+ public bool IsLiveModeChosen => _streamMode == StreamMode.Live;
+ public bool IsPrivateModeChosen => _streamMode == StreamMode.Private;
- public bool ShowStartRecordingAction => ShowLocalMp4Selected && !IsRecording;
- public bool ShowEndRecordingAction => ShowLocalMp4Selected && IsRecording;
+ public bool ShowYouTubeModeChoices => IsYouTubeActivity && !IsLive && _streamMode == StreamMode.None;
+ public bool ShowYouTubeStart => IsYouTubeActivity && !IsLive && _streamMode != StreamMode.None;
+ public bool ShowYouTubeStop => IsYouTubeActivity && IsLive;
+ public bool ShowRecordStart => IsRecordActivity && !IsRecording;
+ public bool ShowRecordStop => IsRecordActivity && IsRecording;
- public ICommand SelectYouTubeCommand { get; private set; } = null!;
- public ICommand SelectLocalMp4Command { get; private set; } = null!;
- public ICommand StartRecordingCommand { get; private set; } = null!;
- public ICommand TestStreamCommand { get; private set; } = null!;
- public ICommand GoLiveCommand { get; private set; } = null!;
+ /// The Record activity's own words: its name while idle, its action while chosen.
+ public string RecordActionLabel => IsRecording ? "Stop Recording" : "Start Recording";
+ public string RecordElapsedLabel => $"REC: {LiveElapsedText}";
- public ICommand EnterBuildWorldCommand { get; private set; } = null!;
- public ICommand EnterOutputWorldCommand { get; private set; } = null!;
+ public ICommand SelectBuildActivityCommand { get; private set; } = null!;
+ public ICommand SelectYouTubeActivityCommand { get; private set; } = null!;
+ public ICommand SelectRecordActivityCommand { get; private set; } = null!;
+ public ICommand ChooseLiveModeCommand { get; private set; } = null!;
+ public ICommand ChoosePrivateModeCommand { get; private set; } = null!;
+ public ICommand StartChosenStreamCommand { get; private set; } = null!;
- private void InitializeWorldCommands()
+ private void InitializeActivityCommands()
{
- SelectYouTubeCommand = new RelayCommand(_ => OnAirPillOn = true, _ => ShowOutputChoice);
- SelectLocalMp4Command = new RelayCommand(_ => RecordPillOn = true, _ => ShowOutputChoice);
- StartRecordingCommand = new RelayCommand(_ => BeginRecordOnly(), _ => ShowStartRecordingAction);
- // A signed-out press starts the sign-in flow instead of sitting dead (no-dead-ends rule).
- TestStreamCommand = new RelayCommand(_ =>
+ SelectBuildActivityCommand = new RelayCommand(_ => SelectActivity(TopActivity.Build));
+ SelectYouTubeActivityCommand = new RelayCommand(_ => SelectActivity(TopActivity.YouTube));
+ SelectRecordActivityCommand = new RelayCommand(_ => SelectActivity(TopActivity.Record));
+
+ ChooseLiveModeCommand = new RelayCommand(_ => SetStreamMode(StreamMode.Live), _ => ShowYouTubeModeChoices);
+ ChoosePrivateModeCommand = new RelayCommand(_ => SetStreamMode(StreamMode.Private), _ => ShowYouTubeModeChoices);
+
+ // Start is its own press: the last chance to say "you're about to be live".
+ // Signed out still routes to sign-in rather than sitting dead (no-dead-ends rule).
+ StartChosenStreamCommand = new RelayCommand(_ =>
{
if (!IsConnected) { _ = SignInAsync(); return; }
- BeginTestStream();
- }, _ => ShowYouTubeSelected);
- GoLiveCommand = new RelayCommand(_ =>
- {
- if (!IsConnected) { _ = SignInAsync(); return; }
- StartSession();
- }, _ => ShowYouTubeSelected);
-
- EnterBuildWorldCommand = new RelayCommand(_ => EnterWorld(BarWorld.Build));
- EnterOutputWorldCommand = new RelayCommand(_ => EnterWorld(BarWorld.Output));
+ if (_streamMode == StreamMode.Private) BeginTestStream();
+ else StartSession();
+ }, _ => ShowYouTubeStart);
}
- /// Everything the output stage shows or hides, in one place so no caller can forget
- /// one of them.
- internal void RaiseOutputStage()
+ /// Switches activity. Build is the only one that edits; the other two take the layers away
+ /// but leave the button lit, so the creator can see where they are and step back.
+ internal void SelectActivity(TopActivity activity)
{
- OnPropertyChanged(nameof(ShowOutputStage));
- OnPropertyChanged(nameof(ShowOutputChoice));
- OnPropertyChanged(nameof(ShowYouTubeSelected));
- OnPropertyChanged(nameof(YouTubeChipVisible));
- OnPropertyChanged(nameof(LocalMp4ChipVisible));
- OnPropertyChanged(nameof(ShowLocalMp4Selected));
- OnPropertyChanged(nameof(ShowStartRecordingAction));
- OnPropertyChanged(nameof(ShowEndRecordingAction));
- OnPropertyChanged(nameof(RecordChipText));
+ _activity = activity;
+ OnPropertyChanged(nameof(Activity));
+ OnPropertyChanged(nameof(IsBuildActivity));
+ OnPropertyChanged(nameof(IsYouTubeActivity));
+ OnPropertyChanged(nameof(IsRecordActivity));
+
+ EditingActive = activity == TopActivity.Build;
+
+ // The underlying outputs follow the activity, so the existing start commands and the
+ // record/live paths agree with what the bar is showing.
+ RecordPillOn = activity == TopActivity.Record;
+ OnAirPillOn = activity == TopActivity.YouTube;
+ _streamMode = StreamMode.None; // the YouTube flow always restarts at the choice
+
+ RaiseActivityStage();
}
- /// Switches worlds. Re-entering the current one still re-asserts its edit state, which is
- /// what lets a creator take EDIT back mid-show by clicking Build Scenes.
- internal void EnterWorld(BarWorld world)
+ private void SetStreamMode(StreamMode mode)
{
- _barWorld = world;
+ _streamMode = mode;
+ OnPropertyChanged(nameof(IsLiveModeChosen));
+ OnPropertyChanged(nameof(IsPrivateModeChosen));
+ RaiseActivityStage();
+ }
- // Entering a world starts with NOTHING chosen inside it (creator, build 729): the output
- // switches are a fresh decision each time, not a remembered one.
- if (world == BarWorld.Output)
- {
- RecordPillOn = false;
- OnAirPillOn = false;
- }
-
- OnPropertyChanged(nameof(BarWorld));
- OnPropertyChanged(nameof(IsBuildWorld));
- OnPropertyChanged(nameof(IsOutputWorld));
- EditingActive = world == BarWorld.Build;
- OnPropertyChanged(nameof(ShowOutputStage));
- RaiseOutputStage();
+ internal void RaiseActivityStage()
+ {
+ OnPropertyChanged(nameof(ShowYouTubeModeChoices));
+ OnPropertyChanged(nameof(ShowYouTubeStart));
+ OnPropertyChanged(nameof(ShowYouTubeStop));
+ OnPropertyChanged(nameof(ShowRecordStart));
+ OnPropertyChanged(nameof(ShowRecordStop));
}
}
diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs
index f53d538..f7a810d 100644
--- a/ViewModels/MainViewModel.cs
+++ b/ViewModels/MainViewModel.cs
@@ -342,7 +342,7 @@ public partial class MainViewModel : ViewModelBase
OpenHotkeyConfigCommand = new RelayCommand(_ => OpenHotkeyConfig());
ChangeAccountCommand = new RelayCommand(_ => _ = ChangeAccountAsync());
LogoutCommand = new RelayCommand(_ => _ = SignOutYouTubeAsync());
- InitializeWorldCommands();
+ InitializeActivityCommands();
_layoutStore = new LayoutStore(LayoutPathOverride ?? DefaultLayoutPath);
_activeLayoutPath = _layoutStore.ActivePath;
@@ -635,10 +635,19 @@ public partial class MainViewModel : ViewModelBase
_shuttingDown = true;
StopStream();
- for (var i = 0; i < 120 && (IsLive || IsRecording); i++) // up to ~6 s
+ for (var i = 0; i < 40 && (IsLive || IsRecording); i++) // ~2 s: long enough for a flush
await Task.Delay(50).ConfigureAwait(true);
- return !IsLive && !IsRecording;
+ if (IsLive || IsRecording)
+ {
+ // The stop could not finish (no pump, a dead encoder, a test harness). A window that cannot
+ // close is a worse failure than a session flag left set, so clear the UI state and go.
+ AppLog.Write("Shutdown: session did not stop in time; closing anyway", AppLogMessageType.Warning);
+ IsRecording = false;
+ StreamStatus = StreamStatus.Offline;
+ }
+
+ return true;
}
public void Shutdown()
diff --git a/ytLive.Tests/TopBarActivityTests.cs b/ytLive.Tests/TopBarActivityTests.cs
new file mode 100644
index 0000000..cad59d9
--- /dev/null
+++ b/ytLive.Tests/TopBarActivityTests.cs
@@ -0,0 +1,80 @@
+using System;
+using System.IO;
+using Xunit;
+using ytLive.ViewModels;
+
+namespace ytLive.Tests;
+
+///
+/// Three activities, always visible (creator, 2026-11-13): build, stream, record. The active one is lit
+/// and runs its own flow in place; the other two stay on the bar and dim, so there is no state where the
+/// creator cannot see where they are or how to step back.
+///
+[Collection("MainViewModelLayoutPath")]
+public class TopBarActivityTests
+{
+ private static MainViewModel NewVm(string db)
+ {
+ MainViewModel.LayoutPathOverride = db;
+ return new MainViewModel();
+ }
+
+ [Fact]
+ public void Three_activities_stay_on_the_bar_and_the_active_one_owns_its_flow()
+ {
+ var db = Path.Combine(Path.GetTempPath(), $"llamacasty-activity-{Guid.NewGuid():N}.db");
+ try
+ {
+ var vm = NewVm(db);
+
+ // Launch: Build is the activity and the only one editing.
+ Assert.Equal(TopActivity.Build, vm.Activity);
+ Assert.True(vm.IsBuildActivity);
+ Assert.True(vm.IsEditMode);
+ Assert.False(vm.IsRecording);
+
+ // Record: its own flow becomes Start, and editing steps aside.
+ vm.SelectRecordActivityCommand.Execute(null);
+ Assert.True(vm.IsRecordActivity);
+ Assert.False(vm.IsEditMode);
+ Assert.True(vm.ShowRecordStart);
+ Assert.False(vm.ShowRecordStop);
+ Assert.Equal("Start Recording", vm.RecordActionLabel);
+
+ // Recording swaps the flow to Stop, and the elapsed label carries REC.
+ vm.IsRecording = true;
+ Assert.False(vm.ShowRecordStart);
+ Assert.True(vm.ShowRecordStop);
+ Assert.Equal("Stop Recording", vm.RecordActionLabel);
+ Assert.StartsWith("REC: ", vm.RecordElapsedLabel);
+ vm.IsRecording = false;
+
+ // YouTube: choosing Live only ARMS it. Start is a second press — the "are you ready?" moment.
+ vm.SelectYouTubeActivityCommand.Execute(null);
+ Assert.True(vm.IsYouTubeActivity);
+ Assert.True(vm.ShowYouTubeModeChoices);
+ Assert.False(vm.ShowYouTubeStart);
+
+ vm.ChooseLiveModeCommand.Execute(null);
+ Assert.True(vm.IsLiveModeChosen);
+ Assert.False(vm.ShowYouTubeModeChoices);
+ Assert.True(vm.ShowYouTubeStart);
+
+ vm.ChoosePrivateModeCommand.Execute(null);
+ Assert.True(vm.IsPrivateModeChosen);
+ Assert.False(vm.IsLiveModeChosen);
+
+ // Back to Build: editing returns, and the YouTube choice is forgotten, not carried.
+ vm.SelectBuildActivityCommand.Execute(null);
+ Assert.True(vm.IsBuildActivity);
+ Assert.True(vm.IsEditMode);
+ Assert.False(vm.ShowYouTubeModeChoices);
+ Assert.False(vm.ShowYouTubeStart);
+ }
+ finally
+ {
+ MainViewModel.LayoutPathOverride = null;
+ try { File.Delete(db); } catch (IOException) { }
+ }
+ }
+}
diff --git a/ytLive.Tests/TopBarModeTests.cs b/ytLive.Tests/TopBarModeTests.cs
index a0e8b5f..d8d04d6 100644
--- a/ytLive.Tests/TopBarModeTests.cs
+++ b/ytLive.Tests/TopBarModeTests.cs
@@ -84,22 +84,21 @@ public sealed class TopBarModeTests
Assert.False(vm.ShowTestButton);
Assert.Equal("Start Recording", vm.PrimaryStartButtonLabel);
- // A local recording STAYS in the output world (build 730): the pill carries REC, the
- // clock and the stop, so the separate reality line stays away — it would be a second set
- // of the same facts.
- vm.EnterOutputWorldCommand.Execute(null);
- vm.RecordPillOn = true;
- vm.OnAirPillOn = false;
+ // A local recording lives in the Record activity (2026-11-13): the bar keeps its three
+ // buttons and the Record one carries REC + the clock + Stop, so the separate reality line
+ // stays away — it would be a second set of the same facts.
+ vm.SelectRecordActivityCommand.Execute(null);
vm.IsRecording = true;
- Assert.True(vm.ShowOutputStage);
+ Assert.True(vm.IsRecordActivity);
+ Assert.True(vm.ShowRecordStop);
Assert.False(vm.RunningVisible);
- Assert.StartsWith("REC: ", vm.RecordChipText);
+ Assert.StartsWith("REC: ", vm.RecordElapsedLabel);
vm.IsRecording = false;
- // A live stream retires the stage instead; the reality line pins the mode.
+ // A live stream is the YouTube activity's flow; the reality line pins the mode.
+ vm.SelectYouTubeActivityCommand.Execute(null);
vm.StreamStatus = StreamStatus.Streaming;
- Assert.True(vm.RunningVisible);
- Assert.False(vm.ShowOutputStage);
+ Assert.True(vm.ShowYouTubeStop);
Assert.Equal("LIVE", vm.RunningText);
Assert.Equal("#ff5451", vm.RunningDotBrush);
vm.IsTestStream = true;
diff --git a/ytLive.Tests/UiShellTests.cs b/ytLive.Tests/UiShellTests.cs
index 7cb4ddd..ff9662f 100644
--- a/ytLive.Tests/UiShellTests.cs
+++ b/ytLive.Tests/UiShellTests.cs
@@ -29,10 +29,11 @@ public class UiShellTests
// 2. The world segment replaced the EDIT toggle (creator ruling 2026-11-12): both halves are
// present, each lit by its own world flag through the shared style.
- Assert.Contains("Text=\"Build scenes\"", topBar);
- Assert.Contains("Text=\"Record / Go-Live\"", topBar);
- Assert.Contains("Tag=\"{Binding IsBuildWorld}\"", topBar);
- Assert.Contains("Tag=\"{Binding IsOutputWorld}\"", topBar);
+ Assert.Contains("Text=\"Build Scenes\"", topBar);
+ Assert.Contains("Text=\"YouTube\"", topBar);
+ Assert.Contains("Text=\"Record\"", topBar);
+ Assert.Contains("Tag=\"{Binding IsBuildActivity}\"", topBar);
+ Assert.Contains("Tag=\"{Binding IsYouTubeActivity}\"", topBar);
Assert.DoesNotContain("x:Name=\"EditBody\"", topBar);
// 2b. The segment is Build-world only: choosing Record / Go Live REPLACES it with the output
@@ -42,18 +43,16 @@ public class UiShellTests
Assert.Contains("Brush.SegmentTrack", topBar);
Assert.Contains("Style=\"{StaticResource SegmentHalf}\"", topBar);
Assert.Contains("Style=\"{StaticResource SegmentIcon}\"", topBar);
- Assert.Contains("Visibility=\"{Binding IsBuildWorld, Converter={StaticResource BoolToVis}}\"", topBar);
- Assert.Contains("Text=\"Output:\"", topBar);
- Assert.Contains("Text=\"<esc> to return\"", topBar);
+
+
+
Assert.DoesNotContain("ToolTip=\"Back to Build Scenes\"", topBar); // Esc replaced the chevron
// 2c. The output stage: two labelled switches and the exclusivity promise beside them.
- Assert.Contains("Text=\"Output:\"", topBar);
+
Assert.Contains("Text=\"YouTube\"", topBar);
- Assert.Contains("Text=\"Local MP4\"", topBar);
- Assert.Contains("Text=\"One output at a time\"", topBar);
- Assert.Contains("Command=\"{Binding SelectYouTubeCommand}\"", topBar);
- Assert.Contains("Command=\"{Binding SelectLocalMp4Command}\"", topBar);
+ Assert.Contains("Command=\"{Binding SelectYouTubeActivityCommand}\"", topBar);
+ Assert.Contains("Command=\"{Binding SelectRecordActivityCommand}\"", topBar);
// 2d. The bar carries NO action button: the output line is the bar's whole middle
// (creator ruling 2026-11-12 — the action is placed elsewhere, on instruction).
@@ -120,9 +119,9 @@ public class UiShellTests
// The world segment leads the centre cluster; the brand column carries no edit control.
var centre = topBar.IndexOf(" 0 && segment > centre,
- "the [ Build Scenes ][ Record / Go Live ] segment must lead the centre cluster");
+ "the three-activity segment must lead the centre cluster");
Assert.DoesNotContain("x:Name=\"EditBody\"", topBar);
}