Files
LlamaCasty/Themes/Controls.xaml
T
gramps a6aea5bf26 feat(ui): color and acknowledge pinned log errors
Add independent AppLog message types and explicit Class 1/2 severity. Wrap and color log rows, pin Class 1 above Class 2, and let acknowledgement return entries to the current-launch timeline without changing file format or rotation.

Ref: https://logtape.org/manual/levels
2026-11-02 18:17:18 -08:00

968 lines
54 KiB
XML

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Helpers="clr-namespace:ytLive.Helpers">
<!-- Typography for every window: dialogs are separate WPF windows, so FontFamily set on
MainWindow does not reach them. This implicit style is the one place that does — a
dialog inherits Inter without setting anything, and the design standard holds for every
surface the creator can open. -->
<Style TargetType="Window">
<Setter Property="FontFamily" Value="{StaticResource FontFamily.Sans}"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
<Setter Property="UseLayoutRounding" Value="True"/>
</Style>
<!-- Base button style -->
<Style x:Key="YtButton" TargetType="Button">
<Setter Property="Background" Value="{StaticResource Brush.Tertiary}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Padding" Value="16,8"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="{StaticResource Radius.Sm}"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<Border x:Name="Glow" Background="White" CornerRadius="{StaticResource Radius.Sm}" Opacity="0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Glow" Property="Opacity" Value="0.08"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Glow" Property="Opacity" Value="0.16"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.45"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="YtButtonSecondary" TargetType="Button" BasedOn="{StaticResource YtButton}">
<Setter Property="Background" Value="{StaticResource Brush.SurfaceContainer}"/>
</Style>
<Style x:Key="IconButton" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="4"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="3"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource Brush.ScrimStrong}"/>
</Trigger>
</Style.Triggers>
</Style>
<!-- Eye icon: open when visible, slashed when hidden (source rows). App scope for
the same LeftPanel reason as EyeButton below. -->
<Style x:Key="EyeIconStyle" TargetType="Path">
<Setter Property="Data" Value="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsVisible}" Value="False">
<Setter Property="Data" Value="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
</DataTrigger>
</Style.Triggers>
</Style>
<!-- Lives here (app scope), NOT in a window: Controls/LeftPanel.xaml references it
via StaticResource, and a UserControl cannot see window resources at parse
time (startup crash caught 2026-09-01). -->
<Style x:Key="EyeButton" TargetType="Button" BasedOn="{StaticResource IconButton}">
<Setter Property="ToolTip" Value="Hide Layer"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsVisible}" Value="False">
<Setter Property="ToolTip" Value="Show Layer"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="YtTextBox" TargetType="TextBox">
<Setter Property="Background" Value="{StaticResource Brush.SurfaceContainerHigh}"/>
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="BorderBrush" Value="{StaticResource Brush.Outline}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="CaretBrush" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{StaticResource Radius.Sm}" Padding="{TemplateBinding Padding}">
<ScrollViewer x:Name="PART_ContentHost" Margin="0"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Brush.SurfaceBright}"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Brush.Tertiary}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Bd" Property="Opacity" Value="0.45"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Dense variant of YtTextBox for the properties panel (11px labels, tight
padding). Same template + colours as YtTextBox — only the metrics differ,
so the panel keeps its rhythm without hand-painting every field. -->
<Style x:Key="YtTextBoxCompact" TargetType="TextBox" BasedOn="{StaticResource YtTextBox}">
<Setter Property="FontSize" Value="11"/>
<Setter Property="Padding" Value="4,2"/>
<Setter Property="MinHeight" Value="22"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<!-- Dark check box. The default WPF template is the light system one — it
sticks out of the dark panels, so every check box carries this style
(the guard test in ytLive.Tests/PropertiesStyleTests.cs enforces it). -->
<!-- ═══ Property-panel typography (2026-11-01) ═══
One hierarchy for every properties section, so no panel invents its own:
PropertyHeader — the heading of a group (bright, 11px, semibold)
PropertyFieldLabel — the label in a row with its control (dim, 10px, semibold)
PropertyHint — the explanatory sentence under a control (dim, 10px, wrapped)
ONE heading rank: a group is never sometimes a header and sometimes a sub-header, which
is what put Ticker out of step with Geometry (creator ruling, 2026-11-01).
Colour does the grouping: bright for the thing you are editing, dim for its labels and
help. No new palette entries; these are the existing OnSurface / OnSurfaceVariant tokens. -->
<Style x:Key="PropertyHeader" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Margin" Value="0,0,0,6"/>
</Style>
<!-- A field label that sits in a row with its control (DockPanel.Dock="Left", fixed Width),
or a value readout beside a slider. Vertically centred and marginless so the rows stay on
a grid. -->
<Style x:Key="PropertyFieldLabel" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceVariant}"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="PropertyHint" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceDisabled}"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Margin" Value="10,0,0,6"/>
</Style>
<Style x:Key="AppLogEntryText" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceVariant}"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="{x:Static Helpers:AppLogMessageType.Success}">
<Setter Property="Foreground" Value="{StaticResource Brush.Positive}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Type}" Value="{x:Static Helpers:AppLogMessageType.Warning}">
<Setter Property="Foreground" Value="{StaticResource Brush.Secondary}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Type}" Value="{x:Static Helpers:AppLogMessageType.Error}">
<Setter Property="Foreground" Value="{StaticResource Brush.Error}"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Type}" Value="{x:Static Helpers:AppLogMessageType.Error}"/>
<Condition Binding="{Binding ErrorClass}" Value="{x:Static Helpers:AppLogErrorClass.Class2}"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="{StaticResource Brush.Attention}"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
<!-- A property-panel action: bordered, quiet, 11px normal weight. The accent-filled YtButton
(white semi-bold 13px) made secondary actions like "Reset to built-in" the loudest text in
the panel, which is backwards. -->
<Style x:Key="PropertyButton" TargetType="Button">
<Setter Property="Background" Value="{StaticResource Brush.SurfaceContainerHigh}"/>
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Padding" Value="8,3"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
BorderBrush="{StaticResource Brush.Outline}" BorderThickness="1"
CornerRadius="{StaticResource Radius.Sm}"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Brush.SurfaceContainerHighest}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceDisabled}"/>
<Setter TargetName="Bd" Property="Opacity" Value="0.6"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Hairline between groups inside one properties category. -->
<Style x:Key="PropertyDivider" TargetType="Border">
<Setter Property="Height" Value="1"/>
<Setter Property="Background" Value="{StaticResource Brush.OutlineVariant}"/>
<Setter Property="Margin" Value="0,10,0,8"/>
</Style>
<!-- Checkboxes are pill switches (creator ruling 2026-11-01): a 14px box in a properties panel
reads as a form, and a switch reads as a setting. IsChecked semantics are untouched, so
every existing binding still works. -->
<Style x:Key="PropertyPillCheck" TargetType="CheckBox">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Track" Grid.Column="0" Width="32" Height="16" CornerRadius="8"
Background="{StaticResource Brush.SurfaceContainerHighest}"
BorderBrush="{StaticResource Brush.Outline}" BorderThickness="1"
VerticalAlignment="Center">
<Ellipse x:Name="Thumb" Width="10" Height="10" Fill="{StaticResource Brush.OnSurfaceVariant}"
HorizontalAlignment="Left" Margin="2,0,0,0">
<Ellipse.RenderTransform>
<TranslateTransform x:Name="ThumbShift" X="0"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
<ContentPresenter Grid.Column="1" Margin="8,0,0,0" VerticalAlignment="Center"
RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Track" Property="Background" Value="{StaticResource Brush.Tertiary}"/>
<Setter TargetName="Track" Property="BorderBrush" Value="{StaticResource Brush.Tertiary}"/>
<!-- 0.6 keeps the state readable without the neon fill the review flagged. -->
<Setter TargetName="Track" Property="Opacity" Value="0.6"/>
<Setter TargetName="Thumb" Property="Fill" Value="{StaticResource Brush.OnAccent}"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ThumbShift" Storyboard.TargetProperty="X"
To="16" Duration="0:0:0.12"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ThumbShift" Storyboard.TargetProperty="X"
To="0" Duration="0:0:0.12"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<!-- Legible-but-dim, not invisible: the label stays readable and the
track drops back so "disabled" reads as a state, not as a bug. -->
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceVariant}"/>
<Setter Property="Opacity" Value="0.55"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="YtCheckBox" TargetType="CheckBox">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Box" Grid.Column="0" Width="14" Height="14" CornerRadius="3"
Background="{StaticResource Brush.SurfaceContainerHigh}" BorderBrush="{StaticResource Brush.Outline}" BorderThickness="1"
VerticalAlignment="Center">
<Path x:Name="Tick" Data="M2.5,7.2 L5.8,10.5 L11.5,3.8"
Stroke="#ffffff" StrokeThickness="2"
StrokeStartLineCap="Round" StrokeEndLineCap="Round"
Visibility="Collapsed"/>
</Border>
<ContentPresenter Grid.Column="1" Margin="7,0,0,0" VerticalAlignment="Center"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Box" Property="BorderBrush" Value="{StaticResource Brush.SurfaceBright}"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="Box" Property="BorderBrush" Value="{StaticResource Brush.Tertiary}"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Box" Property="Background" Value="{StaticResource Brush.Tertiary}"/>
<Setter TargetName="Box" Property="BorderBrush" Value="{StaticResource Brush.Tertiary}"/>
<Setter TargetName="Tick" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.45"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="YtComboBoxItem" TargetType="ComboBoxItem">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Padding" Value="10,7"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="3" Margin="0,1" Padding="{TemplateBinding Padding}">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Brush.ScrimStrong}"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Brush.SurfaceContainerHighest}"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="YtQualityComboBoxItem" TargetType="ComboBoxItem" BasedOn="{StaticResource YtComboBoxItem}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RequiresPro}" Value="True"/>
<Condition Binding="{Binding DataContext.HasProOutput, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceDisabled}"/>
<Setter Property="Opacity" Value="0.55"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="YtComboBox" TargetType="ComboBox">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Background" Value="{StaticResource Brush.SurfaceContainerHigh}"/>
<Setter Property="BorderBrush" Value="{StaticResource Brush.Outline}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="MinHeight" Value="30"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource YtComboBoxItem}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<Border x:Name="Chrome" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{StaticResource Radius.Sm}"/>
<ContentPresenter x:Name="ContentSite" IsHitTestVisible="False"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
<ToggleButton x:Name="ToggleButton" Focusable="False" ClickMode="Press"
Background="Transparent" BorderThickness="0"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Grid Background="Transparent">
<Path x:Name="Chevron" Data="M0,0 L4,4 L8,0" Stroke="{StaticResource Brush.OnSurfaceVariant}"
StrokeThickness="1.5" HorizontalAlignment="Right"
VerticalAlignment="Center" Margin="0,0,10,0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Chevron" Property="Stroke" Value="{StaticResource Brush.OnSurface}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.45"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
<Popup x:Name="PART_Popup" Placement="Bottom" AllowsTransparency="True"
PopupAnimation="Fade" StaysOpen="False"
IsOpen="{TemplateBinding IsDropDownOpen}">
<Border Background="{StaticResource Brush.SurfaceContainer}" BorderBrush="{StaticResource Brush.Outline}" BorderThickness="1"
CornerRadius="5" Padding="2" Margin="0,4,0,0"
SnapsToDevicePixels="True">
<ScrollViewer MaxHeight="{TemplateBinding MaxDropDownHeight}"
ScrollViewer.CanContentScroll="True">
<ItemsPresenter/>
</ScrollViewer>
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Chrome" Property="Background" Value="{StaticResource Brush.SurfaceContainerHighest}"/>
</Trigger>
<Trigger Property="IsDropDownOpen" Value="True">
<Setter TargetName="Chrome" Property="Background" Value="{StaticResource Brush.SurfaceContainerHighest}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Chrome" Property="Opacity" Value="0.45"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Thin dark scrollbar -->
<Style x:Key="YtScrollBarPageButton" TargetType="RepeatButton">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Grid Background="Transparent"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="YtScrollBarThumb" TargetType="Thumb">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Border x:Name="ThumbBd" Background="{StaticResource Brush.SurfaceBright}" CornerRadius="{StaticResource Radius.Sm}" Margin="2"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ThumbBd" Property="Background" Value="{StaticResource Brush.SurfaceBright}"/>
</Trigger>
<Trigger Property="IsDragging" Value="True">
<Setter TargetName="ThumbBd" Property="Background" Value="{StaticResource Brush.SurfaceBright}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ScrollBar">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Width" Value="10"/>
<Setter Property="MinWidth" Value="10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid Background="Transparent">
<Track x:Name="PART_Track" IsDirectionReversed="True">
<Track.DecreaseRepeatButton>
<RepeatButton Command="{x:Static ScrollBar.PageUpCommand}"
Style="{StaticResource YtScrollBarPageButton}"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Command="{x:Static ScrollBar.PageDownCommand}"
Style="{StaticResource YtScrollBarPageButton}"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource YtScrollBarThumb}"/>
</Track.Thumb>
</Track>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="10"/>
<Setter Property="MinHeight" Value="10"/>
</Trigger>
</Style.Triggers>
</Style>
<!-- Slider: slim track, solid interactive fill. Blue is the only interactive accent
(DESIGN.md); the pre-standard green fill is gone. -->
<RadialGradientBrush x:Key="YtSliderKnobBrush" Center="0.35,0.3" GradientOrigin="0.35,0.3">
<GradientStop Color="#ffffff" Offset="0"/>
<GradientStop Color="{StaticResource Color.Tertiary}" Offset="1"/>
</RadialGradientBrush>
<!-- Hover/drag knob: the same gloss with the highlight spread wider. The conversion to
tokens deleted this key while two triggers still referenced it, and WPF turns a missing
StaticResource into DependencyProperty.UnsetValue — which crashes Ellipse.OnRender at
the next layout. ThemeResourceTests now catches that class of defect. -->
<RadialGradientBrush x:Key="YtSliderKnobHoverBrush" Center="0.35,0.3" GradientOrigin="0.35,0.3">
<GradientStop Color="#ffffff" Offset="0"/>
<GradientStop Color="#ffffff" Offset="0.3"/>
<GradientStop Color="{StaticResource Color.Tertiary}" Offset="1"/>
</RadialGradientBrush>
<Style x:Key="YtSliderTrackButton" TargetType="RepeatButton">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Border Background="{x:Null}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="YtSliderFillButton" TargetType="RepeatButton">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Grid>
<Border Height="5" VerticalAlignment="Center"
Background="{StaticResource Brush.Tertiary}"
BorderThickness="1" CornerRadius="2.5"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="YtSliderThumb" TargetType="Thumb">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Grid Width="13" Height="13">
<Ellipse x:Name="Knob" Fill="{StaticResource YtSliderKnobBrush}"
Stroke="{StaticResource Brush.Background}" StrokeThickness="1">
<Ellipse.Effect>
<DropShadowEffect BlurRadius="3" ShadowDepth="1" Opacity="0.55"/>
</Ellipse.Effect>
</Ellipse>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Knob" Property="Fill" Value="{StaticResource YtSliderKnobHoverBrush}"/>
</Trigger>
<Trigger Property="IsDragging" Value="True">
<Setter TargetName="Knob" Property="Fill" Value="{StaticResource YtSliderKnobHoverBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Slider">
<Setter Property="Height" Value="20"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="IsMoveToPointEnabled" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Grid VerticalAlignment="Center">
<Border Height="5" CornerRadius="2.5" VerticalAlignment="Center"
Background="{StaticResource Brush.SurfaceContainerLowest}"
BorderBrush="{StaticResource Brush.Background}" BorderThickness="1"/>
<Track x:Name="PART_Track" Height="18">
<Track.DecreaseRepeatButton>
<RepeatButton Command="{x:Static Slider.DecreaseLarge}"
Style="{StaticResource YtSliderFillButton}"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Command="{x:Static Slider.IncreaseLarge}"
Style="{StaticResource YtSliderTrackButton}"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource YtSliderThumb}"/>
</Track.Thumb>
</Track>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Dark tooltip -->
<Style TargetType="ToolTip">
<Setter Property="Background" Value="{StaticResource Brush.SurfaceContainerLow}"/>
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="BorderBrush" Value="{StaticResource Brush.Outline}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{StaticResource Radius.Sm}" Padding="{TemplateBinding Padding}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}" TextWrapping="Wrap" MaxWidth="320"
Foreground="{StaticResource Brush.OnSurface}" FontSize="12"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Dark context menu -->
<Style TargetType="ContextMenu">
<Setter Property="Background" Value="{StaticResource Brush.SurfaceContainer}"/>
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="BorderBrush" Value="{StaticResource Brush.Outline}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContextMenu">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5" Padding="{TemplateBinding Padding}">
<Grid IsSharedSizeScope="True">
<ItemsPresenter/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="MenuItem">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="10,6"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuItem">
<Grid x:Name="Grid" SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Col0" MinWidth="17" Width="Auto"
SharedSizeGroup="MenuItemIconColumnGroup"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="14"/>
</Grid.ColumnDefinitions>
<Border x:Name="Bd" Grid.ColumnSpan="3"
Background="{TemplateBinding Background}"
CornerRadius="3" Margin="0,1"/>
<TextBlock x:Name="CheckGlyph" Grid.Column="0" Text="&#x2713;"
Margin="4,0,6,0" HorizontalAlignment="Center"
VerticalAlignment="Center" Visibility="Collapsed"/>
<ContentPresenter x:Name="Content" Grid.Column="1"
ContentSource="Header"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
<TextBlock x:Name="Arrow" Grid.Column="2" Text="&#x203A;"
Margin="6,0,0,0" HorizontalAlignment="Center"
VerticalAlignment="Center" Visibility="Collapsed"/>
<Popup x:Name="PART_Popup" Placement="Right"
HorizontalOffset="-1" VerticalOffset="-1"
IsOpen="{TemplateBinding IsSubmenuOpen}"
AllowsTransparency="True"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"
Focusable="False">
<Border Background="{StaticResource Brush.SurfaceContainer}" BorderBrush="{StaticResource Brush.Outline}"
BorderThickness="1" CornerRadius="5" Padding="3">
<Grid IsSharedSizeScope="True">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsPresenter/>
</ScrollViewer>
</Grid>
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Brush.ScrimStrong}"/>
</Trigger>
<Trigger Property="IsSubmenuOpen" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Brush.ScrimStrong}"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="CheckGlyph" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.45"/>
</Trigger>
<DataTrigger Binding="{Binding HasItems, RelativeSource={RelativeSource TemplatedParent}}"
Value="True">
<Setter TargetName="Arrow" Property="Visibility" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Menu separators render as standalone Separator controls -->
<Style TargetType="Separator">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Separator">
<Border Height="1" Background="{StaticResource Brush.Outline}" Margin="8,4"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Dark list item (used by all list boxes) -->
<Style x:Key="YtListBoxItem" TargetType="ListBoxItem">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="Padding" Value="4,2"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Border x:Name="Accent" Width="3" HorizontalAlignment="Left" CornerRadius="1"
Background="{StaticResource Brush.Tertiary}" Margin="0,2" Opacity="0"
VerticalAlignment="Stretch"/>
<Border x:Name="Bd" Background="{TemplateBinding Background}"
CornerRadius="3" Padding="{TemplateBinding Padding}" Margin="0,1">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Brush.ScrimSoft}"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{StaticResource Brush.SurfaceContainerHighest}"/>
<Setter TargetName="Accent" Property="Opacity" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="YtLabel" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceVariant}"/>
<Setter Property="FontSize" Value="12"/>
</Style>
<Style x:Key="SectionHeader" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurface}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Margin" Value="0,0,0,8"/>
</Style>
<Style x:Key="SubHeader" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceVariant}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Margin" Value="4,0,0,4"/>
</Style>
<!-- Top-bar status sign label (REC / ON-AIR): one definition so the two signs can't drift -->
<Style x:Key="StatusSignText" TargetType="TextBlock">
<Setter Property="Foreground" Value="{Binding RecTextBrush}"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="8,0,0,0"/>
</Style>
<!-- Sliding pill toggle: OFF = neutral, ON = blue. Red is reserved for live/record
(DESIGN.md), so a settings toggle can never use it. -->
<Style x:Key="PillToggle" TargetType="ToggleButton">
<Setter Property="Width" Value="36"/>
<Setter Property="Height" Value="18"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Background" Value="{StaticResource Brush.SurfaceContainerHighest}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Border x:Name="Track" Background="{TemplateBinding Background}"
CornerRadius="9" SnapsToDevicePixels="True">
<Ellipse x:Name="Thumb" Width="12" Height="12" Fill="White"
HorizontalAlignment="Left" Margin="3,0,0,0">
<Ellipse.Effect>
<DropShadowEffect BlurRadius="3" ShadowDepth="1" Opacity="0.35"/>
</Ellipse.Effect>
<Ellipse.RenderTransform>
<TranslateTransform x:Name="ThumbTransform" X="0"/>
</Ellipse.RenderTransform>
</Ellipse>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Track" Property="Background" Value="{StaticResource Brush.Tertiary}"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ThumbTransform"
Storyboard.TargetProperty="X"
To="18" Duration="0:0:0.15">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ThumbTransform"
Storyboard.TargetProperty="X"
To="0" Duration="0:0:0.15">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Top-bar mode switch segments (top bar redesign): one two-position REC/ON-AIR
switch replaces the old pill pair — one binary decision, one world rendered.
The selected segment fills app-red and its label goes white. -->
<Style x:Key="SegmentToggle" TargetType="ToggleButton">
<Setter Property="Padding" Value="14,5"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="Seg" Background="Transparent" CornerRadius="3"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Seg" Property="Background" Value="{StaticResource Brush.Tertiary}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SegmentLabel" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource Brush.OnSurfaceVariant}"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource AncestorType=ToggleButton}}"
Value="True">
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
<!-- REC / ON-AIR segment pills: an armed session control reads red, because red is what
"live or recording" means (DESIGN.md). Kept separate from SegmentToggle so the Rect|Circle
choice in the properties panel stays the interactive blue. -->
<Style x:Key="RecordPillToggle" TargetType="ToggleButton" BasedOn="{StaticResource SegmentToggle}">
<!-- SegmentToggle's template hard-codes a Transparent face and paints the checked state
itself, so an armed pill needs its own template that honours Background. -->
<Setter Property="Background" Value="Transparent"/>
<!-- The label inherits this: without it the bare Control default (black) paints on the
dark bar and the pill looks empty. Session controls carry WHITE ink in every state;
the fill is what changes. -->
<Setter Property="Foreground" Value="{StaticResource Brush.OnAccent}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="Seg" Background="{TemplateBinding Background}" CornerRadius="3"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="{StaticResource Brush.Primary}"/>
</Trigger>
</Style.Triggers>
</Style>
<!-- Value-to-visibility converters, promoted from MainWindow.Window.Resources
so extracted UserControls can resolve them (AGENTS: controls must not
reach into a window's own resources; they share the app-level theme). -->
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
<Helpers:InverseBoolToVisibilityConverter x:Key="InverseBoolToVis"/>
<Helpers:NotNullToVisibilityConverter x:Key="NotNullToVis"/>
<Helpers:NullToVisibilityConverter x:Key="NullToVis"/>
<Helpers:HiddenBoolToVisibilityConverter x:Key="HiddenBoolToVis"/>
<Helpers:EnumToBoolConverter x:Key="EnumToBool"/>
<Helpers:AllTrueToVisibilityConverter x:Key="AllTrueToVis"/>
<Helpers:HexToBrushConverter x:Key="HexToBrush"/>
</ResourceDictionary>