private/Banner.ps1

# FR-022: startup banner, horizontally centered to terminal width, visible above both the
# language screen and the main menu (not shown once and dropped).

$script:OctaWordmark = @(
    ' ██████╗ ██████╗ ████████╗ █████╗ ',
    '██╔═══██╗██╔════╝ ╚══██╔══╝██╔══██╗',
    '██║ ██║██║ ██║ ███████║',
    '██║ ██║██║ ██║ ██╔══██║',
    '╚██████╔╝╚██████╗ ██║ ██║ ██║',
    ' ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝'
)

function Get-OctaCenteredLine {
    <#
        Centers text within $Width and pads the remainder with spaces - not just cosmetic:
        the tagline varies in length between the normal banner and Show-OctaLanguageMenu's
        longer bilingual one, and without padding, picking the shorter one after the longer one
        left the longer one's trailing characters stuck on-screen (same bug class Write-
        OctaMenuRow already fixed for menu item rows).
    #>

    param(
        [Parameter(Mandatory)][string]$Text,
        [Parameter(Mandatory)][int]$Width
    )
    $padding = [Math]::Max(0, [Math]::Floor(($Width - $Text.Length) / 2))
    $line = (' ' * $padding) + $Text
    if ($line.Length -lt $Width) { $line = $line.PadRight($Width) }
    return $line
}

function Show-OctaBanner {
    [CmdletBinding()]
    param(
        [string]$Tagline = 'Windows 11 Debloat -- Local. Transparente. Open Source.'
    )

    $width = 80
    try { $width = $Host.UI.RawUI.WindowSize.Width } catch { }
    if ($width -lt 40 -or $width -gt 120) { $width = 80 }
    $safeWidth = $width - 1 # never write the very last column - avoids a soft-wrap-triggered scroll

    Write-Host ''
    foreach ($line in $script:OctaWordmark) {
        Write-Host (Get-OctaCenteredLine -Text $line -Width $safeWidth)
    }
    Write-Host ''
    Write-Host (Get-OctaCenteredLine -Text "🐙 $Tagline" -Width $safeWidth)
    Write-Host ''
}