﻿Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Globalization
Imports Nexamas.UI.Application
Imports Nexamas.UI.Components
Imports Nexamas.UI.Components.DropDownMenu
Imports Nexamas.UI.Controls
Imports Nexamas.UI.FileSystem
Imports Nexamas.UI.Icons
Imports Nexamas.UI.Layout
Imports Nexamas.UI.TextInput
Imports Nexamas.UI.Theming
Imports SkiaSharp

Partial Friend Class NexamasUIShowcase

    Private NotInheritable Class GuidedJourneyStep
        Friend Sub New(title As String,
                       message As String,
                       routeId As String,
                       groupKey As String)
            Me.Title = If(title, String.Empty)
            Me.Message = If(message, String.Empty)
            Me.RouteId = If(routeId, String.Empty)
            Me.GroupKey = If(groupKey, String.Empty)
        End Sub

        Friend ReadOnly Property Title As String
        Friend ReadOnly Property Message As String
        Friend ReadOnly Property RouteId As String
        Friend ReadOnly Property GroupKey As String
    End Class

    Private NotInheritable Class GuidedJourneyDefinition
        Friend Sub New(title As String,
                       message As String,
                       steps As GuidedJourneyStep())
            Me.Title = If(title, String.Empty)
            Me.Message = If(message, String.Empty)
            Me.Steps = If(steps, New GuidedJourneyStep() {})
        End Sub

        Friend ReadOnly Property Title As String
        Friend ReadOnly Property Message As String
        Friend ReadOnly Property Steps As GuidedJourneyStep()
    End Class

    Private Sub BuildHomeExecutiveSurface(page As MASApplicationLayoutPageBuilder)
        If page Is Nothing OrElse Window Is Nothing Then Return

        Dim banner As MASStatusBanner = Window.Controls.AddStatusBanner(
            title:="Showcase remains a pure consumer",
            message:="A live Nexamas.UI experience: the Showcase supplies only sample copy, route metadata, demo values, and page composition. Controls, layout, shell chrome, floating UI, theme, RTL, services, rendering, output, and proof surfaces remain owned by Nexamas.UI.",
            tone:=MASToastTone.Success)
        banner.WithSize(MASSize.FillWidth)
        AddShowcaseContent(page, banner, MASSize.FillWidth)

        Dim metrics As MASApplicationLayoutGridBuilder = page.Grid(3).Gap(MASLayoutSpacing.Large).EqualItemSize()
        metrics.Add(CreateMetric("Focused route", "1", "All launchpad journeys open the same PageHost-guided exploration stage."), MASSize.FillWidth)
        metrics.Add(CreateMetric("Guided step routes", CountGuidedJourneySteps().ToString(CultureInfo.InvariantCulture), "Each guided step is registered as its own PageHost route. The compact MASStepper header replaces the old large all-steps Wizard strip."), MASSize.FillWidth)
        metrics.Add(CreateMetric("Boundary", "Clean", "No Showcase-owned renderer, router, theme engine, or widget layer."), MASSize.FillWidth)

        BuildHomeSingleJourneyHost(page)
    End Sub

    Private Sub BuildHomeSingleJourneyHost(page As MASApplicationLayoutPageBuilder)
        Dim title As MASLabel = CreateBody("Start a focused guided exploration")
        title.LabelVariant = MASLabelVariant.Heading
        AddShowcaseContent(page, title, MASSize.FillWidth)
        AddShowcaseContent(page, CreateMuted("The Overview is only the launchpad. Pick a journey and the Showcase opens a dedicated PageHost route with a compact MASStepper header, clear task instructions, and one live work area for the current step."), MASSize.FillWidth)

        Dim actions As MASApplicationLayoutFlowBuilder = page.Flow().Gap(MASLayoutSpacing.Small).EqualItemWidth()
        AddJourneyLaunchButton(actions, "Start controls exploration", "controls", True)
        AddJourneyLaunchButton(actions, "Start systems exploration", "systems", False)
        AddJourneyLaunchButton(actions, "Start data workspace", "data", False)
        AddJourneyLaunchButton(actions, "Start Theme / RTL", "theme", False)
        AddJourneyLaunchButton(actions, "Start proof journey", "proof", False)
    End Sub
    Private Function CountGuidedJourneySteps() As Integer
        Dim total As Integer = 0
        For Each journeyId As String In New String() {"controls", "systems", "data", "theme", "proof"}
            Dim journey As GuidedJourneyDefinition = ResolveGuidedJourney(journeyId)
            If journey Is Nothing OrElse journey.Steps Is Nothing Then Continue For
            total += journey.Steps.Length
        Next
        Return total
    End Function


    Private Sub AddJourneyLaunchButton(actions As MASApplicationLayoutFlowBuilder,
                                       text As String,
                                       journeyId As String,
                                       primary As Boolean)
        If actions Is Nothing Then Return

        Dim button As MASButton = Window.Controls.AddButton(text)
        If primary Then button.AsPrimary()
        button.WithSize(MASSize.[Default])
        AddHandler button.Click, Sub() OpenGuidedJourney(journeyId, 0)
        actions.Add(button, MASSize.[Default])
    End Sub

    Private Sub OpenGuidedJourney(journeyId As String,
                                  stepIndex As Integer)
        If Window Is Nothing Then Return

        Dim journey As GuidedJourneyDefinition = ResolveGuidedJourney(journeyId)
        _guidedJourneyId = ResolveGuidedJourneyId(journeyId)
        _guidedJourneyStepIndex = NormalizeGuidedJourneyStepIndex(journey, stepIndex)
        NavigateToGuidedJourneyStage()
    End Sub

    Private Sub NavigateToGuidedJourneyStage()
        If Window Is Nothing Then Return

        Window.Pages.NavigateTo(ResolveGuidedJourneyStepPageId(_guidedJourneyId, _guidedJourneyStepIndex))
    End Sub

    Private Function ResolveGuidedJourneyStepPageId(journeyId As String,
                                                    stepIndex As Integer) As String
        Dim normalizedJourneyId As String = ResolveGuidedJourneyId(journeyId)
        Dim journey As GuidedJourneyDefinition = ResolveGuidedJourney(normalizedJourneyId)
        Dim normalizedStepIndex As Integer = NormalizeGuidedJourneyStepIndex(journey, stepIndex)
        Return GuidedJourneyPageId & "." & normalizedJourneyId & "." & normalizedStepIndex.ToString(CultureInfo.InvariantCulture)
    End Function

    Private Function ResolveGuidedJourneyRouteTitle(journeyId As String,
                                                    stepIndex As Integer) As String
        Dim journey As GuidedJourneyDefinition = ResolveGuidedJourney(journeyId)
        Dim currentIndex As Integer = NormalizeGuidedJourneyStepIndex(journey, stepIndex)
        If journey Is Nothing OrElse journey.Steps Is Nothing OrElse journey.Steps.Length = 0 Then Return "Guided Exploration"
        Return journey.Title & " — " & journey.Steps(currentIndex).Title
    End Function

    Friend Sub RegisterGuidedJourneyStepPages()
        If Window Is Nothing Then Return

        Dim journeyIds As String() = New String() {"controls", "systems", "data", "theme", "proof"}
        For Each journeyId As String In journeyIds
            Dim resolvedJourneyId As String = ResolveGuidedJourneyId(journeyId)
            Dim journey As GuidedJourneyDefinition = ResolveGuidedJourney(resolvedJourneyId)
            If journey Is Nothing OrElse journey.Steps Is Nothing Then Continue For

            For index As Integer = 0 To journey.Steps.Length - 1
                Dim registeredJourneyId As String = resolvedJourneyId
                Dim registeredStepIndex As Integer = index
                Window.Pages.RegisterPage(
                    pageId:=ResolveGuidedJourneyStepPageId(registeredJourneyId, registeredStepIndex),
                    title:=ResolveGuidedJourneyRouteTitle(registeredJourneyId, registeredStepIndex),
                    groupName:="Guided journeys",
                    description:=String.Empty,
                    buildPage:=Sub(page As MASApplicationLayoutPageBuilder)
                                   PrepareShowcasePageBuild()
                                   BuildGuidedJourneyStepPage(page, registeredJourneyId, registeredStepIndex)
                               End Sub)
            Next
        Next
    End Sub

    Private Function ResolveGuidedJourneyId(journeyId As String) As String
        Dim normalized As String = If(journeyId, String.Empty).Trim().ToLowerInvariant()

        Select Case normalized
            Case "controls", "systems", "data", "theme", "proof"
                Return normalized
            Case Else
                Return GuidedJourneyDefaultId
        End Select
    End Function

    Private Function ResolveGuidedJourney(journeyId As String) As GuidedJourneyDefinition
        Select Case ResolveGuidedJourneyId(journeyId)
            Case "systems"
                Return CreateSystemsJourney()
            Case "data"
                Return CreateDataJourney()
            Case "theme"
                Return CreateThemeRtlJourney()
            Case "proof"
                Return CreateProofJourney()
            Case Else
                Return CreateControlsJourney()
        End Select
    End Function

    Private Function NormalizeGuidedJourneyStepIndex(journey As GuidedJourneyDefinition,
                                                   requestedIndex As Integer) As Integer
        If journey Is Nothing OrElse journey.Steps Is Nothing OrElse journey.Steps.Length = 0 Then Return 0
        Return Math.Max(0, Math.Min(journey.Steps.Length - 1, requestedIndex))
    End Function

    Private Sub BuildGuidedJourneyPage(page As MASApplicationLayoutPageBuilder)
        BuildGuidedJourneyStepPage(page, _guidedJourneyId, _guidedJourneyStepIndex)
    End Sub

    Private Sub BuildGuidedJourneyStepPage(page As MASApplicationLayoutPageBuilder,
                                           journeyId As String,
                                           stepIndex As Integer)
        If page Is Nothing Then Return

        ApplyShowcaseWorkspaceSurface(page)

        _guidedJourneyId = ResolveGuidedJourneyId(journeyId)
        Dim journey As GuidedJourneyDefinition = ResolveGuidedJourney(_guidedJourneyId)
        Dim currentIndex As Integer = NormalizeGuidedJourneyStepIndex(journey, stepIndex)
        _guidedJourneyStepIndex = currentIndex

        If journey Is Nothing OrElse journey.Steps Is Nothing OrElse journey.Steps.Length = 0 Then
            AddShowcaseContent(page, Window.Controls.AddStatusBanner("No journey available", "The selected guided exploration could not be resolved.", MASToastTone.Warning), MASSize.FillWidth)
            Return
        End If

        Dim currentStep As GuidedJourneyStep = journey.Steps(currentIndex)
        BuildShowcaseRouteSummary(page, "Step " & (currentIndex + 1).ToString(CultureInfo.InvariantCulture) & " of " & journey.Steps.Length.ToString(CultureInfo.InvariantCulture) & " — " & currentStep.Title & ". Each step is its own PageHost route; the header stays compact so the live work area is visible immediately.")
        BuildCapabilityClassificationBanner(page, ShowcaseNavigationCatalog.FindById(currentStep.RouteId))
        BuildGuidedJourneyCompactStepper(page, journey, currentIndex, currentStep)

        Dim workAreaTitle As MASLabel = CreateBody("Live work area — " & currentStep.Title)
        workAreaTitle.LabelVariant = MASLabelVariant.Heading
        AddShowcaseContent(page, workAreaTitle, MASSize.FillWidth)
        AddShowcaseContent(page, CreateMuted(CreateGuidedStepTaskText(currentStep)), MASSize.FillWidth)

        BuildGuidedJourneyLiveStage(page, currentStep)

        AddShowcaseContent(page, CreateMuted("What to notice: " & CreateGuidedStepObservationText(currentStep)), MASSize.FillWidth)

        Dim previous As MASButton = Window.Controls.AddButton("Previous step")
        previous.Enabled = currentIndex > 0
        previous.WithSize(MASSize.Large)
        AddHandler previous.Click,
            Sub()
                _guidedJourneyStepIndex = NormalizeGuidedJourneyStepIndex(journey, _guidedJourneyStepIndex - 1)
                NavigateToGuidedJourneyStage()
            End Sub

        Dim nextButton As MASButton = Window.Controls.AddButton("Next step").AsPrimary()
        nextButton.Enabled = currentIndex < journey.Steps.Length - 1
        nextButton.WithSize(MASSize.Large)
        AddHandler nextButton.Click,
            Sub()
                _guidedJourneyStepIndex = NormalizeGuidedJourneyStepIndex(journey, _guidedJourneyStepIndex + 1)
                NavigateToGuidedJourneyStage()
            End Sub

        Dim back As MASButton = Window.Controls.AddButton("Back to Overview")
        back.WithSize(MASSize.Large)
        AddHandler back.Click, Sub() Window.Pages.NavigateTo(HomePageId)

        page.ActionGroup().AlignStart().IntrinsicItemSize().Gap(MASLayoutSpacing.Small).Add(previous, MASSize.Large).Add(nextButton, MASSize.Large).Add(back, MASSize.Large)
    End Sub

    Private Sub BuildGuidedJourneyCompactStepper(page As MASApplicationLayoutPageBuilder,
                                                 journey As GuidedJourneyDefinition,
                                                 currentIndex As Integer,
                                                 currentStep As GuidedJourneyStep)
        If page Is Nothing OrElse journey Is Nothing OrElse journey.Steps Is Nothing OrElse journey.Steps.Length = 0 Then Return

        Dim summaryText As String = journey.Title & " · Step " & (currentIndex + 1).ToString(CultureInfo.InvariantCulture) & " of " & journey.Steps.Length.ToString(CultureInfo.InvariantCulture) & " — " & If(currentStep Is Nothing, String.Empty, currentStep.Title)
        Dim summary As MASStatusBanner = Window.Controls.AddStatusBanner(
            title:=summaryText,
            message:=If(currentStep Is Nothing, journey.Message, currentStep.Message),
            tone:=MASToastTone.Info)
        summary.WithSize(MASSize.FillWidth)
        AddShowcaseContent(page, summary, MASSize.FillWidth)

        Dim stepper As MASStepper = Window.Controls.AddStepper(MASStepperOrientation.Horizontal, Sub(control As MASStepper)
                                                                                                     For index As Integer = 0 To journey.Steps.Length - 1
                                                                                                         control.AddStep((index + 1).ToString(CultureInfo.InvariantCulture))
                                                                                                     Next
                                                                                                     control.WithCurrentStep(currentIndex)
                                                                                                     control.WithSize(MASSize.FillWidth)
                                                                                                 End Sub)
        stepper.WithSize(MASSize.FillWidth)
        AddHandler stepper.CurrentStepChanged,
            Sub()
                If stepper.CurrentIndex < 0 OrElse stepper.CurrentIndex = _guidedJourneyStepIndex Then Return
                _guidedJourneyStepIndex = NormalizeGuidedJourneyStepIndex(journey, stepper.CurrentIndex)
                NavigateToGuidedJourneyStage()
            End Sub
        AddShowcaseContent(page, stepper, MASSize.FillWidth)
    End Sub

    Private Function CreateGuidedStepTaskText(stepItem As GuidedJourneyStep) As String
        If stepItem Is Nothing Then Return "Use the live stage below."
        Return "Use the live controls below for this step. Focus on this single family before moving forward: " & stepItem.Message
    End Function

    Private Function CreateGuidedStepObservationText(stepItem As GuidedJourneyStep) As String
        If stepItem Is Nothing Then Return "The focused route rebuilds one stage at a time."
        Return "This step is rebuilt as its own PageHost route. Natural controls stay compact, related controls sit in rows, and only true surfaces use full-width bands."
    End Function


    Private Sub BuildGuidedJourneyLiveStage(page As MASApplicationLayoutPageBuilder,
                                            stepItem As GuidedJourneyStep)
        If page Is Nothing OrElse stepItem Is Nothing Then Return

        If Not BuildSharedScenario(page, stepItem.RouteId, stepItem.GroupKey) Then
            BuildMessageGroup(
                page,
                "Unknown shared scenario",
                "The selected guided step could not be mapped to the shared direct-route scenario registry.",
                MASToastTone.Warning)
        End If
    End Sub

    Private Function CreateControlsJourney() As GuidedJourneyDefinition
        Return New GuidedJourneyDefinition("Controls exploration", "Explore live control families. Each step shows real Nexamas.UI controls in the family instead of explanatory DataGrid rows.", New GuidedJourneyStep() {
            New GuidedJourneyStep("Actions", "Buttons, split commands, check boxes, radio buttons, and toggles appear together as the action surface family.", "buttons", "controls.actions"),
            New GuidedJourneyStep("Text inputs", "Text, password, numeric, multiline, and path fields are shown as concrete inputs, not as a form summary.", "inputs", "controls.text"),
            New GuidedJourneyStep("Search, filters, and values", "SearchBox, ComboBox, TagInput, and Slider are grouped because real filtering flows combine all of them.", "inputs", "controls.search"),
            New GuidedJourneyStep("Date and time", "DatePicker, DateRangePicker, CalendarView, and TimePicker are shown as the calendar/time input family.", "inputs", "controls.datetime"),
            New GuidedJourneyStep("Feedback", "Badges, rating, banners, validation, and empty states explain page state without service queues.", "feedback.status", "controls.feedback"),
            New GuidedJourneyStep("People and activity", "Avatar, AvatarGroup, Timeline, and NotificationPanel show activity and people-facing feedback.", "feedback.status", "controls.people"),
            New GuidedJourneyStep("Selection", "Segmented choices, tabs, and TransferList are grouped as selection and mode-changing controls.", "selection", "controls.selection"),
            New GuidedJourneyStep("Lists and structure", "ListBox, ListView, TreeView, Breadcrumb, and Pagination show compact navigation/structure surfaces.", "lists.tree", "controls.lists"),
            New GuidedJourneyStep("Icon resolution", "A shared IMASIconResolver receives real ListView and TreeView requests and returns public MASIconResult decisions.", "icon.resolution", "controls.icons"),
            New GuidedJourneyStep("Tiles", "MASTileBox visual selection proves gallery/template choices without hand-drawing tile chrome or selection state.", "tiles", "controls.tiles"),
            New GuidedJourneyStep("Visual editors", "ColorPicker, visual option choice, and EmptyState preview show editor-like surfaces without a designer engine.", "visual.editors", "controls.visual"),
            New GuidedJourneyStep("File surfaces", "FileDropZone, FilePickerControl, and FileExplorerView complete the controls overview through official file-surface routes.", "file.surfaces", "controls.files")
        })
    End Function

    Private Function CreateSystemsJourney() As GuidedJourneyDefinition
        Return New GuidedJourneyDefinition("Systems exploration", "Explore Nexamas.UI systems through visible behavior: shell, layout, services, theme stress, motion, sizing, and output inside this journey stage.", New GuidedJourneyStep() {
            New GuidedJourneyStep("Shell and PageHost", "Shell, menu, PageHost, route trail, and discovery matrix.", "application.architecture", "systems.shell"),
            New GuidedJourneyStep("Application layout", "AppLayout and SplitView workspace regions.", "application.architecture", "systems.layout"),
            New GuidedJourneyStep("Multi-window lifetime", "Create a secondary Nexamas.UI window through the same MASApplication and observe WindowCount and owner-close cleanup.", "application.lifetime", "systems.lifetime"),
            New GuidedJourneyStep("Services and floating UI", "Toast, dialog, callout, and operation services.", "services", "systems.services"),
            New GuidedJourneyStep("Workflow foundations", "Command/action, binding preview, public validation, FormValidationSummary, Stepper, and Wizard surfaces.", "workflow.foundations", "systems.workflow"),
            New GuidedJourneyStep("Productivity navigation", "NavigationRail, CommandBar, CommandPalette, Breadcrumb, FilterBar, Pagination, LoadingSkeleton, Expander, and Accordion.", "productivity.navigation", "systems.productivity"),
            New GuidedJourneyStep("Theme system", "Global theme stress surface for readability, semantic states, feedback, and focus.", "theme.studio", "systems.theme"),
            New GuidedJourneyStep("Motion and runtime state", "Interaction, progress, operation, selector, and timeline.", "motion", "systems.motion"),
            New GuidedJourneyStep("Sizing profiles", "Public size intents without page constants.", "settings.sizing", "systems.sizing"),
            New GuidedJourneyStep("Output system", "Supported targets and explicit output boundaries.", "output.product", "systems.output")
        })
    End Function

    Private Function CreateDataJourney() As GuidedJourneyDefinition
        Return New GuidedJourneyDefinition("Data workspace exploration", "Explore data controls as product workspaces: DataGrid with search, analytics, filters, hierarchy, charts, planning, inspector, and virtualization inside this journey stage.", New GuidedJourneyStep() {
            New GuidedJourneyStep("DataGrid workbench", "DataGrid is shown with SearchBox and filter helpers so it behaves like a real work surface.", "datagrid", "data.grid"),
            New GuidedJourneyStep("Dashboard metrics", "MetricCard and DashboardGrid summarize business signals without telemetry engines.", "data.analytics", "data.metrics"),
            New GuidedJourneyStep("Filters", "FilterBuilder and AppliedFiltersBar show product-readable filter state without query providers.", "data.analytics", "data.filters"),
            New GuidedJourneyStep("Hierarchy and pivot", "TreeGrid and PivotTable show structured and cross-tabular data without wrapping DataGrid.", "data.analytics", "data.hierarchy"),
            New GuidedJourneyStep("Charts", "Charts and ChartLegend are business visual surfaces, not a Showcase chart renderer.", "charts.dashboard", "data.charts"),
            New GuidedJourneyStep("Planning workspace", "KanbanBoard, AgendaView, and ContentCarousel appear together as a real planning surface.", "planning.workspace", "data.planning"),
            New GuidedJourneyStep("Inspector", "PropertyGrid and MasterDetailView show entity/developer inspection surfaces.", "property.inspector", "data.inspector"),
            New GuidedJourneyStep("Virtualization", "Large-item proof remains visible through a compact live stage instead of redirecting to another page.", "virtualization", "data.virtualization")
        })
    End Function

    Private Function CreateThemeRtlJourney() As GuidedJourneyDefinition
        Return New GuidedJourneyDefinition("Theme and RTL exploration", "Explore readability, material, official Localization / RTL content, feedback state, motion feel, form density, and output readiness inside this journey stage.", New GuidedJourneyStep() {
            New GuidedJourneyStep("Readability", "Window.Theme.GetAll and Window.Theme.TryUse drive the real registered-theme surface.", "theme.studio", "theme.readability"),
            New GuidedJourneyStep("Surface material", "MASApplicationSurfaceMaterialGateway and one public scope apply real selectable materials.", "surface.materials", "theme.material"),
            New GuidedJourneyStep("Localization / RTL", "The Nexamas.UI-owned Localization / RTL page is attached through MASLocalizationRtl.AttachPage(window, page).", "localization.rtl.product", "theme.localization"),
            New GuidedJourneyStep("Feedback states", "Theme-aware banners, validation, badges, and empty states prove readability under state changes.", "feedback.status", "theme.feedback"),
            New GuidedJourneyStep("Motion feel", "Motion stays visible through interactive controls and status changes.", "motion", "theme.motion"),
            New GuidedJourneyStep("Forms", "Input density and readability are shown in a compact theme-aware form surface.", "inputs", "theme.forms"),
            New GuidedJourneyStep("Output readiness", "Theme/RTL surfaces remain compatible with output and proof routes.", "output.product", "theme.output")
        })
    End Function

    Private Function CreateProofJourney() As GuidedJourneyDefinition
        Return New GuidedJourneyDefinition("Proof journey", "Proof is kept separate from controls. It uses the same host, but shows documentation, coverage, render, output, package, certification, diagnostics, and consumer-boundary evidence inside this journey stage.", New GuidedJourneyStep() {
            New GuidedJourneyStep("Documentation alignment", "Docs and recipes map to live routes without exposing internal engines.", "core.documentation", "proof.docs"),
            New GuidedJourneyStep("Licensing / Evaluation", "Seven-day legal evaluation, sales-not-open status, commercial-use boundary, source-access terms, and no false runtime lockout claims.", "licensing.evaluation", "proof.licensing"),
            New GuidedJourneyStep("Commercial foundations", "Report/Print and Plugin/Module foundations are shown as certified commercial decisions without opening unavailable hosts.", "commercial.foundations", "proof.commercial"),
            New GuidedJourneyStep("Element coverage", "Public element coverage proves new controls are not hidden in broad pages.", "element.coverage", "proof.coverage"),
            New GuidedJourneyStep("Render verification", "PNG baseline/current/diff proof remains owned by Nexamas.UI.", "render.verification", "proof.render"),
            New GuidedJourneyStep("Output proof", "MASApplication.Output is a public SDK route with product evidence targets.", "output.product", "proof.output"),
            New GuidedJourneyStep("Package proof", "NuGet README, license, and packed consumer proof stay delivery evidence, not runtime UI.", "packaging.consumer", "proof.package"),
            New GuidedJourneyStep("Certification", "Certification is shown as product-readable summary, not an internal evidence engine.", "certification.center", "proof.certification"),
            New GuidedJourneyStep("Diagnostics", "Diagnostics dashboard is read-only and does not open telemetry ownership in Showcase.", "diagnostics.dashboard", "proof.diagnostics"),
            New GuidedJourneyStep("DPI / Text / Accessibility", "Public geometry and text evidence is shown together with an explicit non-claim for unavailable Screen Reader/UI Automation integration.", "dpi.text.accessibility", "proof.dpiAccessibility"),
            New GuidedJourneyStep("Consumer boundary", "The Showcase remains a clean external consumer of public Nexamas.UI APIs.", "element.coverage", "proof.boundary")
        })
    End Function


    Private Function BuildGuidedStageControlsTextInputs(page As MASApplicationLayoutPageBuilder) As List(Of MASControlBase)
        Dim controls As New List(Of MASControlBase)()
        RegisterGuidedStageControl(page, controls, CreateMuted("Text input family: fields, validation messages, helper text, path input, multiline notes, and a compact DataForm / FormBuilder summary all live inside the journey."))

        Dim textBox As MASTextBox = Window.Controls.AddTextBox("External consumer")
        textBox.WithSize(MASSize.Large)
        Dim textValidation As MASValidationMessage = Window.Controls.AddValidationMessage("Customer name is ready for submission.", MASTextValidationState.Success, Sub(message As MASValidationMessage)
                                                                                                                                             message.WithSize(MASSize.Compact)
                                                                                                                                         End Sub)

        Dim password As MASPasswordTextBox = Window.Controls.AddPasswordTextBox("secret", Sub(box As MASPasswordTextBox)
                                                                                                box.Placeholder = "Password"
                                                                                                box.WithSize(MASSize.Large)
                                                                                            End Sub)
        Dim passwordValidation As MASValidationMessage = Window.Controls.AddValidationMessage("Use at least twelve characters for production credentials.", MASTextValidationState.Warning, Sub(message As MASValidationMessage)
                                                                                                                                                    message.WithSize(MASSize.Compact)
                                                                                                                                                End Sub)

        Dim numeric As MASNumericTextBox = Window.Controls.AddNumericTextBox(Sub(box As MASNumericTextBox)
                                                                                box.WithIntegerValue(42)
                                                                                box.DisallowNegativeNumbers()
                                                                                box.WithSize(MASSize.Compact)
                                                                            End Sub)
        Dim amountValidation As MASValidationMessage = Window.Controls.AddValidationMessage("Amount must stay below the configured invoice limit.", MASTextValidationState.Error, Sub(message As MASValidationMessage)
                                                                                                                                              message.WithSize(MASSize.Compact)
                                                                                                                                          End Sub)
        Dim neutralValidation As MASValidationMessage = Window.Controls.AddValidationMessage("Optional helper text without an icon keeps dense forms readable.", MASTextValidationState.Information, Sub(message As MASValidationMessage)
                                                                                                                                                     message.WithIcon(False)
                                                                                                                                                     message.WithSize(MASSize.Compact)
                                                                                                                                                 End Sub)

        Dim pathBox As MASPathTextBox = Window.Controls.AddPathTextBox("C:\MASLab\Assets")
        pathBox.WithSize(MASSize.Large)
        Dim multiline As MASMultilineTextBox = Window.Controls.AddMultilineTextBox("Customer note:" & Environment.NewLine & "- Delivery before noon" & Environment.NewLine & "- Call before arrival", Sub(box As MASMultilineTextBox)
                                                                                                                                                                                                        box.WithPlaceholder("Write a multiline note...")
                                                                                                                                                                                                        box.WithWordWrap(True)
                                                                                                                                                                                                        box.WithSize(MASSize.Large.OffsetHeight(110.0F))
                                                                                                                                                                                                    End Sub)

        Dim dataForm As MASDataForm = Window.Controls.AddDataForm(
            configure:=Sub(builder As MASFormBuilder)
                           builder.AddText("Customer", "Contoso GmbH", True, "Required public text row")
                           builder.AddSelection("Region", "Germany", "Selection display row")
                           builder.AddDate("Reporting range", "July 2026", "DateRangePicker feeds this display text")
                           builder.AddTags("Labels", "Premium, v1, Launch", "TagInput-style display row")
                           builder.AddToggle("Live sync", True, "Toggle state shown as display-only form evidence")
                       End Sub,
            configureControl:=Sub(form As MASDataForm)
                                  form.WithTitle("DataForm / FormBuilder")
                                  form.WithDescription("Business form summary through MASFormBuilder only; no binding engine, reflection editor, persistence, or validation engine is opened in Showcase.")
                                  form.WithSize(MASSize.FillWidth.OffsetHeight(300.0F))
                              End Sub)

        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {textBox, textValidation})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {password, passwordValidation})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {numeric, amountValidation, neutralValidation})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {pathBox, multiline})
        RegisterGuidedStageControl(page, controls, dataForm)
        Return controls
    End Function

    Private Function BuildGuidedStageControlsSearchFiltersValues(page As MASApplicationLayoutPageBuilder) As List(Of MASControlBase)
        Dim controls As New List(Of MASControlBase)()
        RegisterGuidedStageControl(page, controls, CreateMuted("Search and filter family: SearchBox, ComboBox, TagInput, Slider, helper text, and live status labels are shown together because real filters combine text, choices, labels, and values."))

        Dim search As MASSearchTextBox = Window.Controls.AddSearchTextBox("", Sub(box As MASSearchTextBox)
                                                                                   box.Placeholder = "Search capabilities..."
                                                                                   box.SetSuggestions(New String() {"DataGrid", "Buttons", "RTL", "Render Verification"})
                                                                                   box.AddRecentSearch("DataGrid")
                                                                                   box.AddFilterToken("area", "Controls")
                                                                                   box.WithSize(MASSize.Large)
                                                                               End Sub)
        Dim searchValidation As MASValidationMessage = Window.Controls.AddValidationMessage("Search accepts plain text, recent terms, suggestions, and filter-token hints without a Showcase-owned search engine.", MASTextValidationState.Information, Sub(message As MASValidationMessage)
                                                                                                                                                                                                  message.WithSize(MASSize.Compact)
                                                                                                                                                                                              End Sub)

        Dim combo As MASComboBox = Window.Controls.AddComboBox(items:=New String() {"Germany", "Canada", "Japan", "Netherlands", "Sweden", "France", "Italy", "Spain"}, selectedIndex:=0)
        combo.WithSize(MASSize.Large)
        Dim comboStatus As MASLabel = CreateMuted("ComboBox: country choice is visual state owned by the control.")

        Dim tags As MASTagInput = Window.Controls.AddTagInput(New String() {"Premium", "RTL", "Launch"}, Sub(input As MASTagInput)
                                                                                                             input.WithPlaceholder("Add tags")
                                                                                                             input.WithSize(MASSize.Large)
                                                                                                         End Sub)
        Dim tagStatus As MASLabel = CreateMuted("TagInput: " & tags.TagCount.ToString(CultureInfo.InvariantCulture) & " tags; selected='" & tags.SelectedText & "'.")
        AddHandler tags.TagsChanged,
            Sub(sender As Object, args As EventArgs)
                tagStatus.Text = "TagInput: " & tags.TagCount.ToString(CultureInfo.InvariantCulture) & " tags; selected='" & tags.SelectedText & "'."
            End Sub
        AddHandler tags.SelectedIndexChanged,
            Sub(sender As Object, args As EventArgs)
                tagStatus.Text = "TagInput: " & tags.TagCount.ToString(CultureInfo.InvariantCulture) & " tags; selected='" & tags.SelectedText & "'."
            End Sub

        Dim sliderStatus As MASLabel = CreateMuted("Slider: 68% readiness value.")
        Dim slider As MASSlider = Window.Controls.AddSlider(minimum:=0.0R, maximum:=100.0R, value:=68.0R, configure:=Sub(control As MASSlider)
                                                                                                                            control.WithStep(5.0R)
                                                                                                                            control.WithTicks(25.0R)
                                                                                                                            control.WithValueLabel(True)
                                                                                                                            control.WithSize(MASSize.Large)
                                                                                                                        End Sub)
        AddHandler slider.ValueChanged, Sub(sender As Object, e As EventArgs) sliderStatus.Text = "Slider: " & slider.Value.ToString("0", CultureInfo.InvariantCulture) & "% readiness value."

        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {search, searchValidation})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {combo, comboStatus})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {tags, tagStatus})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {slider, sliderStatus})
        Return controls
    End Function

    Private Function BuildGuidedStageControlsDateTime(page As MASApplicationLayoutPageBuilder) As List(Of MASControlBase)
        Dim controls As New List(Of MASControlBase)()
        RegisterGuidedStageControl(page, controls, CreateMuted("Date/time family: date pickers, date range, calendar month surface, time pickers, and preview labels are all shown in the journey."))
        Dim deliveryDate As MASDatePicker = Window.Controls.AddDatePicker(selectedDate:=New Nullable(Of Date)(New Date(2026, 7, 9)), configure:=Sub(picker As MASDatePicker)
                                                                                                                                            picker.WithPlaceholder("Delivery date")
                                                                                                                                            picker.WithSize(MASSize.Compact)
                                                                                                                                        End Sub)
        Dim reviewDate As MASDatePicker = Window.Controls.AddDatePicker(configure:=Sub(picker As MASDatePicker)
                                                                            picker.WithPlaceholder("Optional review date")
                                                                            picker.WithSize(MASSize.Compact)
                                                                        End Sub)
        Dim datePreview As MASLabel = CreateMuted("DatePicker preview: delivery='" & deliveryDate.DisplayText & "' | review='not selected'.")
        AddHandler deliveryDate.SelectedDateChanged, Sub(sender As Object, args As EventArgs) datePreview.Text = "DatePicker preview: delivery='" & If(deliveryDate.SelectedDate.HasValue, deliveryDate.DisplayText, "not selected") & "' | review='" & If(reviewDate.SelectedDate.HasValue, reviewDate.DisplayText, "not selected") & "'."
        AddHandler reviewDate.SelectedDateChanged, Sub(sender As Object, args As EventArgs) datePreview.Text = "DatePicker preview: delivery='" & If(deliveryDate.SelectedDate.HasValue, deliveryDate.DisplayText, "not selected") & "' | review='" & If(reviewDate.SelectedDate.HasValue, reviewDate.DisplayText, "not selected") & "'."

        Dim reportingRange As MASDateRangePicker = Window.Controls.AddDateRangePicker(startDate:=New Nullable(Of Date)(New Date(2026, 7, 1)), endDate:=New Nullable(Of Date)(New Date(2026, 7, 31)), configure:=Sub(picker As MASDateRangePicker)
                                                                                                                                                                                                                       picker.WithPlaceholders("Start date", "End date")
                                                                                                                                                                                                                       picker.WithSize(MASSize.Large)
                                                                                                                                                                                                                   End Sub)
        Dim rangePreview As MASLabel = CreateMuted("DateRangePicker preview: " & reportingRange.DisplayText)
        AddHandler reportingRange.RangeChanged, Sub(sender As Object, args As EventArgs) rangePreview.Text = "DateRangePicker preview: " & reportingRange.DisplayText

        Dim calendar As MASCalendarView = Window.Controls.AddCalendarView(selectedDate:=New Nullable(Of Date)(New Date(2026, 7, 9)), displayMonth:=New Nullable(Of Date)(New Date(2026, 7, 1)), configure:=Sub(view As MASCalendarView)
                                                                                                                                                           view.WithTitle("Delivery calendar")
                                                                                                                                                           view.WithOutsideDays(True)
                                                                                                                                                           view.WithSize(MASSize.Large.OffsetHeight(300.0F))
                                                                                                                                                       End Sub)
        Dim calendarPreview As MASLabel = CreateMuted("CalendarView preview: selected='" & calendar.SelectedDate.Value.ToString("d", CultureInfo.CurrentCulture) & "' | month='" & calendar.MonthTitle & "'.")
        AddHandler calendar.SelectedDateChanged, Sub(sender As Object, args As EventArgs) calendarPreview.Text = "CalendarView preview: selected='" & If(calendar.SelectedDate.HasValue, calendar.SelectedDate.Value.ToString("d", CultureInfo.CurrentCulture), "not selected") & "' | month='" & calendar.MonthTitle & "'."
        AddHandler calendar.DisplayMonthChanged, Sub(sender As Object, args As EventArgs) calendarPreview.Text = "CalendarView preview: selected='" & If(calendar.SelectedDate.HasValue, calendar.SelectedDate.Value.ToString("d", CultureInfo.CurrentCulture), "not selected") & "' | month='" & calendar.MonthTitle & "'."

        Dim timePicker As MASTimePicker = Window.Controls.AddTimePicker(selectedTime:=New Nullable(Of TimeSpan)(New TimeSpan(9, 30, 0)), configure:=Sub(picker As MASTimePicker)
                                                                                                                                             picker.WithPlaceholder("Start time")
                                                                                                                                             picker.WithSize(MASSize.Compact)
                                                                                                                                         End Sub)
        Dim reminderTime As MASTimePicker = Window.Controls.AddTimePicker(configure:=Sub(picker As MASTimePicker)
                                                                             picker.WithPlaceholder("Reminder time")
                                                                             picker.WithMinuteStep(15)
                                                                             picker.WithSize(MASSize.Compact)
                                                                         End Sub)
        Dim timePreview As MASLabel = CreateMuted("TimePicker preview: start='" & timePicker.DisplayText & "' | reminder='not selected'.")
        AddHandler timePicker.SelectedTimeChanged, Sub(sender As Object, args As EventArgs) timePreview.Text = "TimePicker preview: start='" & If(timePicker.SelectedTime.HasValue, timePicker.DisplayText, "not selected") & "' | reminder='" & If(reminderTime.SelectedTime.HasValue, reminderTime.DisplayText, "not selected") & "'."
        AddHandler reminderTime.SelectedTimeChanged, Sub(sender As Object, args As EventArgs) timePreview.Text = "TimePicker preview: start='" & If(timePicker.SelectedTime.HasValue, timePicker.DisplayText, "not selected") & "' | reminder='" & If(reminderTime.SelectedTime.HasValue, reminderTime.DisplayText, "not selected") & "'."

        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {deliveryDate, reviewDate, datePreview})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {reportingRange, rangePreview})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {calendar, calendarPreview})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {timePicker, reminderTime, timePreview})
        Return controls
    End Function

    Private Function BuildGuidedStageControlsFeedback(page As MASApplicationLayoutPageBuilder) As List(Of MASControlBase)
        Dim controls As New List(Of MASControlBase)()
        RegisterGuidedStageControl(page, controls, CreateMuted("Feedback family: badges, rating, status banners, validation messages, and empty states are shown as product-facing surfaces inside the journey."))
        Dim draft As MASBadge = Window.Controls.AddBadge("Draft", MASToastTone.Neutral, Sub(badge As MASBadge) badge.WithSize(MASSize.Compact))
        Dim live As MASBadge = Window.Controls.AddBadge("Live", MASToastTone.Success, Sub(badge As MASBadge) badge.WithSize(MASSize.Compact))
        Dim review As MASBadge = Window.Controls.AddBadge("Review", MASToastTone.Warning, Sub(badge As MASBadge) badge.WithSize(MASSize.Compact))
        Dim blocked As MASBadge = Window.Controls.AddBadge("Blocked", MASToastTone.Danger, Sub(badge As MASBadge) badge.WithSize(MASSize.Compact))
        Dim dot As MASBadge = Window.Controls.AddBadge(String.Empty, MASToastTone.Info, Sub(badge As MASBadge)
                                                                                           badge.WithDotOnly(True)
                                                                                           badge.WithSize(MASSize.Compact)
                                                                                       End Sub)
        Dim ratingStatus As MASLabel = CreateMuted("Rating: 4.5 / 5 release confidence; visual feedback only.")
        Dim rating As MASRating = Window.Controls.AddRating(4.5R, 5, Sub(control As MASRating)
                                                                         control.WithLabel("Release confidence")
                                                                         control.WithHalfValues(True)
                                                                         control.WithSize(MASSize.FillWidth)
                                                                     End Sub)
        Dim readOnlyRating As MASRating = Window.Controls.AddRating(3.0R, 5, Sub(control As MASRating)
                                                                                 control.WithLabel("Reviewer sentiment")
                                                                                 control.WithReadOnly(True)
                                                                                 control.WithSize(MASSize.FillWidth)
                                                                             End Sub)
        AddHandler rating.ValueChanged,
            Sub(sender As Object, e As EventArgs)
                ratingStatus.Text = "Rating changed: " & rating.ValueText & "; Showcase did not create feedback storage or review services."
            End Sub
        Dim infoBanner As MASStatusBanner = Window.Controls.AddStatusBanner("Workspace ready", "Information feedback can sit directly inside application pages.", MASToastTone.Info)
        Dim successBanner As MASStatusBanner = Window.Controls.AddStatusBanner("Saved successfully", "Success feedback remains semantic and theme-aware.", MASToastTone.Success)
        Dim warningBanner As MASStatusBanner = Window.Controls.AddStatusBanner("Review recommended", "Use a banner when a whole section needs attention.", MASToastTone.Warning)
        Dim quietBanner As MASStatusBanner = Window.Controls.AddStatusBanner("Quiet helper", "This compact banner hides the icon for dense product pages.", MASToastTone.Neutral)
        quietBanner.WithIcon(False)
        For Each banner As MASStatusBanner In New MASStatusBanner() {infoBanner, successBanner, warningBanner, quietBanner}
            banner.WithSize(MASSize.FillWidth)
        Next
        Dim validation As MASValidationMessage = Window.Controls.AddValidationMessage("Field-level message through MASValidationMessage.", MASTextValidationState.Information)
        validation.WithSize(MASSize.HugContent)
        Dim empty As MASEmptyState = Window.Controls.AddEmptyState("No search results", "Try a different keyword or clear filters.", Sub(state As MASEmptyState)
                                                                                                                                            state.WithSize(MASSize.FillWidth)
                                                                                                                                        End Sub)
        Dim emptyNotifications As MASEmptyState = Window.Controls.AddEmptyState("No notifications", "Important updates will appear here when there is something to review.", Sub(state As MASEmptyState)
                                                                                                                                                  state.WithIllustration(False)
                                                                                                                                                  state.WithSize(MASSize.FillWidth)
                                                                                                                                              End Sub)
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {draft, live, review, blocked, dot})
        RegisterGuidedStageCompactRow(page, controls, New MASControlBase() {rating, readOnlyRating})
        RegisterGuidedStageControl(page, controls, ratingStatus)
        RegisterGuidedStageSurfaceGrid(page, controls, 2, New MASControlBase() {infoBanner, successBanner, warningBanner, quietBanner})
        RegisterGuidedStageControl(page, controls, validation, MASSize.HugContent)
        RegisterGuidedStageSurfaceGrid(page, controls, 2, New MASControlBase() {empty, emptyNotifications})
        Return controls
    End Function

    Private Function BuildGuidedStageControlsPeopleActivity(page As MASApplicationLayoutPageBuilder) As List(Of MASControlBase)
        Dim controls As New List(Of MASControlBase)()
        RegisterGuidedStageControl(page, controls, CreateMuted("People/activity family: avatar, avatar group, timeline, notification panel, status labels, and notification actions are all available inside this step."))
        Dim avatar As MASAvatar = Window.Controls.AddAvatar("Design Lead", "DL", Sub(control As MASAvatar)
                                                                                      control.WithPresence("Online", True)
                                                                                      control.WithSelected(True)
                                                                                      control.WithSize(MASSize.Compact)
                                                                                  End Sub)
        Dim avatarA As MASAvatar = MASAvatar.Create("Runtime Owner", "RO").WithPresence("Ready", True)
        Dim avatarB As MASAvatar = MASAvatar.Create("QA Reviewer", "QA").WithPresence("Testing", True)
        Dim avatarC As MASAvatar = MASAvatar.Create("Release", "RL").WithPresence("Review", True)
        Dim group As MASAvatarGroup = Window.Controls.AddAvatarGroup(New MASAvatar() {avatarA, avatarB, avatarC}, Sub(control As MASAvatarGroup)
                                                                                                                       control.WithMaxVisible(3)
                                                                                                                       control.WithSelectedIndex(1)
                                                                                                                       control.WithSize(MASSize.FillWidth)
                                                                                                                   End Sub)
        Dim avatarStatus As MASLabel = CreateMuted("AvatarGroup: selected reviewer index " & group.SelectedIndex.ToString(CultureInfo.InvariantCulture) & ".")
        AddHandler group.SelectedIndexChanged,
            Sub(sender As Object, args As EventArgs)
                avatarStatus.Text = "AvatarGroup changed: selected reviewer index " & group.SelectedIndex.ToString(CultureInfo.InvariantCulture) & "."
            End Sub
        Dim timeline As MASTimeline = Window.Controls.AddTimeline("Activity timeline", "Application-owned activity rows displayed through MASTimeline.", Sub(control As MASTimeline)
                                                                                                                                                  control.WithSize(MASSize.FillWidth.OffsetHeight(280.0F))
                                                                                                                                                  control.AddItem("Architecture checked", "Commercial routes are aligned.", "09:00", MASTimelineItemState.Completed)
                                                                                                                                                  control.AddItem("Showcase update", "Guided journey stage is active.", "10:15", MASTimelineItemState.Current)
                                                                                                                                                  control.AddItem("Manual review", "Inspect the generated page.", "Next", MASTimelineItemState.Warning)
                                                                                                                                                  control.AddItem("v1 launch prep", "Docs, samples, NuGet proof, and API freeze remain host tasks.", "Later", MASTimelineItemState.Normal)
                                                                                                                                              End Sub)
        Dim timelineStatus As MASLabel = CreateMuted("Timeline: " & timeline.ItemCount.ToString(CultureInfo.InvariantCulture) & " items; selected='" & timeline.GetItemTitle(timeline.SelectedIndex) & "'.")
        AddHandler timeline.SelectedIndexChanged,
            Sub(sender As Object, args As EventArgs)
                timelineStatus.Text = "Timeline: " & timeline.ItemCount.ToString(CultureInfo.InvariantCulture) & " items; selected='" & timeline.GetItemTitle(timeline.SelectedIndex) & "'."
            End Sub
        Dim panel As MASNotificationPanel = Window.Controls.AddNotificationPanel("Notification Panel", Sub(control As MASNotificationPanel)
                                                                                                            control.WithTimestamps(True)
                                                                                                            control.WithEmptyText("All clear", "There are no application-owned notification summaries to display.")
                                                                                                            control.WithSize(MASSize.FillWidth.OffsetHeight(260.0F))
                                                                                                        End Sub)
        panel.AddNotification("Build completed", "Guided journey stage is ready for review.", MASToastTone.Success, "09:30", "Open", True)
        panel.AddNotification("Design review", "Check the new single host flow.", MASToastTone.Info, "10:15", "Review", True)
        panel.AddNotification("Action needed", "One notification is intentionally shown as already read.", MASToastTone.Warning, "11:00", "Inspect", False)
        Dim markAllRead As MASButton = Window.Controls.AddButton("Mark all read")
        Dim clearNotifications As MASButton = Window.Controls.AddButton("Clear notifications")
        Dim notificationStatus As MASLabel = CreateMuted("NotificationPanel: " & panel.NotificationCount.ToString(CultureInfo.InvariantCulture) & " items, " & panel.UnreadCount.ToString(CultureInfo.InvariantCulture) & " unread.")
        Dim refreshNotificationStatus As Action =
            Sub()
                notificationStatus.Text = "NotificationPanel: " & panel.NotificationCount.ToString(CultureInfo.InvariantCulture) & " items, " & panel.UnreadCount.ToString(CultureInfo.InvariantCulture) & " unread."
            End Sub
        AddHandler panel.NotificationsChanged, Sub(sender As Object, e As EventArgs) refreshNotificationStatus.Invoke()
        AddHandler markAllRead.Click,
            Sub()
                panel.MarkAllRead()
                refreshNotificationStatus.Invoke()
                Window.Refresh()
            End Sub
        AddHandler clearNotifications.Click,
            Sub()
                panel.ClearNotifications()
                refreshNotificationStatus.Invoke()
                Window.Refresh()
            End Sub
        For Each control As MASControlBase In New MASControlBase() {avatar, group, avatarStatus, timeline, timelineStatus, panel, notificationStatus, markAllRead, clearNotifications}
            RegisterGuidedStageControl(page, controls, control)
        Next
        Return controls
    End Function







    Private Function BuildMessageGroup(page As MASApplicationLayoutPageBuilder,
                                       title As String,
                                       message As String,
                                       tone As MASToastTone) As List(Of MASControlBase)
        Dim controls As New List(Of MASControlBase)()
        Dim banner As MASStatusBanner = Window.Controls.AddStatusBanner(title, message, tone)
        banner.WithSize(MASSize.FillWidth)
        RegisterGuidedStageControl(page, controls, banner)
        Return controls
    End Function



    Private Const GuidedMatrixHeaderHeightDip As Single = 42.0F
    Private Const GuidedMatrixRowHeightDip As Single = 32.0F
    Private Const GuidedMatrixOuterChromeHeightDip As Single = 18.0F
    Private Const GuidedMatrixMaximumVisibleRows As Integer = 8

    Private Function MatrixSizeForRows(rowCount As Integer,
                                       Optional maximumVisibleRows As Integer = GuidedMatrixMaximumVisibleRows) As MASSize
        Dim safeRows As Integer = Math.Max(0, rowCount)
        Dim safeMaximum As Integer = Math.Max(0, maximumVisibleRows)
        Dim visibleRows As Integer = Math.Min(safeRows, safeMaximum)
        Dim heightDip As Single = GuidedMatrixHeaderHeightDip + (CSng(visibleRows) * GuidedMatrixRowHeightDip) + GuidedMatrixOuterChromeHeightDip
        Return MASSize.FillWidth.OffsetHeight(heightDip)
    End Function





    Private Sub RegisterGuidedStageControl(page As MASApplicationLayoutPageBuilder,
                                           controls As List(Of MASControlBase),
                                           control As MASControlBase,
                                           Optional sizeIntent As MASSize = Nothing)
        RegisterSmartGuidedStageControl(page, controls, control, sizeIntent)
    End Sub




    Private Sub RegisterGuidedStageCompactRow(page As MASApplicationLayoutPageBuilder,
                                              controls As List(Of MASControlBase),
                                              items As MASControlBase(),
                                              Optional itemSize As MASSize = Nothing)
        If page Is Nothing OrElse controls Is Nothing OrElse items Is Nothing Then Return
        FlushGuidedStageInlineRow(page)

        Dim resolvedItemSize As MASSize = If(itemSize, MASSize.[Default])

        If IsGuidedActionRow(items) Then
            Dim actions As MASApplicationActionGroupLayoutBuilder = page.ActionGroup().AlignStart().IntrinsicItemSize().Gap(MASLayoutSpacing.Small)
            For Each item As MASControlBase In items
                If item Is Nothing Then Continue For
                item.WithSize(resolvedItemSize)
                controls.Add(item)
                actions.Add(item, resolvedItemSize)
            Next
            Return
        End If

        Dim flow As MASApplicationLayoutFlowBuilder = page.Flow().Gap(MASLayoutSpacing.Small).IntrinsicItemSize()
        For Each item As MASControlBase In items
            If item Is Nothing Then Continue For
            item.WithSize(resolvedItemSize)
            controls.Add(item)
            flow.Add(item, resolvedItemSize)
        Next
    End Sub

    Private Function IsGuidedActionRow(items As MASControlBase()) As Boolean
        If items Is Nothing OrElse items.Length = 0 Then Return False

        Dim visibleActionCount As Integer = 0
        For Each item As MASControlBase In items
            If item Is Nothing Then Continue For
            If Not (TypeOf item Is MASButton OrElse TypeOf item Is MASSplitButton) Then Return False
            visibleActionCount += 1
        Next

        Return visibleActionCount > 0
    End Function

    Private Sub RegisterGuidedStageSurfaceGrid(page As MASApplicationLayoutPageBuilder,
                                               controls As List(Of MASControlBase),
                                               columns As Integer,
                                               items As MASControlBase())
        If page Is Nothing OrElse controls Is Nothing OrElse items Is Nothing Then Return
        FlushGuidedStageInlineRow(page)
        Dim grid As MASApplicationLayoutGridBuilder = page.Grid(Math.Max(1, columns)).Gap(MASLayoutSpacing.Medium).EqualItemSize()
        For Each item As MASControlBase In items
            If item Is Nothing Then Continue For
            controls.Add(item)
            grid.Add(item, MASSize.FillWidth)
        Next
    End Sub
End Class
