using UnityEngine;
using UnityEngine.UI;
using EventsAppQuest.Core;
using EventsAppQuest.Domain.Enums;

namespace EventsAppQuest.Presentation
{
    /// <summary>
    /// Posiciona e preenche os painéis principais da UI espacial (World Space) da apresentação Quest.
    /// Regras simples: painel principal à frente, lateral e progresso organizados; dados reais da sessão.
    /// </summary>
    public class QuestWorldUIPanelLayout : MonoBehaviour
    {
        [Tooltip("Distância dos painéis em relação ao rig (metros).")]
        [SerializeField] private float _distanceInFront = 2f;

        [Tooltip("Escala do Canvas World Space (ex.: 0.002 = 500px ≈ 1m).")]
        [SerializeField] private float _canvasScale = 0.002f;

        private Transform _rig;
        private Transform _anchor;
        private Canvas _canvas;
        private Text _mainTitleText;
        private Text _mainContentText;
        private Text _lateralLabelText;
        private Text _lateralContentText;
        private Text _progressText;
        private Text _modeReadinessText;
        private Text _focusIndicatorText;
        private Text _selectionIndicatorText;
        private Text _pointerModeIndicatorText;
        private GameObject _hotspotContextPanelGo;
        private Text _hotspotContextTitleText;
        private Text _hotspotContextSummaryText;
        private Text _hotspotContextSalesText;
        private Text _hotspotContextPremiumText;
        private Text _hotspotContextProgressText;
        private Button _hotspotContextCloseButton;
        private GameObject _hotspotStoryButtonsRowGo;
        private Button _hotspotStartStoryButton;
        private Button _hotspotPrevStoryButton;
        private Button _hotspotNextStoryButton;
        private Button _hotspotCloseStoryButton;
        private Button _hotspotCompareButton;
        private GameObject _hotspotComparisonPanelGo;
        private Text _comparisonLeftTitleText;
        private Text _comparisonLeftSalesText;
        private Text _comparisonRightTitleText;
        private Text _comparisonRightSalesText;
        private Text _comparisonBetterExpText;
        private Text _comparisonBetterUpsellText;
        private Text _comparisonBetterClarityText;
        private Text _comparisonSummaryText;
        private Button _comparisonSwapButton;
        private Button _comparisonCloseButton;
        private GameObject _closingPanelGo;
        private Text _closingHeadlineText;
        private Text _closingSummaryText;
        private Text _closingConfidenceText;
        private Text _closingNextActionText;
        private Text _closingConclusionsText;
        private Button _closingPrimaryCTAButton;
        private Button _closingSecondaryCTAButton;
        private Button _closingCloseButton;
        private GameObject _outcomePanelGo;
        private Text _outcomeHeadlineText;
        private Text _outcomeDecisionText;
        private Text _outcomeNextActionText;
        private Text _outcomePriorityText;
        private Button _outcomeNeedsFollowUpButton;
        private Button _outcomeReadyToAdvanceButton;
        private Button _outcomeBackToClosingButton;
        private Button _outcomeConfirmFinalButton;
        private GameObject _exportPanelGo;
        private Text _exportHeadlineText;
        private Text _exportIdsText;
        private Text _exportDecisionText;
        private Text _exportCTAText;
        private Text _exportNextActionText;
        private Text _exportPriorityText;
        private Text _exportStatsText;
        private Button _exportGenerateButton;
        private Button _exportRegenerateButton;
        private Button _exportClearButton;
        private Button _exportBackButton;
        private GameObject _persistencePanelGo;
        private Text _persistenceHeadlineText;
        private Text _persistenceStatusText;
        private Button _persistenceSaveButton;
        private Button _persistenceRestoreButton;
        private Button _persistenceClearButton;
        private GameObject _handoffPanelGo;
        private Text _handoffHeadlineText;
        private Text _handoffProposalText;
        private Text _handoffDecisionText;
        private Text _handoffCTAText;
        private Text _handoffNextActionText;
        private Text _handoffPriorityText;
        private Text _handoffHotspotsText;
        private Text _handoffComparisonsText;
        private Text _handoffConfidenceText;
        private Text _handoffNotesText;
        private Button _handoffGenerateButton;
        private Button _handoffRegenerateButton;
        private Button _handoffClearButton;
        private Button _handoffBackButton;
        private GameObject _shareablePanelGo;
        private Text _shareableHeadlineText;
        private Text _shareableTitleText;
        private Text _shareableExecutiveText;
        private Text _shareableDecisionText;
        private Text _shareableCTAText;
        private Text _shareableNextActionText;
        private Text _shareablePriorityText;
        private Text _shareableHighlightsText;
        private Text _shareableRisksText;
        private Text _shareableBodyText;
        private Button _shareableGenerateButton;
        private Button _shareableRegenerateButton;
        private Button _shareableClearButton;
        private Button _shareableCopyButton;
        private GameObject _qualityPanelGo;
        private Text _qualityHeadlineText;
        private Text _qualityScoreText;
        private Text _qualitySubScoresText;
        private Text _qualityLabelText;
        private Text _qualityStrengthsText;
        private Text _qualityWeaknessesText;
        private Text _qualitySuggestionsText;
        private Button _qualityCalculateButton;
        private Button _qualityRecalculateButton;
        private Button _qualityClearButton;
        private Button _qualityBackButton;
        private GameObject _improvementPlanPanelGo;
        private Text _improvementHeadlineText;
        private Text _improvementSummaryText;
        private Text _improvementRecommendationsText;
        private Text _improvementTopPriorityText;
        private Text _improvementTopCategoryText;
        private Button _improvementGenerateButton;
        private Button _improvementRegenerateButton;
        private Button _improvementClearButton;
        private Button _improvementBackButton;
        private GameObject _presetPanelGo;
        private Text _presetHeadlineText;
        private Text _presetCurrentText;
        private Text _presetDurationText;
        private Text _presetFocusText;
        private Button _presetQuickPitchButton;
        private Button _presetGuidedSalesButton;
        private Button _presetPremiumShowcaseButton;
        private Button _presetComparisonModeButton;
        private Button _presetExecutiveReviewButton;
        private Button _presetClearButton;
        private GameObject _onboardingPanelGo;
        private Text _onboardingTitleText;
        private Text _onboardingProposalText;
        private Text _onboardingPresetText;
        private Text _onboardingRuntimeText;
        private Text _onboardingGoalText;
        private Text _onboardingHintsText;
        private Text _onboardingDurationText;
        private Button _onboardingStartButton;
        private Button _onboardingCloseButton;
        private GameObject _mainPanelGo;

        /// <summary>Invocado quando o utilizador pede para fechar o contexto do hotspot (botão Fechar).</summary>
        public System.Action OnCloseHotspotContextRequested;
        /// <summary>Iniciar micro-roteiro narrativo do hotspot.</summary>
        public System.Action OnStartHotspotStoryRequested;
        /// <summary>Passo anterior do micro-roteiro.</summary>
        public System.Action OnPreviousStoryStepRequested;
        /// <summary>Próximo passo do micro-roteiro.</summary>
        public System.Action OnNextStoryStepRequested;
        /// <summary>Fechar narrativa (voltar ao contexto simples).</summary>
        public System.Action OnCloseHotspotStoryRequested;
        /// <summary>Abrir comparação entre hotspots a partir do contexto actual.</summary>
        public System.Action OnOpenComparisonRequested;
        /// <summary>Trocar lados na comparação.</summary>
        public System.Action OnSwapComparisonRequested;
        /// <summary>Fechar comparação.</summary>
        public System.Action OnCloseComparisonRequested;
        /// <summary>Abrir fechamento imersivo.</summary>
        public System.Action OnOpenClosingRequested;
        /// <summary>Fechar painel de fechamento.</summary>
        public System.Action OnCloseClosingRequested;
        /// <summary>Confirmar CTA principal.</summary>
        public System.Action OnConfirmPrimaryCTARequested;
        /// <summary>Confirmar CTA secundário.</summary>
        public System.Action OnConfirmSecondaryCTARequested;
        /// <summary>Marcar resultado como precisa follow-up.</summary>
        public System.Action OnMarkNeedsFollowUpRequested;
        /// <summary>Marcar resultado como pronta para avançar.</summary>
        public System.Action OnMarkReadyToAdvanceRequested;
        /// <summary>Voltar ao painel de fechamento.</summary>
        public System.Action OnBackToClosingRequested;
        /// <summary>Confirmar decisão final (pronta para fechar).</summary>
        public System.Action OnConfirmFinalDecisionRequested;
        /// <summary>Gerar payload de exportação.</summary>
        public System.Action OnGenerateExportRequested;
        /// <summary>Regenerar payload de exportação.</summary>
        public System.Action OnRegenerateExportRequested;
        /// <summary>Limpar payload actual.</summary>
        public System.Action OnClearExportRequested;
        /// <summary>Voltar ao resultado/outcome (fechar inspeção do payload).</summary>
        public System.Action OnBackToOutcomeRequested;
        /// <summary>Salvar sessão localmente.</summary>
        public System.Action OnSaveSessionRequested;
        /// <summary>Restaurar sessão a partir do snapshot salvo.</summary>
        public System.Action OnRestoreSessionRequested;
        /// <summary>Limpar snapshot salvo.</summary>
        public System.Action OnClearSavedSessionRequested;
        /// <summary>Gerar relatório final/handoff da sessão.</summary>
        public System.Action OnGenerateHandoffRequested;
        /// <summary>Regenerar relatório final/handoff da sessão.</summary>
        public System.Action OnRegenerateHandoffRequested;
        /// <summary>Limpar relatório final/handoff.</summary>
        public System.Action OnClearHandoffRequested;
        /// <summary>Fechar painel de relatório (voltar ao estado anterior).</summary>
        public System.Action OnBackFromHandoffRequested;
        /// <summary>Gerar resumo compartilhável da sessão.</summary>
        public System.Action OnGenerateShareableRequested;
        /// <summary>Regenerar resumo compartilhável da sessão.</summary>
        public System.Action OnRegenerateShareableRequested;
        /// <summary>Limpar resumo compartilhável.</summary>
        public System.Action OnClearShareableRequested;
        /// <summary>Copiar texto compartilhável para clipboard (quando suportado).</summary>
        public System.Action OnCopyShareableRequested;
        /// <summary>Calcular diagnóstico de qualidade da sessão.</summary>
        public System.Action OnCalculateQualityRequested;
        /// <summary>Recalcular diagnóstico de qualidade.</summary>
        public System.Action OnRecalculateQualityRequested;
        /// <summary>Limpar diagnóstico de qualidade.</summary>
        public System.Action OnClearQualityRequested;
        /// <summary>Voltar (fechar painel de qualidade).</summary>
        public System.Action OnBackFromQualityRequested;
        /// <summary>Gerar plano de melhorias.</summary>
        public System.Action OnGenerateImprovementPlanRequested;
        /// <summary>Regenerar plano de melhorias.</summary>
        public System.Action OnRegenerateImprovementPlanRequested;
        /// <summary>Limpar plano de melhorias.</summary>
        public System.Action OnClearImprovementPlanRequested;
        /// <summary>Voltar (fechar painel de melhorias).</summary>
        public System.Action OnBackFromImprovementPlanRequested;
        /// <summary>Aplicar preset por id (ex.: QuickPitch, GuidedSales).</summary>
        public System.Action<string> OnApplyPresetRequested;
        /// <summary>Limpar preset aplicado.</summary>
        public System.Action OnClearPresetRequested;
        /// <summary>Iniciar apresentação (fechar onboarding e marcar como visto).</summary>
        public System.Action OnStartPresentationRequested;
        /// <summary>Fechar onboarding.</summary>
        public System.Action OnCloseOnboardingRequested;
        private GameObject _lateralPanelGo;
        private GameObject _progressPanelGo;
        private Color _mainPanelColor = new Color(0.12f, 0.18f, 0.24f, 0.92f);
        private Color _lateralPanelColor = new Color(0.18f, 0.14f, 0.22f, 0.9f);
        private Color _progressPanelColor = new Color(0.1f, 0.14f, 0.18f, 0.88f);
        private readonly Color _focusTint = new Color(0.15f, 0.22f, 0.32f, 0.95f);
        private readonly Color _selectionTint = new Color(0.18f, 0.32f, 0.22f, 0.95f);
        private const float FocusScale = 1.03f;
        private const float SelectionScale = 1.04f;
        private const float PointedScale = 1.02f;
        private readonly Color _pointedTint = new Color(0.32f, 0.28f, 0.12f, 0.92f);
        private readonly Color _xrRaycastTint = new Color(0.38f, 0.28f, 0.08f, 0.95f);
        private const float XRRaycastScale = 1.025f;
        private Font _font;
        private bool _built;
        private Transform _worldCanvasTransform;

        private const string ModoGuiado = "Guiado";
        private const string ModoManual = "Manual";
        private const string ModoHotspot = "Foco hotspot";

        /// <summary>Constrói a UI espacial: canvas World Space e painéis (principal, lateral, progresso).</summary>
        public void Build(Transform cameraRig, Font font)
        {
            if (cameraRig == null || font == null) return;
            _rig = cameraRig;
            _font = font;

            var root = new GameObject("QuestWorldUI");
            root.transform.SetParent(transform);

            _anchor = new GameObject("WorldUIAnchor").transform;
            _anchor.SetParent(root.transform, false);

            var canvasGo = new GameObject("WorldCanvas");
            canvasGo.transform.SetParent(_anchor, false);
            var canvasRt = canvasGo.AddComponent<RectTransform>();
            canvasRt.sizeDelta = new Vector2(1000f, 600f);
            canvasRt.localScale = Vector3.one * _canvasScale;
            canvasRt.localPosition = Vector3.zero;
            canvasRt.localRotation = Quaternion.identity;

            _canvas = canvasGo.AddComponent<Canvas>();
            _canvas.renderMode = RenderMode.WorldSpace;
            canvasGo.AddComponent<CanvasScaler>().dynamicPixelsPerUnit = 100f;
            canvasGo.AddComponent<GraphicRaycaster>();
            _worldCanvasTransform = canvasGo.transform;

            _mainPanelGo = CreatePanel(canvasGo.transform, "MainPanel", new Vector2(0f, 80f), new Vector2(600f, 180f), _mainPanelColor);
            AddRaycastTargetToPanel(_mainPanelGo, "guided_step", QuestPointableTargetType.Panel, new Vector2(600f, 180f));
            _mainTitleText = AddLabel(_mainPanelGo.transform, "—", 36, true);
            _mainContentText = AddLabel(_mainPanelGo.transform, "—", 28, false);

            _lateralPanelGo = CreatePanel(canvasGo.transform, "LateralPanel", new Vector2(380f, 20f), new Vector2(280f, 120f), _lateralPanelColor);
            AddRaycastTargetToPanel(_lateralPanelGo, "hotspot", QuestPointableTargetType.HotspotMarker, new Vector2(280f, 120f));
            var lateralPanel = _lateralPanelGo;
            var lateralVlg = lateralPanel.AddComponent<VerticalLayoutGroup>();
            lateralVlg.spacing = 6;
            lateralVlg.padding = new RectOffset(14, 12, 14, 12);
            lateralVlg.childForceExpandHeight = false;
            _lateralLabelText = AddLabel(lateralPanel.transform, "Hotspot", 22, true);
            _lateralLabelText.gameObject.AddComponent<LayoutElement>().preferredHeight = 28f;
            _lateralContentText = AddLabel(lateralPanel.transform, "—", 24, false);
            _lateralContentText.gameObject.AddComponent<LayoutElement>().preferredHeight = 36f;

            _progressPanelGo = CreatePanel(canvasGo.transform, "ProgressPanel", new Vector2(0f, -220f), new Vector2(700f, 70f), _progressPanelColor);
            AddRaycastTargetToPanel(_progressPanelGo, "action_next", QuestPointableTargetType.ActionTarget, new Vector2(700f, 70f));
            _progressText = AddLabel(_progressPanelGo.transform, "—", 26, true);
            _modeReadinessText = AddLabel(_progressPanelGo.transform, "Modo: —  |  Pronto: —", 20, false);

            var focusIndicatorGo = new GameObject("FocusIndicator");
            focusIndicatorGo.transform.SetParent(canvasGo.transform, false);
            var focusRt = focusIndicatorGo.AddComponent<RectTransform>();
            focusRt.anchorMin = new Vector2(0.5f, 0.5f);
            focusRt.anchorMax = new Vector2(0.5f, 0.5f);
            focusRt.pivot = new Vector2(0.5f, 0.5f);
            focusRt.anchoredPosition = new Vector2(0f, -280f);
            focusRt.sizeDelta = new Vector2(800f, 32f);
            _focusIndicatorText = AddLabel(focusIndicatorGo.transform, "", 18, false);
            _focusIndicatorText.alignment = TextAnchor.MiddleCenter;

            var selectionIndicatorGo = new GameObject("SelectionIndicator");
            selectionIndicatorGo.transform.SetParent(canvasGo.transform, false);
            var selRt = selectionIndicatorGo.AddComponent<RectTransform>();
            selRt.anchorMin = new Vector2(0.5f, 0.5f);
            selRt.anchorMax = new Vector2(0.5f, 0.5f);
            selRt.pivot = new Vector2(0.5f, 0.5f);
            selRt.anchoredPosition = new Vector2(0f, -318f);
            selRt.sizeDelta = new Vector2(800f, 28f);
            _selectionIndicatorText = AddLabel(selectionIndicatorGo.transform, "", 16, false);
            _selectionIndicatorText.alignment = TextAnchor.MiddleCenter;
            _selectionIndicatorText.color = new Color(0.5f, 0.9f, 0.6f, 1f);

            var pointerModeGo = new GameObject("PointerModeIndicator");
            pointerModeGo.transform.SetParent(canvasGo.transform, false);
            var pmRt = pointerModeGo.AddComponent<RectTransform>();
            pmRt.anchorMin = new Vector2(0.5f, 0.5f);
            pmRt.anchorMax = new Vector2(0.5f, 0.5f);
            pmRt.pivot = new Vector2(0.5f, 0.5f);
            pmRt.anchoredPosition = new Vector2(0f, -352f);
            pmRt.sizeDelta = new Vector2(800f, 22f);
            _pointerModeIndicatorText = AddLabel(pointerModeGo.transform, "", 14, false);
            _pointerModeIndicatorText.alignment = TextAnchor.MiddleCenter;
            _pointerModeIndicatorText.color = new Color(0.9f, 0.75f, 0.35f, 1f);

            var ctxPanelColor = new Color(0.16f, 0.12f, 0.2f, 0.95f);
            _hotspotContextPanelGo = CreatePanel(canvasGo.transform, "HotspotContextPanel", new Vector2(420f, 0f), new Vector2(300f, 270f), ctxPanelColor);
            _hotspotContextPanelGo.SetActive(false);
            var ctxVlg = _hotspotContextPanelGo.AddComponent<VerticalLayoutGroup>();
            ctxVlg.spacing = 6;
            ctxVlg.padding = new RectOffset(14, 12, 14, 12);
            ctxVlg.childForceExpandHeight = false;
            _hotspotContextTitleText = AddLabel(_hotspotContextPanelGo.transform, "—", 20, true);
            _hotspotContextTitleText.gameObject.AddComponent<LayoutElement>().preferredHeight = 28f;
            _hotspotContextSummaryText = AddLabel(_hotspotContextPanelGo.transform, "—", 16, false);
            _hotspotContextSummaryText.gameObject.AddComponent<LayoutElement>().preferredHeight = 48f;
            _hotspotContextSalesText = AddLabel(_hotspotContextPanelGo.transform, "—", 14, false);
            _hotspotContextSalesText.color = new Color(0.85f, 0.8f, 0.9f, 1f);
            _hotspotContextSalesText.gameObject.AddComponent<LayoutElement>().preferredHeight = 36f;
            _hotspotContextPremiumText = AddLabel(_hotspotContextPanelGo.transform, "", 12, false);
            _hotspotContextPremiumText.color = new Color(0.95f, 0.75f, 0.3f, 1f);
            _hotspotContextPremiumText.gameObject.AddComponent<LayoutElement>().preferredHeight = 20f;
            _hotspotContextProgressText = AddLabel(_hotspotContextPanelGo.transform, "", 12, false);
            _hotspotContextProgressText.color = new Color(0.7f, 0.75f, 0.85f, 1f);
            _hotspotContextProgressText.gameObject.AddComponent<LayoutElement>().preferredHeight = 18f;
            _hotspotStoryButtonsRowGo = new GameObject("HotspotStoryButtonsRow");
            _hotspotStoryButtonsRowGo.transform.SetParent(_hotspotContextPanelGo.transform, false);
            _hotspotStoryButtonsRowGo.AddComponent<LayoutElement>().preferredHeight = 32f;
            var storyRowHlg = _hotspotStoryButtonsRowGo.AddComponent<HorizontalLayoutGroup>();
            storyRowHlg.spacing = 6;
            storyRowHlg.childForceExpandWidth = true;
            storyRowHlg.childControlWidth = true;
            _hotspotStartStoryButton = AddSmallButton(_hotspotStoryButtonsRowGo.transform, "Iniciar micro-roteiro", () => OnStartHotspotStoryRequested?.Invoke());
            _hotspotPrevStoryButton = AddSmallButton(_hotspotStoryButtonsRowGo.transform, "Ant.", () => OnPreviousStoryStepRequested?.Invoke());
            _hotspotNextStoryButton = AddSmallButton(_hotspotStoryButtonsRowGo.transform, "Próx.", () => OnNextStoryStepRequested?.Invoke());
            _hotspotCloseStoryButton = AddSmallButton(_hotspotStoryButtonsRowGo.transform, "Fechar roteiro", () => OnCloseHotspotStoryRequested?.Invoke());
            _hotspotCompareButton = AddSmallButton(_hotspotStoryButtonsRowGo.transform, "Comparar", () => OnOpenComparisonRequested?.Invoke());
            var closeBtnGo = new GameObject("CloseContextButton");
            closeBtnGo.transform.SetParent(_hotspotContextPanelGo.transform, false);
            closeBtnGo.AddComponent<LayoutElement>().preferredHeight = 36f;
            var closeBtnRt = closeBtnGo.AddComponent<RectTransform>();
            closeBtnRt.sizeDelta = new Vector2(0, 36f);
            var closeBtnImg = closeBtnGo.AddComponent<Image>();
            closeBtnImg.color = new Color(0.35f, 0.22f, 0.4f, 1f);
            _hotspotContextCloseButton = closeBtnGo.AddComponent<Button>();
            _hotspotContextCloseButton.targetGraphic = closeBtnImg;
            _hotspotContextCloseButton.onClick.AddListener(() => OnCloseHotspotContextRequested?.Invoke());
            var closeBtnLabel = AddLabel(closeBtnGo.transform, "Fechar", 16, false);
            closeBtnLabel.alignment = TextAnchor.MiddleCenter;
            closeBtnLabel.raycastTarget = false;

            var compPanelColor = new Color(0.14f, 0.1f, 0.18f, 0.96f);
            _hotspotComparisonPanelGo = CreatePanel(canvasGo.transform, "HotspotComparisonPanel", new Vector2(420f, 0f), new Vector2(340f, 300f), compPanelColor);
            _hotspotComparisonPanelGo.SetActive(false);
            var compVlg = _hotspotComparisonPanelGo.AddComponent<VerticalLayoutGroup>();
            compVlg.spacing = 8;
            compVlg.padding = new RectOffset(12, 12, 12, 12);
            compVlg.childForceExpandHeight = false;
            var compColumnsGo = new GameObject("ComparisonColumns");
            compColumnsGo.transform.SetParent(_hotspotComparisonPanelGo.transform, false);
            compColumnsGo.AddComponent<LayoutElement>().preferredHeight = 100f;
            var compHlg = compColumnsGo.AddComponent<HorizontalLayoutGroup>();
            compHlg.spacing = 12;
            compHlg.childForceExpandWidth = true;
            compHlg.childControlWidth = true;
            var leftCol = new GameObject("LeftColumn");
            leftCol.transform.SetParent(compColumnsGo.transform, false);
            leftCol.AddComponent<LayoutElement>().flexWidth = 1f;
            var leftVlg = leftCol.AddComponent<VerticalLayoutGroup>();
            leftVlg.spacing = 4;
            leftVlg.childForceExpandHeight = false;
            _comparisonLeftTitleText = AddLabel(leftCol.transform, "—", 18, true);
            _comparisonLeftTitleText.gameObject.AddComponent<LayoutElement>().preferredHeight = 24f;
            _comparisonLeftSalesText = AddLabel(leftCol.transform, "—", 12, false);
            _comparisonLeftSalesText.color = new Color(0.82f, 0.78f, 0.9f, 1f);
            _comparisonLeftSalesText.gameObject.AddComponent<LayoutElement>().flexHeight = 1f;
            var rightCol = new GameObject("RightColumn");
            rightCol.transform.SetParent(compColumnsGo.transform, false);
            rightCol.AddComponent<LayoutElement>().flexWidth = 1f;
            var rightVlg = rightCol.AddComponent<VerticalLayoutGroup>();
            rightVlg.spacing = 4;
            rightVlg.childForceExpandHeight = false;
            _comparisonRightTitleText = AddLabel(rightCol.transform, "—", 18, true);
            _comparisonRightTitleText.gameObject.AddComponent<LayoutElement>().preferredHeight = 24f;
            _comparisonRightSalesText = AddLabel(rightCol.transform, "—", 12, false);
            _comparisonRightSalesText.color = new Color(0.82f, 0.78f, 0.9f, 1f);
            _comparisonRightSalesText.gameObject.AddComponent<LayoutElement>().flexHeight = 1f;
            _comparisonBetterExpText = AddLabel(_hotspotComparisonPanelGo.transform, "", 11, false);
            _comparisonBetterExpText.color = new Color(0.75f, 0.85f, 0.9f, 1f);
            _comparisonBetterExpText.gameObject.AddComponent<LayoutElement>().preferredHeight = 16f;
            _comparisonBetterUpsellText = AddLabel(_hotspotComparisonPanelGo.transform, "", 11, false);
            _comparisonBetterUpsellText.color = new Color(0.95f, 0.8f, 0.4f, 1f);
            _comparisonBetterUpsellText.gameObject.AddComponent<LayoutElement>().preferredHeight = 16f;
            _comparisonBetterClarityText = AddLabel(_hotspotComparisonPanelGo.transform, "", 11, false);
            _comparisonBetterClarityText.color = new Color(0.8f, 0.85f, 0.8f, 1f);
            _comparisonBetterClarityText.gameObject.AddComponent<LayoutElement>().preferredHeight = 16f;
            _comparisonSummaryText = AddLabel(_hotspotComparisonPanelGo.transform, "—", 12, false);
            _comparisonSummaryText.gameObject.AddComponent<LayoutElement>().preferredHeight = 40f;
            _comparisonSummaryText.color = new Color(0.88f, 0.86f, 0.92f, 1f);
            var compBtnRow = new GameObject("ComparisonButtonsRow");
            compBtnRow.transform.SetParent(_hotspotComparisonPanelGo.transform, false);
            compBtnRow.AddComponent<LayoutElement>().preferredHeight = 32f;
            var compBtnHlg = compBtnRow.AddComponent<HorizontalLayoutGroup>();
            compBtnHlg.spacing = 8;
            compBtnHlg.childForceExpandWidth = true;
            _comparisonSwapButton = AddSmallButton(compBtnRow.transform, "Trocar lados", () => OnSwapComparisonRequested?.Invoke());
            _comparisonCloseButton = AddSmallButton(compBtnRow.transform, "Fechar comparação", () => OnCloseComparisonRequested?.Invoke());

            var closingPanelColor = new Color(0.1f, 0.18f, 0.14f, 0.96f);
            _closingPanelGo = CreatePanel(canvasGo.transform, "ClosingPanel", new Vector2(420f, 0f), new Vector2(340f, 380f), closingPanelColor);
            _closingPanelGo.SetActive(false);
            var closingVlg = _closingPanelGo.AddComponent<VerticalLayoutGroup>();
            closingVlg.spacing = 8;
            closingVlg.padding = new RectOffset(14, 12, 14, 12);
            closingVlg.childForceExpandHeight = false;
            _closingHeadlineText = AddLabel(_closingPanelGo.transform, "—", 22, true);
            _closingHeadlineText.color = new Color(0.9f, 0.92f, 0.88f, 1f);
            _closingHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 28f;
            _closingSummaryText = AddLabel(_closingPanelGo.transform, "—", 14, false);
            _closingSummaryText.color = new Color(0.85f, 0.88f, 0.9f, 1f);
            _closingSummaryText.gameObject.AddComponent<LayoutElement>().preferredHeight = 48f;
            _closingConfidenceText = AddLabel(_closingPanelGo.transform, "", 12, false);
            _closingConfidenceText.color = new Color(0.7f, 0.9f, 0.75f, 1f);
            _closingConfidenceText.gameObject.AddComponent<LayoutElement>().preferredHeight = 18f;
            _closingNextActionText = AddLabel(_closingPanelGo.transform, "", 12, false);
            _closingNextActionText.color = new Color(0.75f, 0.85f, 0.9f, 1f);
            _closingNextActionText.gameObject.AddComponent<LayoutElement>().preferredHeight = 20f;
            _closingConclusionsText = AddLabel(_closingPanelGo.transform, "", 11, false);
            _closingConclusionsText.color = new Color(0.72f, 0.8f, 0.78f, 1f);
            _closingConclusionsText.gameObject.AddComponent<LayoutElement>().preferredHeight = 42f;
            var closingCtaRow = new GameObject("ClosingCTARow");
            closingCtaRow.transform.SetParent(_closingPanelGo.transform, false);
            closingCtaRow.AddComponent<LayoutElement>().preferredHeight = 32f;
            var closingCtaHlg = closingCtaRow.AddComponent<HorizontalLayoutGroup>();
            closingCtaHlg.spacing = 8;
            closingCtaHlg.childForceExpandWidth = true;
            _closingPrimaryCTAButton = AddSmallButton(closingCtaRow.transform, "Fechar proposta", () => OnConfirmPrimaryCTARequested?.Invoke());
            _closingSecondaryCTAButton = AddSmallButton(closingCtaRow.transform, "Ver alternativas", () => OnConfirmSecondaryCTARequested?.Invoke());
            var closingCloseBtnGo = new GameObject("CloseClosingButton");
            closingCloseBtnGo.transform.SetParent(_closingPanelGo.transform, false);
            closingCloseBtnGo.AddComponent<LayoutElement>().preferredHeight = 34f;
            var closeClosingImg = closingCloseBtnGo.AddComponent<Image>();
            closeClosingImg.color = new Color(0.25f, 0.35f, 0.28f, 1f);
            _closingCloseButton = closingCloseBtnGo.AddComponent<Button>();
            _closingCloseButton.targetGraphic = closeClosingImg;
            _closingCloseButton.onClick.AddListener(() => OnCloseClosingRequested?.Invoke());
            var closeClosingLabel = AddLabel(closingCloseBtnGo.transform, "Voltar", 14, false);
            closeClosingLabel.alignment = TextAnchor.MiddleCenter;
            closeClosingLabel.raycastTarget = false;

            var outcomePanelColor = new Color(0.12f, 0.2f, 0.18f, 0.96f);
            _outcomePanelGo = CreatePanel(canvasGo.transform, "OutcomePanel", new Vector2(420f, -210f), new Vector2(340f, 320f), outcomePanelColor);
            _outcomePanelGo.SetActive(false);
            var outcomeVlg = _outcomePanelGo.AddComponent<VerticalLayoutGroup>();
            outcomeVlg.spacing = 6;
            outcomeVlg.padding = new RectOffset(14, 12, 14, 12);
            outcomeVlg.childForceExpandHeight = false;
            _outcomeHeadlineText = AddLabel(_outcomePanelGo.transform, "Resultado da apresentação", 20, true);
            _outcomeHeadlineText.color = new Color(0.9f, 0.92f, 0.88f, 1f);
            _outcomeHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 24f;
            _outcomeDecisionText = AddLabel(_outcomePanelGo.transform, "—", 14, false);
            _outcomeDecisionText.color = new Color(0.85f, 0.88f, 0.9f, 1f);
            _outcomeDecisionText.gameObject.AddComponent<LayoutElement>().preferredHeight = 22f;
            _outcomeNextActionText = AddLabel(_outcomePanelGo.transform, "—", 12, false);
            _outcomeNextActionText.color = new Color(0.75f, 0.85f, 0.9f, 1f);
            _outcomeNextActionText.gameObject.AddComponent<LayoutElement>().preferredHeight = 20f;
            _outcomePriorityText = AddLabel(_outcomePanelGo.transform, "—", 12, false);
            _outcomePriorityText.color = new Color(0.7f, 0.9f, 0.75f, 1f);
            _outcomePriorityText.gameObject.AddComponent<LayoutElement>().preferredHeight = 18f;
            var outcomeBtnRow1 = new GameObject("OutcomeBtnRow1");
            outcomeBtnRow1.transform.SetParent(_outcomePanelGo.transform, false);
            outcomeBtnRow1.AddComponent<LayoutElement>().preferredHeight = 30f;
            var outcomeHlg1 = outcomeBtnRow1.AddComponent<HorizontalLayoutGroup>();
            outcomeHlg1.spacing = 6;
            outcomeHlg1.childForceExpandWidth = true;
            _outcomeNeedsFollowUpButton = AddSmallButton(outcomeBtnRow1.transform, "Precisa follow-up", () => OnMarkNeedsFollowUpRequested?.Invoke());
            _outcomeReadyToAdvanceButton = AddSmallButton(outcomeBtnRow1.transform, "Pronta para avançar", () => OnMarkReadyToAdvanceRequested?.Invoke());
            var outcomeBtnRow2 = new GameObject("OutcomeBtnRow2");
            outcomeBtnRow2.transform.SetParent(_outcomePanelGo.transform, false);
            outcomeBtnRow2.AddComponent<LayoutElement>().preferredHeight = 30f;
            var outcomeHlg2 = outcomeBtnRow2.AddComponent<HorizontalLayoutGroup>();
            outcomeHlg2.spacing = 6;
            outcomeHlg2.childForceExpandWidth = true;
            _outcomeBackToClosingButton = AddSmallButton(outcomeBtnRow2.transform, "Voltar ao fechamento", () => OnBackToClosingRequested?.Invoke());
            _outcomeConfirmFinalButton = AddSmallButton(outcomeBtnRow2.transform, "Confirmar decisão final", () => OnConfirmFinalDecisionRequested?.Invoke());

            var exportPanelColor = new Color(0.1f, 0.16f, 0.2f, 0.96f);
            _exportPanelGo = CreatePanel(canvasGo.transform, "ExportPanel", new Vector2(420f, -550f), new Vector2(340f, 360f), exportPanelColor);
            _exportPanelGo.SetActive(false);
            var exportVlg = _exportPanelGo.AddComponent<VerticalLayoutGroup>();
            exportVlg.spacing = 5;
            exportVlg.padding = new RectOffset(14, 12, 14, 12);
            exportVlg.childForceExpandHeight = false;
            _exportHeadlineText = AddLabel(_exportPanelGo.transform, "Payload de exportação", 18, true);
            _exportHeadlineText.color = new Color(0.9f, 0.92f, 0.88f, 1f);
            _exportHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 22f;
            _exportIdsText = AddLabel(_exportPanelGo.transform, "—", 11, false);
            _exportIdsText.color = new Color(0.75f, 0.82f, 0.88f, 1f);
            _exportIdsText.gameObject.AddComponent<LayoutElement>().preferredHeight = 16f;
            _exportDecisionText = AddLabel(_exportPanelGo.transform, "—", 12, false);
            _exportDecisionText.color = new Color(0.85f, 0.88f, 0.9f, 1f);
            _exportDecisionText.gameObject.AddComponent<LayoutElement>().preferredHeight = 18f;
            _exportCTAText = AddLabel(_exportPanelGo.transform, "—", 11, false);
            _exportCTAText.color = new Color(0.7f, 0.85f, 0.9f, 1f);
            _exportCTAText.gameObject.AddComponent<LayoutElement>().preferredHeight = 14f;
            _exportNextActionText = AddLabel(_exportPanelGo.transform, "—", 11, false);
            _exportNextActionText.color = new Color(0.7f, 0.85f, 0.9f, 1f);
            _exportNextActionText.gameObject.AddComponent<LayoutElement>().preferredHeight = 14f;
            _exportPriorityText = AddLabel(_exportPanelGo.transform, "—", 11, false);
            _exportPriorityText.color = new Color(0.68f, 0.88f, 0.78f, 1f);
            _exportPriorityText.gameObject.AddComponent<LayoutElement>().preferredHeight = 14f;
            _exportStatsText = AddLabel(_exportPanelGo.transform, "—", 10, false);
            _exportStatsText.color = new Color(0.6f, 0.7f, 0.75f, 1f);
            _exportStatsText.gameObject.AddComponent<LayoutElement>().preferredHeight = 28f;
            var exportBtnRow = new GameObject("ExportBtnRow");
            exportBtnRow.transform.SetParent(_exportPanelGo.transform, false);
            exportBtnRow.AddComponent<LayoutElement>().preferredHeight = 28f;
            var exportHlg = exportBtnRow.AddComponent<HorizontalLayoutGroup>();
            exportHlg.spacing = 6;
            exportHlg.childForceExpandWidth = true;
            _exportGenerateButton = AddSmallButton(exportBtnRow.transform, "Gerar payload", () => OnGenerateExportRequested?.Invoke());
            _exportRegenerateButton = AddSmallButton(exportBtnRow.transform, "Regenerar", () => OnRegenerateExportRequested?.Invoke());
            _exportClearButton = AddSmallButton(exportBtnRow.transform, "Limpar", () => OnClearExportRequested?.Invoke());
            _exportBackButton = AddSmallButton(exportBtnRow.transform, "Voltar ao resultado", () => OnBackToOutcomeRequested?.Invoke());

            var persistencePanelColor = new Color(0.14f, 0.12f, 0.2f, 0.96f);
            _persistencePanelGo = CreatePanel(canvasGo.transform, "PersistencePanel", new Vector2(-420f, -200f), new Vector2(300f, 180f), persistencePanelColor);
            _persistencePanelGo.SetActive(false);
            var persistenceVlg = _persistencePanelGo.AddComponent<VerticalLayoutGroup>();
            persistenceVlg.spacing = 4;
            persistenceVlg.padding = new RectOffset(12, 10, 12, 10);
            persistenceVlg.childForceExpandHeight = false;
            _persistenceHeadlineText = AddLabel(_persistencePanelGo.transform, "Persistência local", 16, true);
            _persistenceHeadlineText.color = new Color(0.9f, 0.88f, 0.92f, 1f);
            _persistenceHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 20f;
            _persistenceStatusText = AddLabel(_persistencePanelGo.transform, "—", 11, false);
            _persistenceStatusText.color = new Color(0.72f, 0.78f, 0.85f, 1f);
            _persistenceStatusText.gameObject.AddComponent<LayoutElement>().preferredHeight = 32f;
            var persistenceBtnRow = new GameObject("PersistenceBtnRow");
            persistenceBtnRow.transform.SetParent(_persistencePanelGo.transform, false);
            persistenceBtnRow.AddComponent<LayoutElement>().preferredHeight = 28f;
            var persistenceHlg = persistenceBtnRow.AddComponent<HorizontalLayoutGroup>();
            persistenceHlg.spacing = 6;
            persistenceHlg.childForceExpandWidth = true;
            _persistenceSaveButton = AddSmallButton(persistenceBtnRow.transform, "Salvar sessão", () => OnSaveSessionRequested?.Invoke());
            _persistenceRestoreButton = AddSmallButton(persistenceBtnRow.transform, "Restaurar", () => OnRestoreSessionRequested?.Invoke());
            _persistenceClearButton = AddSmallButton(persistenceBtnRow.transform, "Limpar", () => OnClearSavedSessionRequested?.Invoke());

            var handoffPanelColor = new Color(0.18f, 0.16f, 0.22f, 0.96f);
            _handoffPanelGo = CreatePanel(canvasGo.transform, "HandoffPanel", new Vector2(0f, -550f), new Vector2(520f, 260f), handoffPanelColor);
            _handoffPanelGo.SetActive(false);
            var handoffVlg = _handoffPanelGo.AddComponent<VerticalLayoutGroup>();
            handoffVlg.spacing = 4;
            handoffVlg.padding = new RectOffset(16, 14, 14, 12);
            handoffVlg.childForceExpandHeight = false;
            _handoffHeadlineText = AddLabel(_handoffPanelGo.transform, "Relatório da sessão", 18, true);
            _handoffHeadlineText.color = new Color(0.92f, 0.94f, 0.96f, 1f);
            _handoffHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 22f;
            _handoffProposalText = AddLabel(_handoffPanelGo.transform, "Propostas: —", 12, false);
            _handoffProposalText.color = new Color(0.85f, 0.9f, 0.95f, 1f);
            _handoffDecisionText = AddLabel(_handoffPanelGo.transform, "Decisão: —", 12, false);
            _handoffDecisionText.color = new Color(0.88f, 0.9f, 0.96f, 1f);
            _handoffCTAText = AddLabel(_handoffPanelGo.transform, "CTA: —", 11, false);
            _handoffCTAText.color = new Color(0.8f, 0.9f, 0.96f, 1f);
            _handoffNextActionText = AddLabel(_handoffPanelGo.transform, "Próxima ação: —", 11, false);
            _handoffNextActionText.color = new Color(0.78f, 0.88f, 0.96f, 1f);
            _handoffPriorityText = AddLabel(_handoffPanelGo.transform, "Prioridade: —", 11, false);
            _handoffPriorityText.color = new Color(0.76f, 0.92f, 0.82f, 1f);
            _handoffHotspotsText = AddLabel(_handoffPanelGo.transform, "Hotspots: —", 11, false);
            _handoffHotspotsText.color = new Color(0.82f, 0.88f, 0.94f, 1f);
            _handoffComparisonsText = AddLabel(_handoffPanelGo.transform, "Comparações: —", 11, false);
            _handoffComparisonsText.color = new Color(0.8f, 0.86f, 0.94f, 1f);
            _handoffConfidenceText = AddLabel(_handoffPanelGo.transform, "Confiança: —", 11, false);
            _handoffConfidenceText.color = new Color(0.78f, 0.9f, 0.82f, 1f);
            _handoffNotesText = AddLabel(_handoffPanelGo.transform, "Observações: —", 10, false);
            _handoffNotesText.color = new Color(0.78f, 0.82f, 0.88f, 1f);
            _handoffNotesText.gameObject.AddComponent<LayoutElement>().preferredHeight = 28f;
            var handoffBtnRow = new GameObject("HandoffBtnRow");
            handoffBtnRow.transform.SetParent(_handoffPanelGo.transform, false);
            handoffBtnRow.AddComponent<LayoutElement>().preferredHeight = 30f;
            var handoffHlg = handoffBtnRow.AddComponent<HorizontalLayoutGroup>();
            handoffHlg.spacing = 6;
            handoffHlg.childForceExpandWidth = true;
            _handoffGenerateButton = AddSmallButton(handoffBtnRow.transform, "Gerar relatório", () => OnGenerateHandoffRequested?.Invoke());
            _handoffRegenerateButton = AddSmallButton(handoffBtnRow.transform, "Regenerar", () => OnRegenerateHandoffRequested?.Invoke());
            _handoffClearButton = AddSmallButton(handoffBtnRow.transform, "Limpar", () => OnClearHandoffRequested?.Invoke());
            _handoffBackButton = AddSmallButton(handoffBtnRow.transform, "Voltar", () => OnBackFromHandoffRequested?.Invoke());

            var shareablePanelColor = new Color(0.16f, 0.14f, 0.22f, 0.96f);
            _shareablePanelGo = CreatePanel(canvasGo.transform, "ShareablePanel", new Vector2(0f, -820f), new Vector2(620f, 360f), shareablePanelColor);
            _shareablePanelGo.SetActive(false);
            var shareableVlg = _shareablePanelGo.AddComponent<VerticalLayoutGroup>();
            shareableVlg.spacing = 4;
            shareableVlg.padding = new RectOffset(16, 14, 14, 12);
            shareableVlg.childForceExpandHeight = false;
            _shareableHeadlineText = AddLabel(_shareablePanelGo.transform, "Resumo compartilhável", 18, true);
            _shareableHeadlineText.color = new Color(0.92f, 0.94f, 0.96f, 1f);
            _shareableHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 22f;
            _shareableTitleText = AddLabel(_shareablePanelGo.transform, "Título: —", 12, false);
            _shareableTitleText.color = new Color(0.86f, 0.9f, 0.95f, 1f);
            _shareableExecutiveText = AddLabel(_shareablePanelGo.transform, "Resumo executivo: —", 11, false);
            _shareableExecutiveText.color = new Color(0.84f, 0.9f, 0.96f, 1f);
            _shareableExecutiveText.gameObject.AddComponent<LayoutElement>().preferredHeight = 40f;
            _shareableDecisionText = AddLabel(_shareablePanelGo.transform, "Decisão: —", 11, false);
            _shareableDecisionText.color = new Color(0.82f, 0.9f, 0.96f, 1f);
            _shareableCTAText = AddLabel(_shareablePanelGo.transform, "CTA: —", 11, false);
            _shareableCTAText.color = new Color(0.8f, 0.9f, 0.96f, 1f);
            _shareableNextActionText = AddLabel(_shareablePanelGo.transform, "Próxima ação: —", 11, false);
            _shareableNextActionText.color = new Color(0.78f, 0.88f, 0.96f, 1f);
            _shareablePriorityText = AddLabel(_shareablePanelGo.transform, "Prioridade: —", 11, false);
            _shareablePriorityText.color = new Color(0.76f, 0.92f, 0.82f, 1f);
            _shareableHighlightsText = AddLabel(_shareablePanelGo.transform, "Highlights: —", 11, false);
            _shareableHighlightsText.color = new Color(0.82f, 0.88f, 0.94f, 1f);
            _shareableRisksText = AddLabel(_shareablePanelGo.transform, "Riscos: —", 11, false);
            _shareableRisksText.color = new Color(0.8f, 0.86f, 0.94f, 1f);
            _shareableBodyText = AddLabel(_shareablePanelGo.transform, "Texto compartilhável:\n—", 10, false);
            _shareableBodyText.color = new Color(0.82f, 0.9f, 0.96f, 1f);
            _shareableBodyText.gameObject.AddComponent<LayoutElement>().preferredHeight = 120f;
            var shareableBtnRow = new GameObject("ShareableBtnRow");
            shareableBtnRow.transform.SetParent(_shareablePanelGo.transform, false);
            shareableBtnRow.AddComponent<LayoutElement>().preferredHeight = 30f;
            var shareableHlg = shareableBtnRow.AddComponent<HorizontalLayoutGroup>();
            shareableHlg.spacing = 6;
            shareableHlg.childForceExpandWidth = true;
            _shareableGenerateButton = AddSmallButton(shareableBtnRow.transform, "Gerar resumo", () => OnGenerateShareableRequested?.Invoke());
            _shareableRegenerateButton = AddSmallButton(shareableBtnRow.transform, "Regenerar", () => OnRegenerateShareableRequested?.Invoke());
            _shareableClearButton = AddSmallButton(shareableBtnRow.transform, "Limpar", () => OnClearShareableRequested?.Invoke());
            _shareableCopyButton = AddSmallButton(shareableBtnRow.transform, "Copiar texto", () => OnCopyShareableRequested?.Invoke());

            var qualityPanelColor = new Color(0.14f, 0.18f, 0.2f, 0.96f);
            _qualityPanelGo = CreatePanel(canvasGo.transform, "QualityPanel", new Vector2(420f, -200f), new Vector2(340f, 320f), qualityPanelColor);
            _qualityPanelGo.SetActive(false);
            var qualityVlg = _qualityPanelGo.AddComponent<VerticalLayoutGroup>();
            qualityVlg.spacing = 4;
            qualityVlg.padding = new RectOffset(14, 12, 14, 12);
            qualityVlg.childForceExpandHeight = false;
            _qualityHeadlineText = AddLabel(_qualityPanelGo.transform, "Diagnóstico de qualidade", 18, true);
            _qualityHeadlineText.color = new Color(0.9f, 0.92f, 0.88f, 1f);
            _qualityHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 22f;
            _qualityScoreText = AddLabel(_qualityPanelGo.transform, "Score: —", 14, false);
            _qualityScoreText.color = new Color(0.85f, 0.9f, 0.95f, 1f);
            _qualitySubScoresText = AddLabel(_qualityPanelGo.transform, "Sub-scores: —", 11, false);
            _qualitySubScoresText.color = new Color(0.78f, 0.86f, 0.92f, 1f);
            _qualitySubScoresText.gameObject.AddComponent<LayoutElement>().preferredHeight = 36f;
            _qualityLabelText = AddLabel(_qualityPanelGo.transform, "Label: —", 12, false);
            _qualityLabelText.color = new Color(0.8f, 0.88f, 0.94f, 1f);
            _qualityStrengthsText = AddLabel(_qualityPanelGo.transform, "Pontos fortes: —", 11, false);
            _qualityStrengthsText.color = new Color(0.72f, 0.88f, 0.78f, 1f);
            _qualityStrengthsText.gameObject.AddComponent<LayoutElement>().preferredHeight = 32f;
            _qualityWeaknessesText = AddLabel(_qualityPanelGo.transform, "Pontos fracos: —", 11, false);
            _qualityWeaknessesText.color = new Color(0.9f, 0.78f, 0.72f, 1f);
            _qualityWeaknessesText.gameObject.AddComponent<LayoutElement>().preferredHeight = 32f;
            _qualitySuggestionsText = AddLabel(_qualityPanelGo.transform, "Sugestões: —", 11, false);
            _qualitySuggestionsText.color = new Color(0.82f, 0.86f, 0.92f, 1f);
            _qualitySuggestionsText.gameObject.AddComponent<LayoutElement>().preferredHeight = 32f;
            var qualityBtnRow = new GameObject("QualityBtnRow");
            qualityBtnRow.transform.SetParent(_qualityPanelGo.transform, false);
            qualityBtnRow.AddComponent<LayoutElement>().preferredHeight = 28f;
            var qualityHlg = qualityBtnRow.AddComponent<HorizontalLayoutGroup>();
            qualityHlg.spacing = 6;
            qualityHlg.childForceExpandWidth = true;
            _qualityCalculateButton = AddSmallButton(qualityBtnRow.transform, "Calcular diagnóstico", () => OnCalculateQualityRequested?.Invoke());
            _qualityRecalculateButton = AddSmallButton(qualityBtnRow.transform, "Recalcular", () => OnRecalculateQualityRequested?.Invoke());
            _qualityClearButton = AddSmallButton(qualityBtnRow.transform, "Limpar", () => OnClearQualityRequested?.Invoke());
            _qualityBackButton = AddSmallButton(qualityBtnRow.transform, "Voltar", () => OnBackFromQualityRequested?.Invoke());

            var improvementPanelColor = new Color(0.16f, 0.14f, 0.2f, 0.96f);
            _improvementPlanPanelGo = CreatePanel(canvasGo.transform, "ImprovementPlanPanel", new Vector2(-420f, -520f), new Vector2(360f, 320f), improvementPanelColor);
            _improvementPlanPanelGo.SetActive(false);
            var improvementVlg = _improvementPlanPanelGo.AddComponent<VerticalLayoutGroup>();
            improvementVlg.spacing = 4;
            improvementVlg.padding = new RectOffset(14, 12, 14, 12);
            improvementVlg.childForceExpandHeight = false;
            _improvementHeadlineText = AddLabel(_improvementPlanPanelGo.transform, "Plano de melhorias", 18, true);
            _improvementHeadlineText.color = new Color(0.92f, 0.9f, 0.88f, 1f);
            _improvementHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 22f;
            _improvementSummaryText = AddLabel(_improvementPlanPanelGo.transform, "Resumo: —", 11, false);
            _improvementSummaryText.color = new Color(0.82f, 0.88f, 0.94f, 1f);
            _improvementSummaryText.gameObject.AddComponent<LayoutElement>().preferredHeight = 40f;
            _improvementTopPriorityText = AddLabel(_improvementPlanPanelGo.transform, "Prioritária: —", 12, false);
            _improvementTopPriorityText.color = new Color(0.88f, 0.82f, 0.72f, 1f);
            _improvementTopCategoryText = AddLabel(_improvementPlanPanelGo.transform, "Categoria: —", 11, false);
            _improvementTopCategoryText.color = new Color(0.8f, 0.86f, 0.92f, 1f);
            _improvementRecommendationsText = AddLabel(_improvementPlanPanelGo.transform, "Recomendações: —", 10, false);
            _improvementRecommendationsText.color = new Color(0.78f, 0.84f, 0.9f, 1f);
            _improvementRecommendationsText.gameObject.AddComponent<LayoutElement>().preferredHeight = 100f;
            var improvementBtnRow = new GameObject("ImprovementBtnRow");
            improvementBtnRow.transform.SetParent(_improvementPlanPanelGo.transform, false);
            improvementBtnRow.AddComponent<LayoutElement>().preferredHeight = 28f;
            var improvementHlg = improvementBtnRow.AddComponent<HorizontalLayoutGroup>();
            improvementHlg.spacing = 6;
            improvementHlg.childForceExpandWidth = true;
            _improvementGenerateButton = AddSmallButton(improvementBtnRow.transform, "Gerar plano", () => OnGenerateImprovementPlanRequested?.Invoke());
            _improvementRegenerateButton = AddSmallButton(improvementBtnRow.transform, "Regenerar", () => OnRegenerateImprovementPlanRequested?.Invoke());
            _improvementClearButton = AddSmallButton(improvementBtnRow.transform, "Limpar", () => OnClearImprovementPlanRequested?.Invoke());
            _improvementBackButton = AddSmallButton(improvementBtnRow.transform, "Voltar", () => OnBackFromImprovementPlanRequested?.Invoke());

            var presetPanelColor = new Color(0.14f, 0.2f, 0.18f, 0.96f);
            _presetPanelGo = CreatePanel(canvasGo.transform, "PresetPanel", new Vector2(0f, 280f), new Vector2(380f, 280f), presetPanelColor);
            _presetPanelGo.SetActive(false);
            var presetVlg = _presetPanelGo.AddComponent<VerticalLayoutGroup>();
            presetVlg.spacing = 4;
            presetVlg.padding = new RectOffset(14, 12, 14, 12);
            presetVlg.childForceExpandHeight = false;
            _presetHeadlineText = AddLabel(_presetPanelGo.transform, "Presets de apresentação", 18, true);
            _presetHeadlineText.color = new Color(0.9f, 0.92f, 0.88f, 1f);
            _presetHeadlineText.gameObject.AddComponent<LayoutElement>().preferredHeight = 22f;
            _presetCurrentText = AddLabel(_presetPanelGo.transform, "Actual: —", 12, false);
            _presetCurrentText.color = new Color(0.85f, 0.9f, 0.88f, 1f);
            _presetDurationText = AddLabel(_presetPanelGo.transform, "Duração: —", 11, false);
            _presetDurationText.color = new Color(0.8f, 0.86f, 0.9f, 1f);
            _presetFocusText = AddLabel(_presetPanelGo.transform, "Foco: —", 11, false);
            _presetFocusText.color = new Color(0.78f, 0.84f, 0.9f, 1f);
            var presetBtnRow1 = new GameObject("PresetBtnRow1");
            presetBtnRow1.transform.SetParent(_presetPanelGo.transform, false);
            presetBtnRow1.AddComponent<LayoutElement>().preferredHeight = 26f;
            var presetHlg1 = presetBtnRow1.AddComponent<HorizontalLayoutGroup>();
            presetHlg1.spacing = 4;
            presetHlg1.childForceExpandWidth = true;
            _presetQuickPitchButton = AddSmallButton(presetBtnRow1.transform, "Pitch rápido", () => OnApplyPresetRequested?.Invoke("QuickPitch"));
            _presetGuidedSalesButton = AddSmallButton(presetBtnRow1.transform, "Vendas guiadas", () => OnApplyPresetRequested?.Invoke("GuidedSales"));
            _presetPremiumShowcaseButton = AddSmallButton(presetBtnRow1.transform, "Showcase premium", () => OnApplyPresetRequested?.Invoke("PremiumShowcase"));
            var presetBtnRow2 = new GameObject("PresetBtnRow2");
            presetBtnRow2.transform.SetParent(_presetPanelGo.transform, false);
            presetBtnRow2.AddComponent<LayoutElement>().preferredHeight = 26f;
            var presetHlg2 = presetBtnRow2.AddComponent<HorizontalLayoutGroup>();
            presetHlg2.spacing = 4;
            presetHlg2.childForceExpandWidth = true;
            _presetComparisonModeButton = AddSmallButton(presetBtnRow2.transform, "Modo comparação", () => OnApplyPresetRequested?.Invoke("ComparisonMode"));
            _presetExecutiveReviewButton = AddSmallButton(presetBtnRow2.transform, "Revisão executiva", () => OnApplyPresetRequested?.Invoke("ExecutiveReview"));
            _presetClearButton = AddSmallButton(presetBtnRow2.transform, "Limpar preset", () => OnClearPresetRequested?.Invoke());

            var onboardingPanelColor = new Color(0.12f, 0.18f, 0.22f, 0.98f);
            _onboardingPanelGo = CreatePanel(canvasGo.transform, "OnboardingPanel", new Vector2(0f, 0f), new Vector2(500f, 380f), onboardingPanelColor);
            _onboardingPanelGo.SetActive(false);
            var onboardingVlg = _onboardingPanelGo.AddComponent<VerticalLayoutGroup>();
            onboardingVlg.spacing = 6;
            onboardingVlg.padding = new RectOffset(20, 16, 20, 16);
            onboardingVlg.childForceExpandHeight = false;
            _onboardingTitleText = AddLabel(_onboardingPanelGo.transform, "Apresentação Quest", 22, true);
            _onboardingTitleText.color = new Color(0.95f, 0.94f, 0.9f, 1f);
            _onboardingTitleText.gameObject.AddComponent<LayoutElement>().preferredHeight = 28f;
            _onboardingProposalText = AddLabel(_onboardingPanelGo.transform, "Proposta: —", 14, false);
            _onboardingProposalText.color = new Color(0.88f, 0.9f, 0.92f, 1f);
            _onboardingPresetText = AddLabel(_onboardingPanelGo.transform, "Modo: —", 12, false);
            _onboardingPresetText.color = new Color(0.82f, 0.88f, 0.9f, 1f);
            _onboardingRuntimeText = AddLabel(_onboardingPanelGo.transform, "Runtime: —", 11, false);
            _onboardingRuntimeText.color = new Color(0.78f, 0.84f, 0.88f, 1f);
            _onboardingGoalText = AddLabel(_onboardingPanelGo.transform, "Objetivo: —", 12, false);
            _onboardingGoalText.color = new Color(0.85f, 0.9f, 0.92f, 1f);
            _onboardingGoalText.gameObject.AddComponent<LayoutElement>().preferredHeight = 36f;
            _onboardingHintsText = AddLabel(_onboardingPanelGo.transform, "Dicas: —", 11, false);
            _onboardingHintsText.color = new Color(0.8f, 0.86f, 0.9f, 1f);
            _onboardingHintsText.gameObject.AddComponent<LayoutElement>().preferredHeight = 70f;
            _onboardingDurationText = AddLabel(_onboardingPanelGo.transform, "Duração estimada: —", 11, false);
            _onboardingDurationText.color = new Color(0.78f, 0.84f, 0.88f, 1f);
            var onboardingBtnRow = new GameObject("OnboardingBtnRow");
            onboardingBtnRow.transform.SetParent(_onboardingPanelGo.transform, false);
            onboardingBtnRow.AddComponent<LayoutElement>().preferredHeight = 32f;
            var onboardingHlg = onboardingBtnRow.AddComponent<HorizontalLayoutGroup>();
            onboardingHlg.spacing = 10;
            onboardingHlg.childForceExpandWidth = true;
            _onboardingStartButton = AddSmallButton(onboardingBtnRow.transform, "Iniciar apresentação", () => OnStartPresentationRequested?.Invoke());
            _onboardingCloseButton = AddSmallButton(onboardingBtnRow.transform, "Fechar", () => OnCloseOnboardingRequested?.Invoke());

            _built = true;
        }

        private void LateUpdate()
        {
            if (!_built || _rig == null || _anchor == null) return;
            _anchor.position = _rig.position + _rig.forward * _distanceInFront;
            _anchor.rotation = Quaternion.LookRotation(_anchor.position - _rig.position);
        }

        /// <summary>Transform do canvas World Space (para anexar cursor/retículo).</summary>
        public Transform GetCursorParent() => _worldCanvasTransform;

        /// <summary>Atualiza os painéis sem camada de apontamento (fallback: foco e seleção apenas).</summary>
        public void Refresh(QuestPresentationSession session, QuestSelectionController selectionController)
        {
            Refresh(session, selectionController, null);
        }

        /// <summary>Atualiza o conteúdo dos painéis com os dados da sessão, seleção, alvo apontado, dwell e alvo resolvido (opcional).</summary>
        /// <param name="resolvedTargetId">Quando fornecido, usado como alvo "apontado" estável (resolver); senão usa pointerPrep.GetPointedTargetId().</param>
        public void Refresh(QuestPresentationSession session, QuestSelectionController selectionController, QuestPointerPreparationController pointerPrepController, QuestHoverDwellController hoverDwellController = null, string resolvedTargetId = null)
        {
            if (!_built) return;

            if (session?.MRPlan == null)
            {
                _mainTitleText.text = "Apresentação Quest";
                _mainContentText.text = "—";
                _lateralLabelText.text = "Hotspot";
                _lateralContentText.text = "—";
                _progressText.text = "—";
                _modeReadinessText.text = "Modo: —  |  Pronto: Não";
                ApplyPanelHighlight(_mainPanelGo, false, false, false, false, false, 0f, _mainPanelColor);
                ApplyPanelHighlight(_lateralPanelGo, false, false, false, false, false, 0f, _lateralPanelColor);
                ApplyPanelHighlight(_progressPanelGo, false, false, false, false, false, 0f, _progressPanelColor);
                RefreshFocusIndicator(session);
                RefreshSelectionIndicator(null);
                RefreshPointerModeIndicator(null, null, null);
                RefreshHotspotContextPanel(null);
                RefreshHotspotComparisonPanel(null);
                RefreshClosingPanel(null);
                RefreshOutcomePanel(null);
                RefreshExportPanel(null);
                RefreshPersistencePanel(null);
                RefreshHandoffPanel(null);
                RefreshShareablePanel(null);
                RefreshQualityPanel(null);
                RefreshImprovementPlanPanel(null);
                RefreshPresetPanel(null);
                RefreshOnboardingPanel(null);
                return;
            }

            var title = string.IsNullOrEmpty(session.MRPlan.PresentationTitle) ? "Apresentação Quest" : session.MRPlan.PresentationTitle;
            _mainTitleText.text = title;

            if (session.CurrentStep != null)
            {
                _mainContentText.text = session.CurrentStep.Title ?? session.CurrentStep.Description ?? "—";
            }
            else if (session.CurrentHotspot != null)
            {
                _mainContentText.text = session.CurrentHotspot.Title ?? session.CurrentHotspot.Description ?? "—";
            }
            else if (session.CurrentSceneState != null)
            {
                _mainContentText.text = session.CurrentSceneState.Name ?? session.CurrentSceneState.Description ?? "—";
            }
            else
            {
                var total = session.TotalSteps;
                _mainContentText.text = total > 0 ? "Use os botões para navegar." : "Nenhum passo disponível.";
            }

            _lateralLabelText.text = "Hotspot";
            _lateralContentText.text = session.CurrentHotspot != null
                ? (session.CurrentHotspot.Title ?? session.CurrentHotspot.Description ?? "—")
                : "—";

            var totalSteps = session.TotalSteps;
            var current = session.CurrentGuidedStepIndex + 1;
            _progressText.text = totalSteps > 0 ? $"{current} / {totalSteps}" : "—";
            _modeReadinessText.text = "Modo: " + NavigationModeLabel(session.NavigationMode)
                + "  |  Pronto: " + (session.IsPresentationReady ? "Sim" : "Não");
            if (session.RuntimeReadiness != null)
                _modeReadinessText.text += "  |  Build: " + (session.RuntimeReadiness.IsBuildReady ? "Sim" : "Não");

            ApplyFocusHighlight(session, selectionController, pointerPrepController, hoverDwellController, resolvedTargetId);
            ApplySelectionHighlight(selectionController);
            RefreshFocusIndicator(session);
            RefreshSelectionIndicator(selectionController);
            RefreshPointerModeIndicator(pointerPrepController, hoverDwellController, session);
            RefreshHotspotContextPanel(session);
            RefreshHotspotComparisonPanel(session);
            RefreshClosingPanel(session);
            RefreshOutcomePanel(session);
            RefreshExportPanel(session);
            RefreshPersistencePanel(session);
            RefreshHandoffPanel(session);
            RefreshShareablePanel(session);
            RefreshQualityPanel(session);
            RefreshImprovementPlanPanel(session);
            RefreshPresetPanel(session);
            RefreshOnboardingPanel(session);
        }

        private void RefreshHotspotContextPanel(QuestPresentationSession session)
        {
            if (_hotspotContextPanelGo == null) return;
            if (session != null && (session.HasHotspotComparisonOpen || session.HasClosingOpen))
            {
                _hotspotContextPanelGo.SetActive(false);
                return;
            }
            var ctx = session?.CurrentHotspotContext;
            if (ctx == null || !ctx.IsContextOpen)
            {
                _hotspotContextPanelGo.SetActive(false);
                return;
            }
            _hotspotContextPanelGo.SetActive(true);
            var step = ctx.CurrentStoryStep;
            if (ctx.IsStoryActive && step != null)
            {
                _hotspotContextTitleText.text = step.Title ?? "—";
                _hotspotContextSummaryText.text = step.Summary ?? "—";
                _hotspotContextSalesText.text = step.SalesMessage ?? "—";
                _hotspotContextPremiumText.text = step.IsUpsellMoment ? "Upsell" : "";
                var total = ctx.StorySteps != null ? ctx.StorySteps.Count : 0;
                _hotspotContextProgressText.text = total > 0 ? "Passo " + (ctx.CurrentStoryStepIndex + 1) + "/" + total : "";
                _hotspotContextProgressText.gameObject.SetActive(true);
                if (_hotspotStartStoryButton != null) _hotspotStartStoryButton.gameObject.SetActive(false);
                if (_hotspotPrevStoryButton != null) _hotspotPrevStoryButton.gameObject.SetActive(true);
                if (_hotspotNextStoryButton != null) _hotspotNextStoryButton.gameObject.SetActive(true);
                if (_hotspotCloseStoryButton != null) _hotspotCloseStoryButton.gameObject.SetActive(true);
                if (_hotspotCompareButton != null) _hotspotCompareButton.gameObject.SetActive(false);
            }
            else
            {
                _hotspotContextTitleText.text = ctx.ContextTitle ?? "—";
                _hotspotContextSummaryText.text = ctx.ContextSummary ?? "—";
                _hotspotContextSalesText.text = ctx.SalesMessage ?? "—";
                _hotspotContextPremiumText.text = ctx.IsPremiumUpsell ? "Premium upsell" : "";
                _hotspotContextProgressText.text = "";
                _hotspotContextProgressText.gameObject.SetActive(false);
                var hasSteps = ctx.StorySteps != null && ctx.StorySteps.Count > 0;
                if (_hotspotStartStoryButton != null) _hotspotStartStoryButton.gameObject.SetActive(hasSteps);
                if (_hotspotPrevStoryButton != null) _hotspotPrevStoryButton.gameObject.SetActive(false);
                if (_hotspotNextStoryButton != null) _hotspotNextStoryButton.gameObject.SetActive(false);
                if (_hotspotCloseStoryButton != null) _hotspotCloseStoryButton.gameObject.SetActive(false);
                if (_hotspotCompareButton != null) _hotspotCompareButton.gameObject.SetActive(session?.Hotspots != null && session.Hotspots.Count >= 1);
            }
        }

        private void RefreshHotspotComparisonPanel(QuestPresentationSession session)
        {
            if (_hotspotComparisonPanelGo == null) return;
            if (session != null && session.HasClosingOpen)
            {
                _hotspotComparisonPanelGo.SetActive(false);
                return;
            }
            var comp = session?.CurrentHotspotComparison;
            if (comp == null || !comp.IsComparisonOpen)
            {
                _hotspotComparisonPanelGo.SetActive(false);
                return;
            }
            _hotspotComparisonPanelGo.SetActive(true);
            _comparisonLeftTitleText.text = comp.LeftTitle ?? "—";
            _comparisonLeftSalesText.text = comp.LeftSalesMessage ?? "—";
            _comparisonRightTitleText.text = comp.RightTitle ?? "—";
            _comparisonRightSalesText.text = comp.RightSalesMessage ?? "—";
            _comparisonBetterExpText.text = string.IsNullOrEmpty(comp.BetterForExperience) ? "" : "Melhor experiência: " + (comp.BetterForExperience == "Left" ? "Esq." : "Dir.");
            _comparisonBetterUpsellText.text = string.IsNullOrEmpty(comp.BetterForUpsell) ? "" : "Melhor upsell: " + (comp.BetterForUpsell == "Left" ? "Esq." : "Dir.");
            _comparisonBetterClarityText.text = string.IsNullOrEmpty(comp.BetterForClarity) ? "" : "Mais claro: " + (comp.BetterForClarity == "Left" ? "Esq." : "Dir.");
            _comparisonSummaryText.text = comp.ComparisonSummary ?? "—";
        }

        private void RefreshClosingPanel(QuestPresentationSession session)
        {
            if (_closingPanelGo == null) return;
            var closing = session?.CurrentClosingState;
            if (closing == null || !closing.IsClosingOpen)
            {
                _closingPanelGo.SetActive(false);
                return;
            }
            _closingPanelGo.SetActive(true);
            _closingHeadlineText.text = closing.ClosingHeadline ?? "—";
            _closingSummaryText.text = closing.ClosingSummary ?? "—";
            _closingConfidenceText.text = closing.ConfidenceLabel ?? "";
            _closingNextActionText.text = string.IsNullOrEmpty(closing.SuggestedNextAction) ? "" : "Próxima ação: " + closing.SuggestedNextAction;
            var parts = new System.Collections.Generic.List<string>();
            if (!string.IsNullOrEmpty(closing.BudgetConclusion)) parts.Add("Orçamento: " + closing.BudgetConclusion);
            if (!string.IsNullOrEmpty(closing.ExperienceConclusion)) parts.Add("Experiência: " + closing.ExperienceConclusion);
            if (!string.IsNullOrEmpty(closing.OperationalConclusion)) parts.Add("Operacional: " + closing.OperationalConclusion);
            _closingConclusionsText.text = parts.Count > 0 ? string.Join("\n", parts) : "";
            var primaryLabel = _closingPrimaryCTAButton?.GetComponentInChildren<Text>();
            if (primaryLabel != null) primaryLabel.text = closing.PrimaryCTA ?? "Fechar proposta";
            var secondaryLabel = _closingSecondaryCTAButton?.GetComponentInChildren<Text>();
            if (secondaryLabel != null) secondaryLabel.text = closing.SecondaryCTA ?? "Ver alternativas";
        }

        private static string DecisionStateLabel(QuestCommercialDecisionState state)
        {
            switch (state)
            {
                case QuestCommercialDecisionState.ExplorationOnly: return "Apenas exploração";
                case QuestCommercialDecisionState.Interested: return "Interesse manifestado";
                case QuestCommercialDecisionState.NeedsFollowUp: return "Precisa follow-up";
                case QuestCommercialDecisionState.ReadyToAdvance: return "Pronta para avançar";
                case QuestCommercialDecisionState.ReadyToClose: return "Pronta para fechar";
                default: return state.ToString();
            }
        }

        private void RefreshOutcomePanel(QuestPresentationSession session)
        {
            if (_outcomePanelGo == null) return;
            var outcome = session?.CurrentCommercialOutcome;
            var closingOpen = session?.CurrentClosingState?.IsClosingOpen == true;
            if (outcome == null || closingOpen)
            {
                _outcomePanelGo.SetActive(false);
                return;
            }
            _outcomePanelGo.SetActive(true);
            _outcomeHeadlineText.text = "Resultado da apresentação";
            _outcomeDecisionText.text = "Decisão: " + DecisionStateLabel(outcome.FinalDecisionState);
            _outcomeNextActionText.text = string.IsNullOrEmpty(outcome.SuggestedNextAction) ? "—" : "Próxima ação: " + outcome.SuggestedNextAction;
            _outcomePriorityText.text = "Prioridade follow-up: " + (outcome.FollowUpPriority <= 0 ? "—" : outcome.FollowUpPriority.ToString());
        }

        private void RefreshExportPanel(QuestPresentationSession session)
        {
            if (_exportPanelGo == null) return;
            var outcome = session?.CurrentCommercialOutcome;
            var payload = session?.CurrentExportPayload;
            var closingOpen = session?.CurrentClosingState?.IsClosingOpen == true;
            if ((outcome == null && payload == null) || closingOpen)
            {
                _exportPanelGo.SetActive(false);
                return;
            }
            _exportPanelGo.SetActive(true);
            if (payload == null)
            {
                _exportHeadlineText.text = "Payload de exportação";
                _exportIdsText.text = "Gere o payload a partir do resultado actual.";
                _exportDecisionText.text = "";
                _exportCTAText.text = "";
                _exportNextActionText.text = "";
                _exportPriorityText.text = "";
                _exportStatsText.text = "";
                if (_exportGenerateButton != null) _exportGenerateButton.gameObject.SetActive(true);
                if (_exportRegenerateButton != null) _exportRegenerateButton.gameObject.SetActive(false);
                if (_exportClearButton != null) _exportClearButton.gameObject.SetActive(false);
                if (_exportBackButton != null) _exportBackButton.gameObject.SetActive(false);
                return;
            }
            _exportHeadlineText.text = "Payload de exportação";
            _exportIdsText.text = "Sessão: " + (payload.SessionId ?? "—") + "  |  Projeto: " + (string.IsNullOrEmpty(payload.ProjectId) ? "—" : payload.ProjectId) + "  |  Proposta: " + (payload.SelectedProposalId ?? "—");
            _exportDecisionText.text = "Decisão: " + DecisionStateLabel(payload.FinalDecisionState);
            _exportCTAText.text = string.IsNullOrEmpty(payload.ConfirmedCTA) ? "CTA: —" : "CTA: " + payload.ConfirmedCTA;
            _exportNextActionText.text = string.IsNullOrEmpty(payload.SuggestedNextAction) ? "" : "Próxima ação: " + payload.SuggestedNextAction;
            _exportPriorityText.text = "Prioridade: " + (payload.FollowUpPriority <= 0 ? "—" : payload.FollowUpPriority.ToString());
            var stats = payload.InteractionStats;
            _exportStatsText.text = stats != null
                ? "Passos " + stats.GuidedStepsViewed + "  |  Hotspots " + stats.HotspotsOpened + "  |  Compar. " + stats.ComparisonsOpened + "  |  Fech. " + stats.ClosingOpened + "  |  CTA " + stats.CTAConfirmations + "  |  Total " + stats.TotalInteractionCount + "  |  " + (int)stats.EstimatedSessionDurationSeconds + "s"
                : "";
            if (_exportGenerateButton != null) _exportGenerateButton.gameObject.SetActive(false);
            if (_exportRegenerateButton != null) _exportRegenerateButton.gameObject.SetActive(true);
            if (_exportClearButton != null) _exportClearButton.gameObject.SetActive(true);
            if (_exportBackButton != null) _exportBackButton.gameObject.SetActive(true);
        }

        private void RefreshHandoffPanel(QuestPresentationSession session)
        {
            if (_handoffPanelGo == null) return;
            var report = session?.CurrentHandoffReport;
            var closingOpen = session?.CurrentClosingState?.IsClosingOpen == true;
            if (session == null || closingOpen)
            {
                _handoffPanelGo.SetActive(false);
                return;
            }
            if (report == null)
            {
                _handoffPanelGo.SetActive(true);
                _handoffHeadlineText.text = "Relatório da sessão";
                _handoffProposalText.text = "Propostas: gere o relatório para consolidar a sessão actual.";
                _handoffDecisionText.text = "Decisão: —";
                _handoffCTAText.text = "CTA: —";
                _handoffNextActionText.text = "Próxima ação: —";
                _handoffPriorityText.text = "Prioridade: —";
                _handoffHotspotsText.text = "Hotspots: —";
                _handoffComparisonsText.text = "Comparações: —";
                _handoffConfidenceText.text = "Confiança: —";
                _handoffNotesText.text = "Observações: —";
                if (_handoffGenerateButton != null) _handoffGenerateButton.gameObject.SetActive(true);
                if (_handoffRegenerateButton != null) _handoffRegenerateButton.gameObject.SetActive(false);
                if (_handoffClearButton != null) _handoffClearButton.gameObject.SetActive(false);
                if (_handoffBackButton != null) _handoffBackButton.gameObject.SetActive(false);
                return;
            }
            _handoffPanelGo.SetActive(true);
            var recId = string.IsNullOrEmpty(report.RecommendedProposalId) ? "—" : report.RecommendedProposalId;
            var selId = string.IsNullOrEmpty(report.SelectedProposalId) ? "—" : report.SelectedProposalId;
            _handoffHeadlineText.text = "Relatório da sessão";
            _handoffProposalText.text = "Propostas: Recomendada " + recId + "  |  Escolhida " + selId;
            _handoffDecisionText.text = "Decisão: " + report.FinalDecisionState;
            _handoffCTAText.text = "CTA: " + (string.IsNullOrEmpty(report.ConfirmedCTA) ? "—" : report.ConfirmedCTA);
            _handoffNextActionText.text = "Próxima ação: " + (string.IsNullOrEmpty(report.SuggestedNextAction) ? "—" : report.SuggestedNextAction);
            _handoffPriorityText.text = "Prioridade: " + (report.FollowUpPriority <= 0 ? "—" : report.FollowUpPriority.ToString());
            _handoffHotspotsText.text = "Hotspots: " + (report.KeyHotspotsVisited != null && report.KeyHotspotsVisited.Count > 0 ? string.Join(", ", report.KeyHotspotsVisited) : "—");
            _handoffComparisonsText.text = "Comparações: " + (report.KeyComparisonsViewed != null && report.KeyComparisonsViewed.Count > 0 ? string.Join(", ", report.KeyComparisonsViewed) : "—");
            _handoffConfidenceText.text = "Confiança: " + (string.IsNullOrEmpty(report.FinalConfidenceLabel) ? "—" : report.FinalConfidenceLabel);
            _handoffNotesText.text = "Observações: " + (string.IsNullOrEmpty(report.HandoffNotes) ? "—" : report.HandoffNotes);
            if (_handoffGenerateButton != null) _handoffGenerateButton.gameObject.SetActive(false);
            if (_handoffRegenerateButton != null) _handoffRegenerateButton.gameObject.SetActive(true);
            if (_handoffClearButton != null) _handoffClearButton.gameObject.SetActive(true);
            if (_handoffBackButton != null) _handoffBackButton.gameObject.SetActive(true);
        }

        private void RefreshShareablePanel(QuestPresentationSession session)
        {
            if (_shareablePanelGo == null) return;
            if (session == null || session.MRPlan == null)
            {
                _shareablePanelGo.SetActive(false);
                return;
            }
            var summary = session.CurrentShareableSummary;
            if (summary == null)
            {
                _shareablePanelGo.SetActive(true);
                _shareableHeadlineText.text = "Resumo compartilhável";
                _shareableTitleText.text = "Título: gere o resumo para consolidar a sessão actual.";
                _shareableExecutiveText.text = "Resumo executivo: —";
                _shareableDecisionText.text = "Decisão: —";
                _shareableCTAText.text = "CTA: —";
                _shareableNextActionText.text = "Próxima ação: —";
                _shareablePriorityText.text = "Prioridade: —";
                _shareableHighlightsText.text = "Highlights: —";
                _shareableRisksText.text = "Riscos: —";
                _shareableBodyText.text = "Texto compartilhável:\n—";
                if (_shareableGenerateButton != null) _shareableGenerateButton.gameObject.SetActive(true);
                if (_shareableRegenerateButton != null) _shareableRegenerateButton.gameObject.SetActive(false);
                if (_shareableClearButton != null) _shareableClearButton.gameObject.SetActive(false);
                if (_shareableCopyButton != null) _shareableCopyButton.gameObject.SetActive(false);
                return;
            }

            _shareablePanelGo.SetActive(true);
            _shareableHeadlineText.text = "Resumo compartilhável";
            _shareableTitleText.text = "Título: " + (summary.Title ?? "—");
            _shareableExecutiveText.text = "Resumo executivo: " + (summary.ExecutiveSummary ?? "—");
            _shareableDecisionText.text = "Decisão: " + (summary.FinalDecisionLabel ?? "—");
            _shareableCTAText.text = "CTA: " + (summary.ConfirmedCTALabel ?? "—");
            _shareableNextActionText.text = "Próxima ação: " + (summary.SuggestedNextActionLabel ?? "—");
            _shareablePriorityText.text = "Prioridade: " + (summary.FollowUpPriorityLabel ?? "—");
            _shareableHighlightsText.text = "Highlights: " + ((summary.KeyHighlights != null && summary.KeyHighlights.Count > 0) ? string.Join("; ", summary.KeyHighlights) : "—");
            _shareableRisksText.text = "Riscos: " + ((summary.KeyRisks != null && summary.KeyRisks.Count > 0) ? string.Join("; ", summary.KeyRisks) : "—");
            _shareableBodyText.text = "Texto compartilhável:\n" + (summary.ShareableText ?? "—");

            if (_shareableGenerateButton != null) _shareableGenerateButton.gameObject.SetActive(false);
            if (_shareableRegenerateButton != null) _shareableRegenerateButton.gameObject.SetActive(true);
            if (_shareableClearButton != null) _shareableClearButton.gameObject.SetActive(true);
            if (_shareableCopyButton != null) _shareableCopyButton.gameObject.SetActive(true);
        }

        private void RefreshQualityPanel(QuestPresentationSession session)
        {
            if (_qualityPanelGo == null) return;
            if (session == null || session.MRPlan == null)
            {
                _qualityPanelGo.SetActive(false);
                return;
            }
            var assessment = session.CurrentQualityAssessment;
            if (assessment == null)
            {
                _qualityPanelGo.SetActive(true);
                _qualityHeadlineText.text = "Diagnóstico de qualidade";
                _qualityScoreText.text = "Score: calcule o diagnóstico para ver a avaliação.";
                _qualitySubScoresText.text = "Sub-scores: —";
                _qualityLabelText.text = "Label: —";
                _qualityStrengthsText.text = "Pontos fortes: —";
                _qualityWeaknessesText.text = "Pontos fracos: —";
                _qualitySuggestionsText.text = "Sugestões: —";
                if (_qualityCalculateButton != null) _qualityCalculateButton.gameObject.SetActive(true);
                if (_qualityRecalculateButton != null) _qualityRecalculateButton.gameObject.SetActive(false);
                if (_qualityClearButton != null) _qualityClearButton.gameObject.SetActive(false);
                if (_qualityBackButton != null) _qualityBackButton.gameObject.SetActive(true);
                return;
            }

            _qualityPanelGo.SetActive(true);
            var overall = (assessment.PresentationQualityScore + assessment.CommercialClarityScore + assessment.InteractionQualityScore + assessment.DecisionReadinessScore + assessment.EngagementContributionScore) / 5;
            _qualityHeadlineText.text = "Diagnóstico de qualidade";
            _qualityScoreText.text = "Score geral: " + overall + "  (apresentação " + assessment.PresentationQualityScore + ", comercial " + assessment.CommercialClarityScore + ", interação " + assessment.InteractionQualityScore + ", decisão " + assessment.DecisionReadinessScore + ", engajamento " + assessment.EngagementContributionScore + ")";
            _qualitySubScoresText.text = "Apresentação: " + assessment.PresentationQualityScore + "  |  Comercial: " + assessment.CommercialClarityScore + "  |  Interação: " + assessment.InteractionQualityScore + "  |  Decisão: " + assessment.DecisionReadinessScore + "  |  Engajamento: " + assessment.EngagementContributionScore;
            _qualityLabelText.text = "Label: " + (assessment.QualityLabel ?? "—");
            _qualityStrengthsText.text = "Pontos fortes: " + (assessment.Strengths != null && assessment.Strengths.Count > 0 ? string.Join("; ", assessment.Strengths) : "—");
            _qualityWeaknessesText.text = "Pontos fracos: " + (assessment.Weaknesses != null && assessment.Weaknesses.Count > 0 ? string.Join("; ", assessment.Weaknesses) : "—");
            _qualitySuggestionsText.text = "Sugestões: " + (assessment.ImprovementSuggestions != null && assessment.ImprovementSuggestions.Count > 0 ? string.Join("; ", assessment.ImprovementSuggestions) : "—");
            if (_qualityCalculateButton != null) _qualityCalculateButton.gameObject.SetActive(false);
            if (_qualityRecalculateButton != null) _qualityRecalculateButton.gameObject.SetActive(true);
            if (_qualityClearButton != null) _qualityClearButton.gameObject.SetActive(true);
            if (_qualityBackButton != null) _qualityBackButton.gameObject.SetActive(true);
        }

        private void RefreshImprovementPlanPanel(QuestPresentationSession session)
        {
            if (_improvementPlanPanelGo == null) return;
            if (session == null || session.MRPlan == null)
            {
                _improvementPlanPanelGo.SetActive(false);
                return;
            }
            var plan = session.CurrentImprovementPlan;
            if (plan == null)
            {
                _improvementPlanPanelGo.SetActive(true);
                _improvementHeadlineText.text = "Plano de melhorias";
                _improvementSummaryText.text = "Resumo: calcule o diagnóstico de qualidade e depois gere o plano para ver recomendações.";
                _improvementTopPriorityText.text = "Prioritária: —";
                _improvementTopCategoryText.text = "Categoria: —";
                _improvementRecommendationsText.text = "Recomendações: —";
                if (_improvementGenerateButton != null) _improvementGenerateButton.gameObject.SetActive(true);
                if (_improvementRegenerateButton != null) _improvementRegenerateButton.gameObject.SetActive(false);
                if (_improvementClearButton != null) _improvementClearButton.gameObject.SetActive(false);
                if (_improvementBackButton != null) _improvementBackButton.gameObject.SetActive(true);
                return;
            }

            _improvementPlanPanelGo.SetActive(true);
            _improvementHeadlineText.text = "Plano de melhorias";
            _improvementSummaryText.text = "Resumo: " + (plan.ImprovementSummary ?? "—");
            var top = plan.TopPriorityRecommendation;
            _improvementTopPriorityText.text = "Prioritária: " + (top != null ? (top.Title ?? top.Summary ?? "—") : "—");
            _improvementTopCategoryText.text = "Categoria: " + (top != null ? (top.Category ?? "—") : "—");
            var recLines = new System.Collections.Generic.List<string>();
            if (plan.Recommendations != null)
            {
                foreach (var r in plan.Recommendations)
                {
                    var line = "[" + (r.Priority ?? "—") + "] " + (r.Title ?? r.Summary ?? "—");
                    if (!string.IsNullOrEmpty(r.SuggestedAction)) line += " → " + (r.SuggestedAction.Length > 40 ? r.SuggestedAction.Substring(0, 40) + "…" : r.SuggestedAction);
                    recLines.Add(line);
                }
            }
            _improvementRecommendationsText.text = "Recomendações:\n" + (recLines.Count > 0 ? string.Join("\n", recLines) : "—");
            if (_improvementGenerateButton != null) _improvementGenerateButton.gameObject.SetActive(false);
            if (_improvementRegenerateButton != null) _improvementRegenerateButton.gameObject.SetActive(true);
            if (_improvementClearButton != null) _improvementClearButton.gameObject.SetActive(true);
            if (_improvementBackButton != null) _improvementBackButton.gameObject.SetActive(true);
        }

        private void RefreshPresetPanel(QuestPresentationSession session)
        {
            if (_presetPanelGo == null) return;
            if (session == null || session.MRPlan == null)
            {
                _presetPanelGo.SetActive(false);
                return;
            }
            _presetPanelGo.SetActive(true);
            _presetHeadlineText.text = "Presets de apresentação";
            var preset = session.CurrentPresentationPreset;
            if (preset == null)
            {
                _presetCurrentText.text = "Actual: Nenhum";
                _presetDurationText.text = "Duração: —";
                _presetFocusText.text = "Foco: aplique um preset para definir estilo de condução.";
            }
            else
            {
                _presetCurrentText.text = "Actual: " + (preset.Name ?? preset.PresetId ?? "—");
                _presetDurationText.text = "Duração: " + (preset.EstimatedDurationMinutes > 0 ? preset.EstimatedDurationMinutes + " min" : "—");
                var focusParts = new System.Collections.Generic.List<string>();
                if (preset.EmphasizeHotspots) focusParts.Add("Hotspots");
                if (preset.EmphasizeComparison) focusParts.Add("Comparação");
                if (preset.EmphasizeClosing) focusParts.Add("Fechamento");
                _presetFocusText.text = "Foco: " + (focusParts.Count > 0 ? string.Join(", ", focusParts) : "Roteiro guiado");
            }
        }

        private void RefreshOnboardingPanel(QuestPresentationSession session)
        {
            if (_onboardingPanelGo == null) return;
            if (session == null)
            {
                _onboardingPanelGo.SetActive(false);
                return;
            }
            var state = session.CurrentOnboardingState;
            bool isOpen = state != null && state.IsOnboardingOpen;
            _onboardingPanelGo.SetActive(isOpen);
            if (!isOpen) return;

            _onboardingTitleText.text = state.SessionTitle ?? "Apresentação Quest";
            _onboardingProposalText.text = "Proposta: " + (state.ProposalLabel ?? "—");
            _onboardingPresetText.text = "Modo: " + (state.PresetLabel ?? "Nenhum");
            _onboardingRuntimeText.text = "Runtime: " + (state.RuntimeModeLabel ?? "—");
            _onboardingGoalText.text = "Objetivo: " + (state.PrimaryGoal ?? "Conhecer a proposta e concluir.");
            _onboardingHintsText.text = "Dicas:\n" + (state.InteractionHints != null && state.InteractionHints.Count > 0 ? string.Join("\n", state.InteractionHints) : "Use os botões para navegar.");
            _onboardingDurationText.text = "Duração estimada: " + (state.EstimatedDurationMinutes > 0 ? state.EstimatedDurationMinutes + " min" : "—");
            if (_onboardingStartButton != null) _onboardingStartButton.interactable = state.IsReadyToStart;
        }

        private void RefreshPersistencePanel(QuestPresentationSession session)
        {
            if (_persistencePanelGo == null) return;
            if (session?.MRPlan == null)
            {
                _persistencePanelGo.SetActive(false);
                return;
            }
            _persistencePanelGo.SetActive(true);
            _persistenceHeadlineText.text = "Persistência local";
            var snap = session.CurrentLocalSnapshot;
            var restorable = session.RestorableSnapshotAvailable;
            if (snap != null)
                _persistenceStatusText.text = "Salvo: " + (snap.SavedAt ?? "—") + "  |  Sessão " + (snap.SessionId ?? "—") + "  |  Restaurável: " + (restorable ? "Sim" : "Não");
            else
                _persistenceStatusText.text = restorable ? "Restaurável: Sim (snapshot em storage)" : "Nenhum snapshot salvo.";
        }

        private void ApplyFocusHighlight(QuestPresentationSession session, QuestSelectionController selectionController, QuestPointerPreparationController pointerPrepController, QuestHoverDwellController hoverDwellController = null, string resolvedTargetId = null)
        {
            if (session == null) return;
            var selectedType = selectionController?.GetSelectedTargetType();
            var mainSelected = selectedType == QuestSelectableTargetType.GuidedStep || selectedType == QuestSelectableTargetType.SceneState;
            var lateralSelected = selectedType == QuestSelectableTargetType.Hotspot;
            var progressSelected = selectedType == QuestSelectableTargetType.ActionButton || selectedType == QuestSelectableTargetType.ModeToggle;

            var pointedId = !string.IsNullOrEmpty(resolvedTargetId) ? resolvedTargetId : pointerPrepController?.GetPointedTargetId();
            var pointedFromXR = pointerPrepController != null && pointerPrepController.IsPointedFromXRRaycast;
            var mainPointed = pointedId == "guided_step" || pointedId == "scene_state";
            var lateralPointed = pointedId == "hotspot";
            var progressPointed = pointedId == "action_next" || pointedId == "action_restart" || pointedId == "mode_toggle";

            var dwellProgress = hoverDwellController != null ? hoverDwellController.GetDwellProgressNormalized() : 0f;
            var isDwellReady = hoverDwellController != null && session?.CurrentHoverState != null && session.CurrentHoverState.IsDwellReady;
            var mainDwellReady = mainPointed && isDwellReady;
            var lateralDwellReady = lateralPointed && isDwellReady;
            var progressDwellReady = progressPointed && isDwellReady;

            if (!session.IsInteractionModeActive && !mainSelected && !lateralSelected && !progressSelected && !mainPointed && !lateralPointed && !progressPointed)
            {
                ApplyPanelHighlight(_mainPanelGo, false, false, false, false, false, 0f, _mainPanelColor);
                ApplyPanelHighlight(_lateralPanelGo, false, false, false, false, false, 0f, _lateralPanelColor);
                ApplyPanelHighlight(_progressPanelGo, false, false, false, false, false, 0f, _progressPanelColor);
                return;
            }
            var focus = session.FocusedTargetType;
            var mainFocused = focus == QuestPresentationFocusTargetType.GuidedStepPanel || focus == QuestPresentationFocusTargetType.SceneStatePanel;
            var lateralFocused = focus == QuestPresentationFocusTargetType.HotspotPanel;
            var progressFocused = focus == QuestPresentationFocusTargetType.ProgressPanel || focus == QuestPresentationFocusTargetType.ActionPanel;

            ApplyPanelHighlight(_mainPanelGo, mainFocused, mainSelected, mainPointed, pointedFromXR && mainPointed, mainDwellReady, mainPointed ? dwellProgress : 0f, _mainPanelColor);
            ApplyPanelHighlight(_lateralPanelGo, lateralFocused, lateralSelected, lateralPointed, pointedFromXR && lateralPointed, lateralDwellReady, lateralPointed ? dwellProgress : 0f, _lateralPanelColor);
            ApplyPanelHighlight(_progressPanelGo, progressFocused, progressSelected, progressPointed, pointedFromXR && progressPointed, progressDwellReady, progressPointed ? dwellProgress : 0f, _progressPanelColor);
        }

        private void ApplySelectionHighlight(QuestSelectionController selectionController)
        {
            // Visual selection state is applied in ApplyPanelHighlight via isSelected.
        }

        private void ApplyPanelHighlight(GameObject panel, bool focused, bool selected, bool pointed, bool pointedFromXR, bool dwellReady, float dwellProgress, Color normalColor)
        {
            if (panel == null) return;
            var img = panel.GetComponent<Image>();
            if (img != null)
                img.color = selected ? _selectionTint : (pointed ? (dwellReady ? new Color(0.4f, 0.35f, 0.12f, 0.95f) : (pointedFromXR ? _xrRaycastTint : _pointedTint)) : (focused ? _focusTint : normalColor));
            var rt = panel.GetComponent<RectTransform>();
            if (rt != null)
                rt.localScale = Vector3.one * (selected ? SelectionScale : (pointed ? (dwellReady ? 1.04f : (pointedFromXR ? XRRaycastScale : PointedScale)) : (focused ? FocusScale : 1f)));
            var outline = panel.GetComponent<Outline>();
            if (outline == null) outline = panel.AddComponent<Outline>();
            if (selected)
            {
                outline.effectColor = new Color(0.3f, 0.85f, 0.4f, 0.95f);
                outline.effectDistance = new Vector2(4, 4);
            }
            else if (dwellReady)
            {
                outline.effectColor = new Color(0.95f, 0.8f, 0.2f, 0.95f);
                outline.effectDistance = new Vector2(4, 4);
            }
            else if (pointed)
            {
                outline.effectColor = pointedFromXR ? new Color(0.95f, 0.65f, 0.1f, 0.95f) : new Color(0.9f, 0.7f, 0.2f, 0.9f);
                outline.effectDistance = pointedFromXR ? new Vector2(3, 3) : new Vector2(2, 2);
            }
            else if (focused)
            {
                outline.effectColor = new Color(0.4f, 0.6f, 0.9f, 0.9f);
                outline.effectDistance = new Vector2(3, 3);
            }
            else
                outline.effectDistance = Vector2.zero;

            RefreshDwellProgressOnPanel(panel, pointed, dwellProgress, dwellReady);
        }

        private void RefreshDwellProgressOnPanel(GameObject panel, bool pointed, float dwellProgress, bool dwellReady)
        {
            var progressText = panel.transform.Find("DwellProgressText")?.GetComponent<Text>();
            if (pointed && (dwellProgress > 0f || dwellReady))
            {
                if (progressText == null)
                {
                    var go = new GameObject("DwellProgressText");
                    go.transform.SetParent(panel.transform, false);
                    var rt = go.AddComponent<RectTransform>();
                    rt.anchorMin = new Vector2(0, 0);
                    rt.anchorMax = new Vector2(1, 0);
                    rt.pivot = new Vector2(0.5f, 0f);
                    rt.offsetMin = new Vector2(8, 4);
                    rt.offsetMax = new Vector2(-8, 22);
                    progressText = go.AddComponent<Text>();
                    if (_font != null) progressText.font = _font;
                    progressText.fontSize = 14;
                    progressText.alignment = TextAnchor.LowerCenter;
                    progressText.color = new Color(1f, 0.9f, 0.5f, 0.95f);
                }
                progressText.text = dwellReady ? "Pronto ✓" : string.Format("{0:P0}", dwellProgress);
                progressText.gameObject.SetActive(true);
            }
            else if (progressText != null)
                progressText.gameObject.SetActive(false);
        }

        private void RefreshFocusIndicator(QuestPresentationSession session)
        {
            if (_focusIndicatorText == null) return;
            if (session == null || !session.IsInteractionModeActive)
            {
                _focusIndicatorText.text = "";
                return;
            }
            var targetName = FocusTargetLabel(session.FocusedTargetType);
            var actionHint = FocusActionHint(session.FocusedTargetType);
            _focusIndicatorText.text = "Foco: " + targetName + "  |  Modo interação: Sim  |  Ação: " + actionHint;
        }

        private void RefreshSelectionIndicator(QuestSelectionController selectionController)
        {
            if (_selectionIndicatorText == null) return;
            var target = selectionController?.GetSelectedTarget();
            if (target == null)
            {
                _selectionIndicatorText.text = "Seleção: —  (F/G = navegar, Enter = ativar)";
                return;
            }
            _selectionIndicatorText.text = "Selecionado: " + target.DisplayName + "  |  Ação: " + target.SelectionHint + "  |  Enter = confirmar";
        }

        private void RefreshPointerModeIndicator(QuestPointerPreparationController pointerPrepController, QuestHoverDwellController hoverDwellController = null, QuestPresentationSession session = null)
        {
            if (_pointerModeIndicatorText == null) return;
            var mode = pointerPrepController?.LastSourceMode ?? QuestPointerSourceMode.CenterScreenSimulated;
            var line = "Apontamento: " + PointerSourceModeLabel(mode) + "  (P = alternar)";
            if (hoverDwellController != null && pointerPrepController != null && !string.IsNullOrEmpty(pointerPrepController.GetPointedTargetId()))
            {
                var p = hoverDwellController.GetDwellProgressNormalized();
                var ready = hoverDwellController.CurrentState != null && hoverDwellController.CurrentState.IsDwellReady;
                line += "  |  Dwell: " + (ready ? "pronto" : string.Format("{0:P0}", p));
            }
            if (session != null && session.GazeLikeState != null)
            {
                if (session.CurrentTargetFromGazeLike)
                    line += "  |  Gaze estável";
                else if (session.GazeLikeState.IsActive && session.GazeLikeState.RequiredStabilitySeconds > 0f)
                {
                    var gazeP = Mathf.Clamp01(session.GazeLikeState.StabilityElapsedSeconds / session.GazeLikeState.RequiredStabilitySeconds);
                    line += "  |  Gaze " + string.Format("{0:P0}", gazeP);
                }
            }
            _pointerModeIndicatorText.text = line;
        }

        private static string PointerSourceModeLabel(QuestPointerSourceMode mode)
        {
            switch (mode)
            {
                case QuestPointerSourceMode.FocusDriven: return "FocusDriven";
                case QuestPointerSourceMode.CenterScreenSimulated: return "CenterScreenSimulated";
                case QuestPointerSourceMode.ManualCycleAssisted: return "ManualCycleAssisted";
                default: return "—";
            }
        }

        private static string FocusTargetLabel(QuestPresentationFocusTargetType type)
        {
            switch (type)
            {
                case QuestPresentationFocusTargetType.GuidedStepPanel: return "Passo";
                case QuestPresentationFocusTargetType.HotspotPanel: return "Hotspot";
                case QuestPresentationFocusTargetType.SceneStatePanel: return "Estado cena";
                case QuestPresentationFocusTargetType.ProgressPanel: return "Progresso";
                case QuestPresentationFocusTargetType.ActionPanel: return "Ações";
                default: return "—";
            }
        }

        private static string FocusActionHint(QuestPresentationFocusTargetType type)
        {
            switch (type)
            {
                case QuestPresentationFocusTargetType.GuidedStepPanel: return "Próx. passo";
                case QuestPresentationFocusTargetType.HotspotPanel: return "Próx. hotspot";
                case QuestPresentationFocusTargetType.SceneStatePanel: return "Próx. estado";
                case QuestPresentationFocusTargetType.ProgressPanel: return "Reiniciar";
                case QuestPresentationFocusTargetType.ActionPanel: return "Alternar modo";
                default: return "—";
            }
        }

        /// <summary>Exibe ou oculta a UI espacial.</summary>
        public void SetVisible(bool visible)
        {
            if (_anchor != null)
                _anchor.gameObject.SetActive(visible);
        }

        /// <summary>Retorna true se a UI espacial foi construída com sucesso.</summary>
        public bool IsBuilt => _built;

        private static GameObject CreatePanel(Transform parent, string name, Vector2 anchoredPosition, Vector2 sizeDelta, Color bgColor)
        {
            var go = new GameObject(name);
            go.transform.SetParent(parent, false);
            var rt = go.AddComponent<RectTransform>();
            rt.anchorMin = new Vector2(0.5f, 0.5f);
            rt.anchorMax = new Vector2(0.5f, 0.5f);
            rt.pivot = new Vector2(0.5f, 0.5f);
            rt.anchoredPosition = anchoredPosition;
            rt.sizeDelta = sizeDelta;
            var img = go.AddComponent<Image>();
            img.color = bgColor;
            return go;
        }

        /// <summary>Adiciona collider e marcador para raycast XR no painel.</summary>
        private static void AddRaycastTargetToPanel(GameObject panel, string targetId, QuestPointableTargetType targetType, Vector2 sizeDelta)
        {
            if (panel == null || string.IsNullOrEmpty(targetId)) return;
            var col = panel.AddComponent<BoxCollider>();
            col.isTrigger = true;
            col.size = new Vector3(sizeDelta.x, sizeDelta.y, 10f);
            col.center = Vector3.zero;
            var marker = panel.AddComponent<QuestPointableTargetMarker>();
            marker.SetTarget(targetId, targetType);
        }

        private Text AddLabel(Transform parent, string text, int fontSize, bool bold)
        {
            var go = new GameObject("Label");
            go.transform.SetParent(parent, false);
            var rt = go.AddComponent<RectTransform>();
            rt.anchorMin = new Vector2(0, 0);
            rt.anchorMax = new Vector2(1, 1);
            rt.offsetMin = new Vector2(16, 12);
            rt.offsetMax = new Vector2(-16, -12);
            var t = go.AddComponent<Text>();
            t.text = text;
            t.font = _font;
            t.fontSize = fontSize;
            t.fontStyle = bold ? FontStyle.Bold : FontStyle.Normal;
            t.color = Color.white;
            return t;
        }

        private Button AddSmallButton(Transform parent, string label, System.Action onClick)
        {
            var go = new GameObject("Btn_" + label);
            go.transform.SetParent(parent, false);
            go.AddComponent<LayoutElement>().flexWidth = 1f;
            go.AddComponent<LayoutElement>().preferredHeight = 28f;
            var rt = go.AddComponent<RectTransform>();
            rt.sizeDelta = new Vector2(0, 28f);
            var img = go.AddComponent<Image>();
            img.color = new Color(0.28f, 0.2f, 0.32f, 1f);
            var btn = go.AddComponent<Button>();
            btn.targetGraphic = img;
            if (onClick != null) btn.onClick.AddListener(() => onClick());
            var t = AddLabel(go.transform, label, 12, false);
            t.alignment = TextAnchor.MiddleCenter;
            t.raycastTarget = false;
            return btn;
        }

        private static string NavigationModeLabel(QuestPresentationNavigationMode mode)
        {
            switch (mode)
            {
                case QuestPresentationNavigationMode.Guided: return ModoGuiado;
                case QuestPresentationNavigationMode.Manual: return ModoManual;
                case QuestPresentationNavigationMode.FocusedHotspot: return ModoHotspot;
                default: return "—";
            }
        }
    }
}
