private/theme/Update-SingleControlTheme.ps1

function Update-SingleControlTheme {
    <#
    .SYNOPSIS
        Applies theme styling to a single control based on its type.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        $Control,
        [Parameter(Mandatory)]
        [hashtable]$Colors
    )

    # Window styling
    if ($Control -is [System.Windows.Window]) {
        Write-Debug "Updating Window with accent: $($Colors.Accent)"

        # Update window title bar color via DWM (only for native chrome windows)
        if ([PsUi.ModuleContext]::IsInitialized -and $Control.WindowStyle -ne 'None') {
            $headerBg = [System.Windows.Media.ColorConverter]::ConvertFromString($Colors.HeaderBackground)
            $headerFg = [System.Windows.Media.ColorConverter]::ConvertFromString($Colors.HeaderForeground)
            [PsUi.WindowManager]::SetTitleBarColor($Control, $headerBg, $headerFg)
        }

        # Skip background for transparent/borderless windows (custom chrome needs transparent background)
        if (!$Control.AllowsTransparency) {
            $Control.Background = ConvertTo-UiBrush $Colors.WindowBg
        }
        $Control.Foreground = ConvertTo-UiBrush $Colors.WindowFg

        # Regenerate window icon with new theme colors (unless custom logo is set)
        $session = Get-UiSession
        if ($session -and $session.CustomLogo -and (Test-Path $session.CustomLogo)) {
            # Custom logo is set - load it instead of regenerating themed icon
            $newIcon = Get-CustomLogoIcon -Path $session.CustomLogo
        }
        else {
            $newIcon = New-WindowIcon -Colors $Colors
        }
        if ($newIcon) {
            Write-Debug "New icon created, setting on window"
            $Control.Icon = $newIcon
            [PsUi.WindowManager]::SetTaskbarIcon($Control, $newIcon)
            
            # Update titlebar icon for custom chrome windows (Tag is a hashtable)
            $chromeInfo = $Control.Tag
            if ($chromeInfo -is [System.Collections.IDictionary] -and $chromeInfo['TitleBarIcon']) {
                $chromeInfo['TitleBarIcon'].Source = $newIcon
            }
        }

        # Update taskbar overlay if present (e.g. TextEditor document icon)
        if ($Control.Resources.Contains('OverlayGlyph')) {
            try {
                $glyph       = $Control.Resources['OverlayGlyph']
                $overlayIcon = New-TaskbarOverlayIcon -GlyphChar $glyph -Color $Colors.Accent
                if ($overlayIcon) {
                    [PsUi.WindowManager]::SetTaskbarOverlay($Control, $overlayIcon, 'Overlay')
                }
            }
            catch {
                Write-Verbose "Failed to update taskbar overlay: $_"
            }
        }
    }
    elseif ($Control -is [System.Windows.Controls.GroupBox]) {
        Set-GroupBoxStyle -GroupBox $Control
    }
    elseif ($Control -is [System.Windows.Controls.Button]) {
        # Inline button theme update logic (was Update-ButtonTheme)
        $isAccent = $false
        if ($Control.Tag -is [System.Collections.IDictionary] -and $Control.Tag['IsAccent']) {
            $isAccent = $true
        }

        # Apply base button style
        Set-ButtonStyle -Button $Control -Accent:$isAccent

        # Update button icon color (non-accent buttons use accent color for icon)
        if (!$isAccent -and $Control.Content -is [System.Windows.Controls.StackPanel]) {
            foreach ($child in $Control.Content.Children) {
                if ($child -is [System.Windows.Controls.TextBlock] -and $child.FontFamily.Source -eq 'Segoe MDL2 Assets') {
                    $child.Foreground = ConvertTo-UiBrush $Colors.Accent
                }
            }
        }

        # Update checkmark for theme menu buttons
        if ($Control.Tag -is [System.Collections.IDictionary] -and $Control.Tag.ContainsKey('ThemeName')) {
            if ($Control.Tag.ContainsKey('Checkmark') -and $Control.Tag['Checkmark']) {
                $isActive = $Control.Tag['ThemeName'] -eq [PsUi.ModuleContext]::ActiveTheme
                $Control.Tag['Checkmark'].Text = if ($isActive) { [char]0x2713 } else { ' ' }
                if ($isActive) { $Control.Tag['Checkmark'].Foreground = ConvertTo-UiBrush $Colors.Accent }
            }
        }

        # Style popup contents if button has a popup tag
        if ($Control.Tag -is [System.Windows.Controls.Primitives.Popup]) {
            $popup       = $Control.Tag
            $popupBorder = $popup.Child
            if ($popupBorder -is [System.Windows.Controls.Border]) {
                $popupBorder.Background  = ConvertTo-UiBrush $Colors.ControlBg
                $popupBorder.BorderBrush = ConvertTo-UiBrush $Colors.Border
            }
        }
    }
    elseif ($Control -is [System.Windows.Controls.TextBox]) {
        Set-TextBoxStyle -TextBox $Control
    }
    elseif ($Control -is [System.Windows.Controls.DataGrid]) {
        Set-DataGridStyle -Grid $Control
    }
    elseif ($Control -is [System.Windows.Controls.TabControl]) {
        Set-TabControlStyle -TabControl $Control
        $Control.Foreground = ConvertTo-UiBrush $Colors.ControlFg
    }
    elseif ($Control -is [System.Windows.Controls.TabItem]) {
        Set-TabItemStyle -TabItem $Control
    }
    elseif ($Control -is [System.Windows.Controls.ComboBox]) {
        Set-ComboBoxStyle -ComboBox $Control
    }
    elseif ($Control -is [System.Windows.Controls.RadioButton]) {
        # Wrap in try/catch - internal template RadioButtons may fail
        try { Set-RadioButtonStyle -RadioButton $Control }
        catch { Write-Debug "RadioButton style skipped: $_" }
    }
    elseif ($Control -is [System.Windows.Controls.ListBox]) {
        Set-ListBoxStyle -ListBox $Control
    }
    elseif ($Control -is [System.Windows.Controls.DatePicker]) {
        Set-DatePickerStyle -DatePicker $Control
    }
    elseif ($Control -is [System.Windows.Controls.TextBlock]) {
        # Inline TextBlock theme update logic (was Update-TextBlockTheme)
        switch ($Control.Tag) {
            'AccentBrush'               { $Control.Foreground = ConvertTo-UiBrush $Colors.Accent }
            'AccentHeaderForegroundBrush' { $Control.Foreground = ConvertTo-UiBrush $Colors.AccentHeaderFg }
            'ControlFgBrush'            { $Control.Foreground = ConvertTo-UiBrush $Colors.ControlFg }
            'SecondaryTextBrush'        { $Control.Foreground = ConvertTo-UiBrush $Colors.SecondaryText }
            'SuccessBrush'              { $Control.Foreground = ConvertTo-UiBrush $Colors.Success }
            'ErrorBrush'                { $Control.Foreground = ConvertTo-UiBrush $Colors.Error }
            'AccentText'                { $Control.Foreground = ConvertTo-UiBrush $Colors.Accent }
            'AccentButtonIcon'          { $Control.Foreground = ConvertTo-UiBrush $Colors.AccentHeaderFg }
            'AccentButtonText'          { $Control.Foreground = ConvertTo-UiBrush $Colors.AccentHeaderFg }
            'ThemeButtonIcon'           { $Control.Foreground = ConvertTo-UiBrush $Colors.HeaderForeground }
            'HeaderText'                { $Control.Foreground = ConvertTo-UiBrush $Colors.HeaderForeground }
            { $_ -in @('TimePickerLabel', 'TimePickerText', 'TimePickerArrowIcon', 'TimePickerColon') } {
                $Control.Foreground = ConvertTo-UiBrush $Colors.ControlFg
            }
            { $_ -in @('CardHeaderIcon', 'CardHeaderText') } {
                # Card header text/icon - look at parent for accent info
                $parent = [System.Windows.Media.VisualTreeHelper]::GetParent($Control)
                while ($parent -and !($parent.Tag -is [System.Collections.IDictionary])) {
                    $parent = [System.Windows.Media.VisualTreeHelper]::GetParent($parent)
                }
                if ($parent -and $parent.Tag -is [System.Collections.IDictionary] -and $parent.Tag['IsAccent']) {
                    $bgColor = if ($parent.Tag['CustomColor']) { $parent.Tag['CustomColor'] } else { $Colors.Accent }
                    $Control.Foreground = ConvertTo-UiBrush (Get-ContrastColor -HexColor $bgColor)
                }
                else {
                    $Control.Foreground = ConvertTo-UiBrush $Colors.ControlFg
                }
            }
            default {
                # Regular text (not an icon font)
                if ($Control.FontFamily.Source -ne 'Segoe MDL2 Assets') {
                    $Control.Foreground = ConvertTo-UiBrush $Colors.ControlFg
                }
            }
        }
    }
    elseif ($Control -is [System.Windows.Controls.Border]) {
        # Inline Border theme update logic (was Update-BorderTheme)
        switch ($Control.Tag) {
            'HeaderBorder' {
                $Control.Background = ConvertTo-UiBrush $Colors.HeaderBackground
            }
            'StatusBar' {
                $Control.Background  = ConvertTo-UiBrush $Colors.ControlBg
                $Control.BorderBrush = ConvertTo-UiBrush $Colors.Border
            }
            'PopupBorder' {
                $Control.Background  = ConvertTo-UiBrush $Colors.ControlBg
                $Control.BorderBrush = ConvertTo-UiBrush $Colors.Border
            }
            'CardBorder' {
                $Control.Background  = ConvertTo-UiBrush $Colors.ControlBg
                $Control.BorderBrush = ConvertTo-UiBrush $Colors.Border
            }
            'CardSeparator' {
                $Control.Background = ConvertTo-UiBrush $Colors.Border
            }
            'ConsoleGutter' {
                $Control.Background  = ConvertTo-UiBrush $Colors.WindowBg
                $Control.BorderBrush = ConvertTo-UiBrush $Colors.Border
            }
            { $_ -in @('TimePickerBorder', 'TimePickerArrowBorder', 'TimePickerPopupBorder') } {
                $Control.Background  = ConvertTo-UiBrush $Colors.ControlBg
                $Control.BorderBrush = ConvertTo-UiBrush $Colors.Border
            }
            'TimePickerSeparator' {
                $Control.Background = ConvertTo-UiBrush $Colors.Border
            }
            'Separator_Solid' {
                $Control.Background = ConvertTo-UiBrush $Colors.Border
            }
            'Separator_Fade' {
                # Recreate fade gradient with new border color
                $borderColor       = [System.Windows.Media.ColorConverter]::ConvertFromString($Colors.Border)
                $transparentBorder = [System.Windows.Media.Color]::FromArgb(0, $borderColor.R, $borderColor.G, $borderColor.B)
                $gradient          = [System.Windows.Media.LinearGradientBrush]::new()
                $gradient.StartPoint = [System.Windows.Point]::new(0, 0.5)
                $gradient.EndPoint   = [System.Windows.Point]::new(1, 0.5)
                [void]$gradient.GradientStops.Add([System.Windows.Media.GradientStop]::new($transparentBorder, 0))
                [void]$gradient.GradientStops.Add([System.Windows.Media.GradientStop]::new($borderColor, 0.1))
                [void]$gradient.GradientStops.Add([System.Windows.Media.GradientStop]::new($borderColor, 0.9))
                [void]$gradient.GradientStops.Add([System.Windows.Media.GradientStop]::new($transparentBorder, 1))
                $Control.Background = $gradient
            }
            'Separator_Accent' {
                # Recreate accent fade gradient
                $accentColor       = [System.Windows.Media.ColorConverter]::ConvertFromString($Colors.Accent)
                $transparentAccent = [System.Windows.Media.Color]::FromArgb(0, $accentColor.R, $accentColor.G, $accentColor.B)
                $gradient          = [System.Windows.Media.LinearGradientBrush]::new()
                $gradient.StartPoint = [System.Windows.Point]::new(0, 0.5)
                $gradient.EndPoint   = [System.Windows.Point]::new(1, 0.5)
                [void]$gradient.GradientStops.Add([System.Windows.Media.GradientStop]::new($transparentAccent, 0))
                [void]$gradient.GradientStops.Add([System.Windows.Media.GradientStop]::new($accentColor, 0.15))
                [void]$gradient.GradientStops.Add([System.Windows.Media.GradientStop]::new($accentColor, 0.85))
                [void]$gradient.GradientStops.Add([System.Windows.Media.GradientStop]::new($transparentAccent, 1))
                $Control.Background = $gradient
            }
        }

        # Hashtable tags (card headers with accent/custom colors)
        if ($Control.Tag -is [System.Collections.IDictionary]) {
            $tagType = $Control.Tag['Type']
            if ($tagType -eq 'CardHeader') {
                if ($Control.Tag['CustomColor']) {
                    $Control.Background = ConvertTo-UiBrush $Control.Tag['CustomColor']
                }
                elseif ($Control.Tag['IsAccent']) {
                    $Control.Background = ConvertTo-UiBrush $Colors.Accent
                }
                else {
                    $headerBgColor = if ($Colors.GroupBoxBg) { $Colors.GroupBoxBg } else { $Colors.WindowBg }
                    $Control.Background = ConvertTo-UiBrush $headerBgColor
                }
            }
        }
    }
    elseif ($Control -is [System.Windows.Controls.PasswordBox]) {
        $Control.Background  = ConvertTo-UiBrush $Colors.ControlBg
        $Control.Foreground  = ConvertTo-UiBrush $Colors.ControlFg
        $Control.BorderBrush = ConvertTo-UiBrush $Colors.Border
    }
    elseif ($Control -is [System.Windows.Controls.CheckBox]) {
        Set-CheckBoxStyle -CheckBox $Control
    }
    elseif ($Control -is [System.Windows.Controls.RichTextBox]) {
        $Control.Background  = ConvertTo-UiBrush $Colors.ControlBg
        $Control.Foreground  = ConvertTo-UiBrush $Colors.ControlFg
        $Control.BorderBrush = ConvertTo-UiBrush $Colors.Border
        $highlightColor      = if ($Colors.TextHighlight) { $Colors.TextHighlight } else { $Colors.Selection }
        $Control.SelectionBrush = ConvertTo-UiBrush $highlightColor
    }
    elseif ($Control -is [System.Windows.Controls.ProgressBar]) {
        Set-ProgressBarStyle -ProgressBar $Control
    }
    elseif ($Control -is [System.Windows.Controls.Slider]) {
        Set-SliderStyle -Slider $Control
    }
    elseif ($Control -is [System.Windows.Controls.StackPanel]) {
        if ($Control.Tag -eq 'ProgressPanel') {
            $Control.Background = ConvertTo-UiBrush $Colors.ControlBg
        }
    }

    # Update ContextMenu if present (not in visual tree)
    if ($Control -is [System.Windows.FrameworkElement] -and $Control.ContextMenu) {
        Set-ContextMenuStyle -ContextMenu $Control.ContextMenu
    }
}