/* eslint-disable no-unused-vars, no-empty, react-hooks/rules-of-hooks */
// =====================================================
// HORMOSCAN - QUIZ ADAPTATIVO INTELIGENTE
// =====================================================
// Sistema com fluxo adaptativo baseado em respostas
// Perguntas personalizadas em tempo real
// =====================================================

import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { supabase } from '../lib/supabaseClient';
import secureStorage from '../lib/secureStorage';
import { useSEO } from '../hooks/useSEO';
import Header from '../components/Header';
import { markQuizCompleted } from '../components/QuizRecoveryBanner';
import logoHormoscan from '../assets/logo fundo transparente.webp';
import { Shield, CheckCircle, ArrowRight, Lock, ChevronRight, ChevronLeft } from 'lucide-react';

// Importar sistema adaptativo
import { useQuizAdaptativo } from '../hooks/quizV2/useQuizAdaptativo';
import { 
  CONFIG_ADAPTATIVO,
  HORMONIOS_RASTREADOS 
} from '../config/quizV2/sistemaAdaptativo';

// Importar novo motor de diagnóstico avançado
import { gerarDiagnosticoCompleto } from '../config/quizV2/adaptadorDiagnostico';

// 🛡️ Importar sistema de validação Zod
import { validarEsanitizarQuiz } from '../config/quizV2/validationSchemas';

// 📝 Logger seguro (silenciado em produção)
import logger from '../lib/logger';

// 📊 Meta Pixel tracking
import { 
  trackQuizStart, trackQuizComplete, trackQuizAnswer, 
  trackQuizProgress, trackEstiloVidaComplete, trackQuizAbandon 
} from '../lib/metaPixel';

// 📊 Analytics Tracking (Supabase)
import { trackQuizFunnel } from '../hooks/useAnalytics';

// Importar componentes V2
import { 
  TimelineInput, 
  BodyMapInput, 
  PressureOrbInput, 
  DualSliderInput, 
  VisualSelectInput,
  EmotionWheelInput,
  TimePickerInput,
  ThermometerInput,
  BatteryGaugeInput,
  SleepQualityGaugeInput,
  FuelGaugeInput,
  FlameGaugeInput,
  PowerMeterInput,
  StressMeterInput,
  MultiSelectInput
} from '../components/quizV2/VisualInputs';
import QuestionShell from '../components/quizV2/QuestionShell';
import CustomSlider from '../components/quizV2/CustomSlider';

// Importar configurações V2
import { 
  INPUT_TYPES,
  CATEGORIAS 
} from '../config/quizV2/perguntasCore';

// 🛡️ Error Boundary especializado para Quiz
import QuizErrorBoundary from '../components/quizV2/QuizErrorBoundary';

// =====================================================
// 🧭 Mapeamento `fatores_vida` (multi-select Onda 3.4) -> formato antigo
// `estiloVida` que o motor V4 espera em AJUSTES_ESTILO_VIDA.
// Sem seleção = baseline neutro/saudável (sem penalidade nem bônus).
// =====================================================
const FATORES_VIDA_NEUTRO = {
  exercicio: 'leve',
  trabalho: 'diurno',
  dieta: 'equilibrada',
  sono_horario: 'regular',
  estresse_trabalho: 'moderado',
  medicamentos: 'nenhum',
  consumo_cafeina: 'nenhum',
};

const mapearFatoresVidaParaEstiloVida = (resposta) => {
  const valor = resposta?.valor ?? resposta;
  const ids = Array.isArray(valor)
    ? valor.map((v) => (typeof v === 'object' ? v.id : v)).filter(Boolean)
    : [];
  if (ids.length === 0) return { ...FATORES_VIDA_NEUTRO };

  const e = { ...FATORES_VIDA_NEUTRO };
  if (ids.includes('sedentario')) e.exercicio = 'sedentario';
  else if (ids.includes('exercicio_intenso')) e.exercicio = 'intenso';
  if (ids.includes('trabalho_noturno')) e.trabalho = 'noturno';
  if (ids.includes('sono_irregular')) e.sono_horario = 'irregular';
  // Se trabalho noturno + sono irregular, considera turnos (penalidade maior)
  if (ids.includes('trabalho_noturno') && ids.includes('sono_irregular')) e.sono_horario = 'turnos';
  if (ids.includes('dieta_sem_controle')) e.dieta = 'sem_controle';
  else if (ids.includes('dieta_restritiva')) e.dieta = 'restritiva';
  if (ids.includes('estresse_alto')) e.estresse_trabalho = 'alto';
  if (ids.includes('cafeina_excessiva')) e.consumo_cafeina = 'excessivo';
  // Medicamentos: prioridade reposição > antidepressivo > anticoncepcional
  if (ids.includes('reposicao_hormonal')) e.medicamentos = 'hormonios';
  else if (ids.includes('antidepressivo')) e.medicamentos = 'antidepressivos';
  else if (ids.includes('anticoncepcional')) e.medicamentos = 'anticoncepcionais';
  return e;
};

// =====================================================
// ESTILOS GLOBAIS - TEMA LIGHT HORMOSCAN V3
// =====================================================
const THEME = {
  // Cores — Hierarquia: primária 70%, accent 20%, secundárias 10%
  primary: '#DD79D4',       // Pink — protagonista
  primaryLight: '#ADC1F9',
  primaryDark: '#B85DAE',
  accent: '#7DC7FA',        // Azul claro — CTAs e estados ativos
  secondary: '#ADC1F9',     // Azul — dados e gráficos
  pink: '#DD79D4',          // Pink — detalhes pontuais
  
  // Backgrounds — clean, light mode
  bgDark: '#F4F1FB',
  bgCard: 'rgba(255, 255, 255, 0.85)',
  bgCardAlt: '#FFFFFF',
  bgInput: '#FFFFFF',
  bgElevated: '#FFFFFF',
  
  // Borders — sutis
  border: 'rgba(26, 22, 37, 0.08)',
  borderFocus: 'rgba(221, 121, 212, 0.5)',
  borderSubtle: 'rgba(26, 22, 37, 0.04)',
  
  // Text — hierarquia forte
  textPrimary: '#1A1625',
  textSecondary: '#7A7189',
  textMuted: '#7A7189',
  textDisabled: '#7A7189',
  
  // Status
  success: '#16A34A',
  warning: '#F59E0B',
  error: '#DC2626',
  info: '#7DC7FA',
  
  // Gradients — uso mínimo
  gradientPrimary: 'linear-gradient(135deg, #DD79D4 0%, #ADC1F9 100%)',
  gradientAccent: 'linear-gradient(135deg, #7DC7FA 0%, #ADC1F9 100%)',
  gradientCard: 'rgba(255, 255, 255, 0.85)',
  gradientCTA: 'linear-gradient(135deg, #7DC7FA 0%, #ADC1F9 35%, #DD79D4 70%, #E9B7EA 100%)',
  
  // Shadows — sutis, light mode
  shadowSm: '0 1px 3px rgba(26, 22, 37, 0.06)',
  shadowMd: '0 4px 12px rgba(26, 22, 37, 0.08)',
  shadowLg: '0 8px 24px rgba(26, 22, 37, 0.10)',
  shadowCard: '0 2px 8px rgba(26, 22, 37, 0.06)',
  shadowCTA: '0 4px 20px rgba(221, 121, 212, 0.15)',
  
  // Spacing system (4px base)
  sp1: '4px', sp2: '8px', sp3: '12px', sp4: '16px',
  sp5: '20px', sp6: '24px', sp8: '32px', sp10: '40px',
  sp12: '48px', sp16: '64px',
  
  // Radius system
  radiusSm: '8px', radiusMd: '12px', radiusLg: '16px', radiusXl: '24px',
  radiusFull: '9999px',
  
  // Font sizes
  textXs: '0.75rem', textSm: '0.875rem', textBase: '1rem',
  textLg: '1.125rem', textXl: '1.25rem', text2xl: '1.5rem',
  text3xl: '2rem', text4xl: '2.5rem',
};

// =====================================================
// COMPONENTE: Tela de Boas-Vindas com Coleta de Dados
// =====================================================
const TelaBoasVindas = ({ onStart, userData }) => {
  // Returning users with a name already saved skip step 0 (name)
  const hasName = !!(userData?.nome || userData?.nome_completo);
  const [step, setStep] = useState(hasName ? 1 : 0); // 0=nome, 1=idade+sexo, 2=peso+altura
  const [dados, setDados] = useState({
    nome: userData?.nome || userData?.nome_completo || '',
    idade: userData?.idade || '',
    sexo: userData?.sexo || userData?.genero || '',
    peso: userData?.peso || '',
    altura: userData?.altura || ''
  });
  const [errors, setErrors] = useState({});
  const [isLoading, setIsLoading] = useState(false);

  // Check for saved progress
  const [savedProgress, setSavedProgress] = useState(null);
  useEffect(() => {
    try {
      const saved = secureStorage.getItem('hormoscan_quiz_progress');
      if (saved) {
        const data = JSON.parse(saved);
        const age = Date.now() - data.timestamp;
        if (data.versao === '2.1' && age < 24 * 60 * 60 * 1000 && data.totalRespondidas > 3) {
          setSavedProgress(data);
        }
      }
    } catch {}
  }, []);

  useEffect(() => {
    if (userData) {
      setDados(prev => ({
        ...prev,
        nome: userData.nome || userData.nome_completo || prev.nome,
        idade: userData.idade || prev.idade,
        sexo: userData.sexo || userData.genero || prev.sexo
      }));
    }
  }, [userData]);

  const handleChange = (field, value) => {
    // Parse numeric fields to avoid NaN in calculations (IMC, scoring)
    const numericFields = ['idade', 'peso', 'altura'];
    const parsed = numericFields.includes(field) ? (value === '' ? '' : Number(value)) : value;
    setDados(prev => ({ ...prev, [field]: parsed }));
    if (errors[field]) setErrors(prev => ({ ...prev, [field]: null }));
  };

  // Haptic feedback
  const haptic = (ms = 10) => { try { navigator?.vibrate?.(ms); } catch {} };

  const validateStep = () => {
    const newErrors = {};
    if (step === 0 && !dados.nome.trim()) newErrors.nome = 'Digite seu nome';
    if (step === 1) {
      if (!dados.idade) newErrors.idade = 'Informe sua idade';
      else if (dados.idade < 18 || dados.idade > 100) newErrors.idade = 'Entre 18 e 100';
      if (!dados.sexo) newErrors.sexo = 'Selecione';
    }
    if (step === 2) {
      if (!dados.peso) newErrors.peso = 'Informe seu peso';
      else if (dados.peso < 30 || dados.peso > 300) newErrors.peso = '30-300 kg';
      if (!dados.altura) newErrors.altura = 'Informe sua altura';
      else if (dados.altura < 100 || dados.altura > 250) newErrors.altura = '100-250 cm';
    }
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleNext = () => {
    if (!validateStep()) return;
    haptic();
    if (step < 2) {
      setStep(s => s + 1);
    } else {
      setIsLoading(true);
      const alturaM = dados.altura / 100;
      const imc = (dados.peso / (alturaM * alturaM)).toFixed(1);
      setTimeout(() => onStart({ ...dados, imc: parseFloat(imc) }), 400);
    }
  };

  const inputStyle = useCallback((hasError) => ({
    width: '100%',
    padding: 'clamp(14px, 2vw, 18px) clamp(14px, 2vw, 18px)',
    background: THEME.bgInput,
    border: hasError ? `2px solid ${THEME.error}` : `1px solid ${THEME.border}`,
    borderRadius: THEME.radiusMd,
    color: THEME.textPrimary,
    fontSize: 'clamp(1rem, 1.5vw, 1.1rem)',
    fontFamily: 'inherit',
    outline: 'none',
    transition: 'border-color 0.2s, box-shadow 0.2s',
  }), []);

  const labelStyle = {
    display: 'flex',
    alignItems: 'center',
    gap: '6px',
    marginBottom: '8px',
    color: THEME.textSecondary,
    fontSize: 'clamp(0.875rem, 1.2vw, 1rem)',
    fontWeight: 500,
    letterSpacing: '-0.01em',
  };

  const steps = [
    { label: 'Perfil', icon: '👤' },
    { label: 'Dados', icon: '📋' },
    { label: 'Medidas', icon: '📏' },
  ];

  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0, x: -40 }}
      transition={{ duration: 0.3 }}
      style={{
        maxWidth: '560px',
        width: '100%',
        margin: '0 auto',
        padding: 'clamp(1.5rem, 4vw, 3rem) clamp(1rem, 3vw, 2rem)',
      }}
    >
      {/* Header */}
      <div style={{ textAlign: 'center', marginBottom: THEME.sp10 }}>
        {/* Resume saved progress banner */}
        {savedProgress && (
          <motion.div
            initial={{ opacity: 0, y: -10 }}
            animate={{ opacity: 1, y: 0 }}
            style={{
              padding: '14px 18px',
              background: 'rgba(34, 197, 94, 0.08)',
              border: '1px solid rgba(34, 197, 94, 0.2)',
              borderRadius: THEME.radiusMd,
              marginBottom: THEME.sp5,
              textAlign: 'left',
            }}
          >
            <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '8px' }}>
              <span style={{ fontSize: '1.1rem' }}>📋</span>
              <span style={{ color: '#16A34A', fontWeight: 600, fontSize: THEME.textSm }}>
                Análise incompleta encontrada
              </span>
            </div>
            <p style={{ color: THEME.textSecondary, fontSize: THEME.textXs, margin: '0 0 10px' }}>
              Você respondeu {savedProgress.totalRespondidas} perguntas. Quer continuar de onde parou?
            </p>
            <div style={{ display: 'flex', gap: '8px' }}>
              <button
                onClick={() => {
                  // Start quiz with saved data — the hook restores automatically
                  // Restaurar dados do usuário salvos (peso/altura/nome)
                  let dadosSalvos = {};
                  try {
                    const raw = localStorage.getItem('hormoscan_quiz_dados_usuario');
                    if (raw) dadosSalvos = JSON.parse(raw);
                  } catch {}
                  const pesoSalvo = dadosSalvos.peso || savedProgress.peso || 70;
                  const alturaSalva = dadosSalvos.altura || savedProgress.altura || 170;
                  const alturaM = alturaSalva / 100;
                  const imcCalc = pesoSalvo / (alturaM * alturaM);
                  onStart({ 
                    nome: dadosSalvos.nome || savedProgress.nome || 'Você', 
                    idade: Math.max(18, Math.min(100, dadosSalvos.idade || savedProgress.idade || 30)), 
                    sexo: dadosSalvos.sexo || savedProgress.genero || 'feminino',
                    peso: pesoSalvo, altura: alturaSalva, imc: Math.round(imcCalc * 10) / 10
                  });
                }}
                style={{
                  flex: 1, padding: '8px 14px',
                  background: 'rgba(34, 197, 94, 0.15)',
                  border: '1px solid rgba(34, 197, 94, 0.3)',
                  borderRadius: THEME.radiusSm,
                  color: '#16A34A', fontWeight: 600, fontSize: THEME.textSm,
                  cursor: 'pointer', fontFamily: 'inherit',
                }}
              >
                Continuar ({savedProgress.totalRespondidas} respondidas)
              </button>
              <button
                onClick={() => {
                  secureStorage.removeItem('hormoscan_quiz_progress');
                  setSavedProgress(null);
                }}
                style={{
                  padding: '8px 14px',
                  background: 'transparent',
                  border: `1px solid ${THEME.border}`,
                  borderRadius: THEME.radiusSm,
                  color: THEME.textMuted, fontSize: THEME.textSm,
                  cursor: 'pointer', fontFamily: 'inherit',
                }}
              >
                Recomeçar
              </button>
            </div>
          </motion.div>
        )}

        <motion.div
          initial={{ opacity: 0, scale: 0.9 }}
          animate={{ opacity: 1, scale: 1 }}
          transition={{ type: 'spring', stiffness: 200 }}
          style={{
            display: 'inline-flex',
            alignItems: 'center',
            gap: '8px',
            padding: '8px 20px',
            background: 'rgba(221, 121, 212, 0.1)',
            border: '1px solid rgba(221, 121, 212, 0.2)',
            borderRadius: THEME.radiusFull,
            marginBottom: THEME.sp4,
          }}
        >
          <Shield size={14} color={THEME.primary} />
          <span style={{ color: THEME.textSecondary, fontSize: THEME.textSm, fontWeight: 500 }}>
            Teste 100% gratuito e confidencial
          </span>
        </motion.div>
        <h1 style={{ 
          fontSize: 'clamp(1.75rem, 5vw, 2.5rem)', 
          fontWeight: 800, 
          color: THEME.textPrimary,
          letterSpacing: '-0.03em',
          lineHeight: 1.15,
          marginBottom: THEME.sp3,
        }}>
          Análise Hormonal
        </h1>
        <p style={{ 
          color: THEME.textSecondary, 
          fontSize: 'clamp(1rem, 1.5vw, 1.1rem)',
          lineHeight: 1.6,
          maxWidth: '420px',
          margin: '0 auto',
        }}>
          Responda com honestidade. Cada detalhe importa para a precisão do seu resultado.
        </p>
      </div>

      {/* Step indicators - Premium numbered */}
      <div style={{ 
        display: 'flex', 
        alignItems: 'center', 
        gap: THEME.sp3, 
        marginBottom: THEME.sp8,
        justifyContent: 'center',
      }}>
        {steps.map((s, i) => (
          <React.Fragment key={i}>
            <div style={{ 
              display: 'flex', alignItems: 'center', gap: '8px',
            }}>
              <div style={{
                width: '32px', height: '32px',
                borderRadius: '50%',
                background: i < step ? THEME.success : i === step ? THEME.primary : 'transparent',
                border: i <= step ? 'none' : `1px solid ${THEME.border}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                color: i <= step ? '#fff' : THEME.textMuted,
                fontSize: THEME.textSm, fontWeight: 700,
                transition: 'all 0.3s ease',
                boxShadow: i === step ? '0 0 16px rgba(221, 121, 212, 0.3)' : 'none',
              }}>
                {i < step ? <CheckCircle size={16} /> : i + 1}
              </div>
              <span style={{ 
                color: i <= step ? THEME.textPrimary : THEME.textMuted, 
                fontSize: THEME.textSm, fontWeight: i === step ? 600 : 400,
              }}
              className="step-label-desktop"
              >
                {s.label}
              </span>
            </div>
            {i < steps.length - 1 && (
              <div style={{
                width: 'clamp(24px, 5vw, 48px)', height: '2px',
                background: i < step ? THEME.success : THEME.border,
                borderRadius: '1px',
                transition: 'background 0.4s ease',
              }} />
            )}
          </React.Fragment>
        ))}
      </div>

      {/* Form card */}
      <motion.div
        layout
        style={{
          background: THEME.bgCard,
          border: `1px solid ${THEME.border}`,
          borderRadius: THEME.radiusXl,
          padding: 'clamp(1.5rem, 4vw, 2.5rem)',
          boxShadow: '0 8px 32px rgba(26, 22, 37, 0.10), 0 0 1px rgba(221, 121, 212, 0.1)',
          position: 'relative',
          overflow: 'hidden',
        }}
      >
        {/* Subtle top accent line */}
        <div style={{
          position: 'absolute', top: 0, left: 0, right: 0, height: '3px',
          background: step === 2 ? THEME.success : THEME.gradientPrimary,
          transition: 'background 0.4s ease',
        }} />

        {/* Auto-fill indicator */}
        {step === 0 && (dados.nome || dados.idade || dados.sexo) && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            style={{
              display: 'flex', alignItems: 'center', gap: THEME.sp2,
              padding: `${THEME.sp2} ${THEME.sp3}`,
              background: 'rgba(34, 197, 94, 0.08)',
              border: '1px solid rgba(34, 197, 94, 0.15)',
              borderRadius: THEME.radiusSm,
              marginBottom: THEME.sp4,
              fontSize: THEME.textSm, color: THEME.success,
            }}
          >
            <CheckCircle size={14} /> Dados do perfil carregados
          </motion.div>
        )}

        {/* Step title inside card */}
        <div style={{ marginBottom: THEME.sp5 }}>
          <p style={{ 
            color: THEME.textMuted, fontSize: THEME.textXs, fontWeight: 600,
            textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: '4px',
          }}>
            Etapa {step + 1} de 3
          </p>
          <h3 style={{ 
            color: THEME.textPrimary, fontSize: 'clamp(1.1rem, 2vw, 1.3rem)', fontWeight: 700,
            letterSpacing: '-0.02em', margin: 0,
          }}>
            {step === 0 && 'Como você se chama?'}
            {step === 1 && `Prazer, ${dados.nome}!`}
            {step === 2 && 'Quase lá! Suas medidas'}
          </h3>
        </div>

        <AnimatePresence mode="wait">
          {/* Step 0: Nome */}
          {step === 0 && (
            <motion.div key="step0" initial={{ opacity: 0, x: 30 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -30 }} transition={{ duration: 0.25 }}>
              <label htmlFor="quiz-nome" style={labelStyle}>
                Seu primeiro nome
              </label>
              <input
                id="quiz-nome" name="nome"
                type="text" value={dados.nome} autoFocus
                onChange={(e) => handleChange('nome', e.target.value)}
                onKeyDown={(e) => e.key === 'Enter' && handleNext()}
                placeholder="Como podemos te chamar?"
                style={inputStyle(errors.nome)}
                onFocus={(e) => { e.target.style.borderColor = THEME.primary; e.target.style.boxShadow = `0 0 0 3px rgba(221, 121, 212,0.1)`; }}
                onBlur={(e) => { e.target.style.borderColor = errors.nome ? THEME.error : THEME.border; e.target.style.boxShadow = 'none'; }}
              />
              {errors.nome && <p style={{ color: THEME.error, fontSize: THEME.textXs, marginTop: '4px' }}>{errors.nome}</p>}
            </motion.div>
          )}

          {/* Step 1: Idade + Sexo */}
          {step === 1 && (
            <motion.div key="step1" initial={{ opacity: 0, x: 30 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -30 }} transition={{ duration: 0.25 }}>
              <p style={{ color: THEME.textSecondary, fontSize: THEME.textSm, marginBottom: THEME.sp5 }}>
                Precisamos de mais alguns dados para calibrar sua análise com precisão.
              </p>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: THEME.sp5, marginBottom: 0 }}>
                <div>
                  <label htmlFor="quiz-idade" style={labelStyle}>Idade</label>
                  <input id="quiz-idade" name="idade" type="number" value={dados.idade} autoFocus
                    onChange={(e) => handleChange('idade', e.target.value)}
                    onKeyDown={(e) => e.key === 'Enter' && handleNext()}
                    placeholder="35" min="18" max="100" style={inputStyle(errors.idade)}
                  />
                  {errors.idade && <p style={{ color: THEME.error, fontSize: THEME.textXs, marginTop: '4px' }}>{errors.idade}</p>}
                </div>
                <div>
                  <label htmlFor="quiz-sexo" style={labelStyle}>Sexo biológico</label>
                  <select id="quiz-sexo" name="sexo" value={dados.sexo} onChange={(e) => handleChange('sexo', e.target.value)}
                    aria-label="Sexo biológico" style={{ ...inputStyle(errors.sexo), color: dados.sexo ? THEME.textPrimary : THEME.textMuted, fontFamily: 'inherit' }}>
                    <option value="" style={{ color: '#7A7189', background: '#F4F1FB' }}>Selecione</option>
                    <option value="feminino" style={{ color: '#1A1625', background: '#F4F1FB' }}>Feminino</option>
                    <option value="masculino" style={{ color: '#1A1625', background: '#F4F1FB' }}>Masculino</option>
                  </select>
                  {errors.sexo && <p style={{ color: THEME.error, fontSize: THEME.textXs, marginTop: '4px' }}>{errors.sexo}</p>}
                </div>
              </div>
            </motion.div>
          )}

          {/* Step 2: Peso + Altura */}
          {step === 2 && (
            <motion.div key="step2" initial={{ opacity: 0, x: 30 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -30 }} transition={{ duration: 0.25 }}>
              <p style={{ color: THEME.textSecondary, fontSize: THEME.textSm, marginBottom: THEME.sp5 }}>
                Suas medidas são essenciais para calcular o IMC e personalizar a análise.
              </p>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: THEME.sp5 }}>
                <div>
                  <label htmlFor="quiz-peso" style={labelStyle}>Peso (kg)</label>
                  <input id="quiz-peso" name="peso" type="number" value={dados.peso} autoFocus
                    onChange={(e) => handleChange('peso', e.target.value)}
                    onKeyDown={(e) => e.key === 'Enter' && handleNext()}
                    placeholder="70" min="30" max="300" step="0.1" style={inputStyle(errors.peso)}
                  />
                  {errors.peso && <p style={{ color: THEME.error, fontSize: THEME.textXs, marginTop: '4px' }}>{errors.peso}</p>}
                </div>
                <div>
                  <label htmlFor="quiz-altura" style={labelStyle}>Altura (cm)</label>
                  <input id="quiz-altura" name="altura" type="number" value={dados.altura}
                    onChange={(e) => handleChange('altura', e.target.value)}
                    onKeyDown={(e) => e.key === 'Enter' && handleNext()}
                    placeholder="165" min="100" max="250" style={inputStyle(errors.altura)}
                  />
                  {errors.altura && <p style={{ color: THEME.error, fontSize: THEME.textXs, marginTop: '4px' }}>{errors.altura}</p>}
                </div>
              </div>
            </motion.div>
          )}
        </AnimatePresence>

        {/* Navigation */}
        <div style={{ display: 'flex', gap: THEME.sp3, marginTop: THEME.sp6 }}>
          {step > 0 && (
            <motion.button
              whileTap={{ scale: 0.97 }}
              onClick={() => { haptic(5); setStep(s => s - 1); }}
              style={{
                padding: '14px 20px', background: 'transparent',
                border: `1px solid ${THEME.border}`, borderRadius: THEME.radiusMd,
                color: THEME.textSecondary, fontWeight: 500, fontSize: THEME.textSm,
                cursor: 'pointer', fontFamily: 'inherit',
              }}
            >
              Voltar
            </motion.button>
          )}
          <motion.button
            whileTap={{ scale: 0.97 }}
            onClick={handleNext}
            disabled={isLoading}
            style={{
              flex: 1, padding: '14px 24px',
              background: THEME.gradientPrimary,
              border: 'none', borderRadius: THEME.radiusFull,
              color: '#fff', fontWeight: 600, fontSize: THEME.textBase,
              cursor: isLoading ? 'wait' : 'pointer',
              boxShadow: THEME.shadowCTA,
              opacity: isLoading ? 0.7 : 1,
              fontFamily: 'inherit',
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: THEME.sp2,
            }}
          >
            {isLoading ? 'Preparando...' : step < 2 ? 'Continuar' : 'Começar Análise'}
            {!isLoading && <ArrowRight size={18} />}
          </motion.button>
        </div>
      </motion.div>

      {/* Trust signal - minimal */}
      <p style={{ 
        color: THEME.textMuted, fontSize: THEME.textXs, 
        marginTop: THEME.sp6, textAlign: 'center',
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '6px',
      }}>
        <Lock size={12} /> Dados privados e criptografados
      </p>
    </motion.div>
  );
};


// =====================================================
// COMPONENTE: Barra de Progresso Adaptativa
// ✅ Memoizado para evitar re-renders desnecessários
// =====================================================

// Milestone messages by progress percentage
const MILESTONE_MESSAGES = [
  { at: 20, text: 'Ótimo começo! ✨', color: '#DD79D4' },
  { at: 40, text: 'Seus padrões hormonais estão emergindo...', color: '#ADC1F9' },
  { at: 55, text: 'Metade concluída! Análise ficando precisa 🎯', color: '#F59E0B' },
  { at: 70, text: 'Padrão interessante detectado no seu perfil...', color: '#7DC7FA' },
  { at: 85, text: 'Quase lá! Finalizando seu mapa hormonal 🧬', color: '#16A34A' },
  { at: 95, text: 'Últimas perguntas... resultado quase pronto!', color: '#E9B7EA' },
];

// Catalogo de categorias para os chips do progresso. Ordem reflete o fluxo
// tipico do quiz adaptativo. Cada chip tem 3 estados: visitada (✓), atual
// (animada) e pendente (cinza). Dado leigo nao ve nomes tecnicos como
// "investigando: cortisol" — ve apenas a categoria humana.
const CATEGORIAS_CHIPS = [
  { id: 'energia',     nome: 'Energia',     icone: '⚡', cor: '#F59E0B' },
  { id: 'sono',        nome: 'Sono',        icone: '🌙', cor: '#7DC7FA' },
  { id: 'metabolismo', nome: 'Metabolismo', icone: '🔥', cor: '#DC2626' },
  { id: 'humor',       nome: 'Humor',       icone: '😊', cor: '#E9B7EA' },
  { id: 'mental',      nome: 'Foco',        icone: '🧠', cor: '#7DC7FA' },
  { id: 'fisico',      nome: 'Físico',      icone: '💪', cor: '#16A34A' },
];

const ProgressBar = React.memo(({ progresso, perguntasRespondidas, totalEstimado, categoria, tipoPergunta, hormonioInvestigando, scoresPreview, categoriasVisitadas, tempoDecorrido }) => {
  const progressoPercent = Math.round(progresso * 100);
  const [milestoneMsg, setMilestoneMsg] = useState(null);
  const lastMilestoneRef = useRef(0);

  // Show milestone message when crossing thresholds
  useEffect(() => {
    const milestone = MILESTONE_MESSAGES.filter(m => progressoPercent >= m.at && m.at > lastMilestoneRef.current).pop();
    if (milestone) {
      lastMilestoneRef.current = milestone.at;
      setMilestoneMsg(milestone);
      const timer = setTimeout(() => setMilestoneMsg(null), 3000);
      return () => clearTimeout(timer);
    }
  }, [progressoPercent]);

  // Determinar cor baseada no tipo de pergunta
  const corProgresso = tipoPergunta === 'aprofundamento'
    ? 'linear-gradient(135deg, #F59E0B 0%, #DC2626 100%)'
    : 'linear-gradient(135deg, #DD79D4 0%, #ADC1F9 100%)';

  // ID e nome da categoria atual
  const catAtualId = typeof categoria === 'object' ? categoria?.id : categoria;
  const catAtualNome = (typeof categoria === 'object' ? categoria?.nome : categoria) || 'Análise';
  // Em aprofundamento, mostra "[Categoria] · análise extra" no nome — UNICO header,
  // sem badge separado de "Investigação aprofundada".
  const nomeCategoria = tipoPergunta === 'aprofundamento'
    ? `${catAtualNome} · análise extra`
    : catAtualNome;
  // Suprimir warning de var nao usada
  void hormonioInvestigando;

  // Tempo estimado restante (~25s por pergunta)
  const restantes = Math.max(0, (totalEstimado || 20) - (perguntasRespondidas || 0));
  const minutosRestantes = Math.ceil((restantes * 25) / 60);

  return (
    <div style={{ marginBottom: '2rem' }}>
      {/* Milestone message */}
      <AnimatePresence>
        {milestoneMsg && (
          <motion.div
            initial={{ opacity: 0, y: -8, height: 0 }}
            animate={{ opacity: 1, y: 0, height: 'auto' }}
            exit={{ opacity: 0, y: -8, height: 0 }}
            style={{
              padding: '8px 14px',
              background: `${milestoneMsg.color}10`,
              border: `1px solid ${milestoneMsg.color}25`,
              borderRadius: THEME.radiusSm,
              marginBottom: '10px',
              fontSize: THEME.textSm,
              color: milestoneMsg.color,
              fontWeight: 500,
              textAlign: 'center',
            }}
          >
            {milestoneMsg.text}
          </motion.div>
        )}
      </AnimatePresence>

      {/* Indicador de tipo removido 2026-04 — header unificado em
          nomeCategoria ("[Categoria] · análise extra") evita duplicacao
          com label de aprofundamento. */}

      {/* Progress bar */}
      <div style={{
        height: '6px',
        background: 'rgba(221, 121, 212, 0.2)',
        borderRadius: '3px',
        overflow: 'hidden',
        marginBottom: '0.6rem'
      }}>
        <motion.div
          initial={{ width: 0 }}
          animate={{ width: `${progressoPercent}%` }}
          transition={{ duration: 0.5, ease: 'easeOut' }}
          style={{
            height: '100%',
            background: corProgresso,
            borderRadius: '3px'
          }}
        />
      </div>

      {/* Info: categoria/numero/tempo */}
      <div style={{
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        fontSize: THEME.textXs,
        color: THEME.textMuted,
        marginBottom: '0.7rem',
      }}>
        <span style={{ fontWeight: 500 }}>{nomeCategoria}</span>
        <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
          {/* Live timer — mostra tempo decorrido desde início da análise */}
          {tempoDecorrido > 0 && (
            <span style={{ display: 'flex', alignItems: 'center', gap: '3px', opacity: 0.6 }}>
              ⏱ {Math.floor(tempoDecorrido / 60) > 0 && `${Math.floor(tempoDecorrido / 60)}m `}{String(tempoDecorrido % 60).padStart(2, '0')}s
            </span>
          )}
          {/* Contador ancorado: x/20 até 20, depois só o número — anchoring psicológico */}
          <span>
            {perguntasRespondidas <= 20
              ? `${perguntasRespondidas}/20`
              : `${perguntasRespondidas}`}
          </span>
        </div>
      </div>

      {/* Chips de categorias — visitada, atual, pendente */}
      <div
        style={{
          display: 'flex',
          gap: '0.3rem',
          overflowX: 'auto',
          paddingBottom: '2px',
          marginBottom: '0.5rem',
          scrollbarWidth: 'none',
        }}
      >
        {CATEGORIAS_CHIPS.map((cat) => {
          const visitada = categoriasVisitadas?.has(cat.id);
          const isAtual = cat.id === catAtualId;
          const isPendente = !visitada && !isAtual;
          return (
            <motion.div
              key={cat.id}
              animate={isAtual ? { scale: [1, 1.05, 1] } : { scale: 1 }}
              transition={isAtual ? { duration: 1.4, repeat: Infinity, ease: 'easeInOut' } : { duration: 0.2 }}
              style={{
                flexShrink: 0,
                display: 'inline-flex', alignItems: 'center', gap: '4px',
                padding: '0.3rem 0.6rem',
                borderRadius: 999,
                fontSize: '0.7rem',
                fontWeight: 700,
                letterSpacing: '0.02em',
                background: isAtual
                  ? `${cat.cor}1f`
                  : visitada
                    ? 'rgba(34, 197, 94, 0.1)'
                    : 'rgba(143, 130, 158, 0.1)',
                border: isAtual
                  ? `1.5px solid ${cat.cor}55`
                  : visitada
                    ? '1px solid rgba(34, 197, 94, 0.3)'
                    : '1px solid rgba(143, 130, 158, 0.18)',
                color: isAtual ? cat.cor : visitada ? '#16A34A' : '#9C94AB',
                opacity: isPendente ? 0.6 : 1,
                whiteSpace: 'nowrap',
              }}
            >
              {visitada && !isAtual ? '✓' : <span aria-hidden>{cat.icone}</span>}
              <span>{cat.nome}</span>
            </motion.div>
          );
        })}
      </div>

      {/* Onda 4.6: Hormone analysis counter REMOVIDO — pessoa pesquisa
          os nomes dos hormônios no YouTube e polui visualmente o header. */}
    </div>
  );
});

// =====================================================
// COMPONENTE: Slider Simples (estilizado dark)
// ✅ Memoizado para evitar re-renders desnecessários
// =====================================================
const SliderSimples = React.memo(({ pergunta, onComplete, onInteraction }) => {
  const config = pergunta?.config || {};
  const min = config.min || 0;
  const max = config.max || 10;
  // Onda 4.6: config.labels SEMPRE prevalece (sem misturar com universais).
  // CustomSlider interpola via closestKey, entao 3 labels esparsos funcionam.
  // Quando a pergunta nao define labels, usa fallback contextual (frases curtas).
  const labelsFallback = {
    0: 'Muito baixo', 2: 'Baixo', 4: 'Abaixo da média',
    5: 'Médio', 6: 'Levemente acima', 8: 'Bom', 10: 'Excelente',
  };
  const labels = Object.keys(config.labels || {}).length > 0
    ? config.labels
    : labelsFallback;
  const emojis = config.emojis || {};
  const inverterCores = config.inverterCores || false;

  const valorInicial = Math.round((min + max) / 2);
  const [valor, setValor] = useState(valorInicial);

  const handleChange = (novoValor) => {
    setValor(novoValor);
    onInteraction?.('slider_change', { valor: novoValor });
  };

  return (
    <QuestionShell
      pergunta={pergunta}
      categoria={pergunta?.categoria}
      numeroAtual={pergunta?.numero}
      titulo={pergunta?.titulo || pergunta?.texto || 'Avalie de 0 a 10'}
      subtitulo={pergunta?.subtitulo || pergunta?.descricao}
      ajuda={pergunta?.ajuda}
      ajudaPrivada={pergunta?.ajudaPrivada}
      helperText="Arraste pra ajustar"
      helperIcon={<>👆</>}
      hasValidValue={true}
      onConfirm={() => onComplete?.(valor)}
    >
      <CustomSlider
        min={min}
        max={max}
        step={1}
        value={valor}
        onChange={handleChange}
        labels={labels}
        emojis={emojis}
        inverse={inverterCores}
        ariaLabel={pergunta?.titulo}
      />
    </QuestionShell>
  );
});

// Helpers do SliderSimples antigo (touched, getCorPorValor, getLabelAtual,
// getEmojiAtual, motion.div de valor, slider nativo, botao manual) substituidos
// por QuestionShell + CustomSlider acima — design system unificado.

// =====================================================
// COMPONENTE: Múltipla Escolha (estilizado dark)
// ✅ Memoizado para evitar re-renders desnecessários
// =====================================================
const MultiplaEscolha = React.memo(({ pergunta, onComplete, onInteraction }) => {
  const opcoes = pergunta?.opcoes || [];
  const [selecionada, setSelecionada] = useState(null);

  const handleSelect = (index) => {
    setSelecionada(index);
    onInteraction?.('option_select', { index });
    
    // Auto-avançar após pequeno delay
    setTimeout(() => {
      onComplete?.(opcoes[index]);
    }, 300);
  };

  return (
    <div style={{ padding: '1rem' }}>
      {/* Título */}
      <div style={{ textAlign: 'center', marginBottom: THEME.sp5 }}>
        <h3 style={{ 
          fontSize: THEME.textLg, 
          fontWeight: 600, 
          color: THEME.textPrimary,
          marginBottom: THEME.sp2,
          letterSpacing: '-0.01em',
        }}>
          {pergunta?.titulo || pergunta?.texto}
        </h3>
        {(pergunta?.subtitulo || pergunta?.descricao) && (
          <p style={{ fontSize: THEME.textSm, color: THEME.textSecondary }}>
            {pergunta.subtitulo || pergunta.descricao}
          </p>
        )}
      </div>

      {/* Opções */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: THEME.sp3 }}>
        {opcoes.map((opcao, index) => (
          <motion.button
            key={index}
            type="button"
            onClick={() => handleSelect(index)}
            whileTap={{ scale: 0.98 }}
            transition={{ duration: 0.15 }}
            style={{
              width: '100%',
              padding: '14px 16px',
              background: selecionada === index 
                ? 'rgba(221, 121, 212, 0.1)'
                : THEME.bgCard,
              border: selecionada === index 
                ? `2px solid ${THEME.primary}` 
                : `1px solid ${THEME.border}`,
              borderRadius: THEME.radiusMd,
              color: selecionada === index ? THEME.primaryLight : THEME.textPrimary,
              fontSize: THEME.textBase,
              fontWeight: selecionada === index ? 600 : 400,
              cursor: 'pointer',
              textAlign: 'left',
              display: 'flex',
              alignItems: 'center',
              gap: THEME.sp3,
              fontFamily: 'inherit',
              transition: 'border-color 0.2s ease, background 0.2s ease',
              outline: 'none',
            }}
          >
            {/* Indicador */}
            <div style={{
              width: '20px',
              height: '20px',
              borderRadius: '50%',
              border: `2px solid ${selecionada === index ? THEME.primary : THEME.border}`,
              background: selecionada === index ? THEME.primary : 'transparent',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              flexShrink: 0,
              transition: 'all 0.2s ease',
            }}>
              {selecionada === index && (
                <motion.div
                  initial={{ scale: 0 }}
                  animate={{ scale: 1 }}
                >
                  <CheckCircle size={12} color="#fff" />
                </motion.div>
              )}
            </div>
            
            {/* Texto */}
            <span>{opcao.texto || opcao.label}</span>
          </motion.button>
        ))}
      </div>
    </div>
  );
});

// =====================================================
// COMPONENTE: Renderizador de Pergunta Universal
// ✅ Memoizado para evitar re-renders desnecessários
// =====================================================
const PerguntaUniversal = React.memo(({ pergunta, onComplete, onInteraction }) => {
  const tipo = pergunta?.tipo || pergunta?.tipoInput || 'multipla_escolha';

  // Container minimalista
  const containerStyle = {
    maxWidth: '560px',
    margin: '0 auto'
  };

  // Categoria badge
  const categoriaNome = typeof pergunta?.categoria === 'object' 
    ? pergunta.categoria.nome 
    : pergunta?.categoria;

  const renderInput = () => {
    switch (tipo) {
      case INPUT_TYPES.BATTERY_GAUGE:
      case 'battery_gauge':
        return (
          <BatteryGaugeInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.SLEEP_QUALITY_GAUGE:
      case 'sleep_quality_gauge':
        return (
          <SleepQualityGaugeInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.SLIDER:
      case 'slider':
        return (
          <SliderSimples
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.TIMELINE:
      case 'timeline':
        return (
          <TimelineInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.BODY_MAP:
      case 'body_map':
        return (
          <BodyMapInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
            maxSelecoes={pergunta.config?.maxSelecoes || 5}
          />
        );

      case INPUT_TYPES.PRESSURE_ORB:
      case 'pressure_orb':
        return (
          <PressureOrbInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.DUAL_SLIDER:
      case 'dual_slider':
        return (
          <DualSliderInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.VISUAL_SELECT:
      case 'visual_select':
        return (
          <VisualSelectInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
            multiplo={pergunta.config?.multiplo || false}
            maxSelecoes={pergunta.config?.maxSelecoes || 3}
          />
        );

      case INPUT_TYPES.EMOTION_WHEEL:
      case 'emotion_wheel':
        return (
          <EmotionWheelInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.TIME_PICKER:
      case 'time_picker':
        return (
          <TimePickerInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.THERMOMETER:
      case 'thermometer':
        return (
          <ThermometerInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.FUEL_GAUGE:
      case 'fuel_gauge':
        return (
          <FuelGaugeInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.FLAME_GAUGE:
      case 'flame_gauge':
        return (
          <FlameGaugeInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.POWER_METER:
      case 'power_meter':
        return (
          <PowerMeterInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.STRESS_METER:
      case 'stress_meter':
        return (
          <StressMeterInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      case INPUT_TYPES.MULTI_SELECT:
      case 'multi_select':
        return (
          <MultiSelectInput
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );

      default:
        return (
          <MultiplaEscolha
            pergunta={pergunta}
            onComplete={onComplete}
            onInteraction={onInteraction}
          />
        );
    }
  };

  return (
    <AnimatePresence mode="wait" initial={false}>
      <motion.div
        key={pergunta?.id}
        initial={{ opacity: 0, x: 32, scale: 0.98 }}
        animate={{ opacity: 1, x: 0, scale: 1 }}
        exit={{ opacity: 0, x: -32, scale: 0.98 }}
        transition={{ duration: 0.32, ease: [0.22, 1, 0.36, 1] }}
        style={containerStyle}
      >
        {renderInput()}
      </motion.div>
    </AnimatePresence>
  );
});


// =====================================================
// COMPONENTE: Tela de Processamento - DESIGN PREMIUM
// =====================================================
const TelaProcessamento = ({ onComplete, dadosUsuario }) => {
  const [etapa, setEtapa] = useState(0);
  const [progresso, setProgresso] = useState(0);
  const [checkmarks, setCheckmarks] = useState([]);
  const [contadorMarcadores, setContadorMarcadores] = useState(0);

  const nomeUsuario = dadosUsuario?.nome || 'você';
  const primeiroNome = nomeUsuario.split(' ')[0];

  // Etapas mais cinematograficas — focadas em PRECISAO + RARIDADE
  const etapas = [
    { texto: 'Suas respostas estão sendo cruzadas...', detalhe: '30+ marcadores hormonais identificados' },
    { texto: 'Comparando com 10 hormônios principais...', detalhe: 'Correlações sendo desenhadas' },
    { texto: `Detectando o seu padrão hormonal único...`, detalhe: 'Cada perfil tem um padrão diferente' },
    { texto: 'Posicionando na curva de saúde hormonal...', detalhe: 'Comparando com perfis similares' },
    { texto: `${primeiroNome}, sua análise está pronta.`, detalhe: 'Diagnóstico personalizado completo' },
  ];

  // Contador animado de "marcadores analisados" — gera sensacao de profundidade real
  useEffect(() => {
    const target = 247 + Math.floor(Math.random() * 60); // 247-306
    const start = Date.now();
    const dur = 7200;
    const timer = setInterval(() => {
      const t = Math.min(1, (Date.now() - start) / dur);
      // ease-out
      const eased = 1 - Math.pow(1 - t, 3);
      setContadorMarcadores(Math.floor(target * eased));
      if (t >= 1) clearInterval(timer);
    }, 60);
    return () => clearInterval(timer);
  }, []);

  useEffect(() => {
    const totalDuration = 8000;
    const startTime = Date.now();
    
    const intervalo = setInterval(() => {
      const elapsed = Date.now() - startTime;
      const newProgress = Math.min(100, (elapsed / totalDuration) * 100);
      setProgresso(Math.round(newProgress));
      
      const stageIndex = Math.min(Math.floor((elapsed / totalDuration) * etapas.length), etapas.length - 1);
      setEtapa(stageIndex);
      
      const completedStages = Math.floor((elapsed / totalDuration) * etapas.length);
      setCheckmarks(prev => {
        if (completedStages > prev.length) {
          const newChecks = [...prev];
          for (let i = prev.length; i < completedStages; i++) newChecks.push(i);
          return newChecks;
        }
        return prev;
      });
      
      if (elapsed >= totalDuration) {
        clearInterval(intervalo);
        setTimeout(() => onComplete(), 600);
      }
    }, 50);

    return () => clearInterval(intervalo);
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      style={{
        maxWidth: '560px',
        width: '100%',
        margin: '0 auto',
        padding: 'clamp(2rem, 5vw, 3rem) clamp(1rem, 3vw, 1.5rem)',
        textAlign: 'center',
      }}
    >
      {/* Spinner */}
      <div style={{ marginBottom: THEME.sp8, position: 'relative', display: 'inline-block' }}>
        <motion.div
          animate={{ rotate: 360 }}
          transition={{ duration: 2, repeat: Infinity, ease: 'linear' }}
          style={{
            width: '80px', height: '80px',
            border: `3px solid ${THEME.border}`,
            borderTopColor: THEME.primary,
            borderRadius: '50%',
          }}
        />
        <img 
          src={logoHormoscan} alt="HormoScan" 
          style={{ 
            position: 'absolute', top: '50%', left: '50%', 
            transform: 'translate(-50%, -50%)',
            height: '36px', width: 'auto',
          }} 
        />
      </div>

      {/* Title cinematografico */}
      <h2 style={{
        fontSize: 'clamp(1.35rem, 4.5vw, 1.7rem)',
        fontWeight: 800, color: THEME.textPrimary,
        marginBottom: THEME.sp2, letterSpacing: '-0.02em',
        lineHeight: 1.2,
      }}>
        Construindo sua análise hormonal
      </h2>

      {/* Contador de marcadores — sensacao de profundidade real */}
      <motion.div
        initial={{ opacity: 0, y: 8 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ delay: 0.2 }}
        style={{
          display: 'inline-flex', alignItems: 'center', gap: '0.5rem',
          padding: '0.4rem 0.9rem', marginBottom: THEME.sp4,
          background: 'rgba(221, 121, 212, 0.1)',
          border: '1px solid rgba(221, 121, 212, 0.2)',
          borderRadius: 999,
        }}
      >
        <motion.span
          key={contadorMarcadores}
          initial={{ scale: 1.15 }}
          animate={{ scale: 1 }}
          transition={{ duration: 0.2 }}
          style={{
            color: THEME.primary, fontWeight: 800, fontSize: '0.95rem',
            fontVariantNumeric: 'tabular-nums',
          }}
        >
          {contadorMarcadores}
        </motion.span>
        <span style={{ color: THEME.textSecondary, fontSize: '0.78rem', fontWeight: 600 }}>
          marcadores analisados
        </span>
      </motion.div>

      {/* Current stage */}
      <AnimatePresence mode="wait">
        <motion.p
          key={etapa}
          initial={{ opacity: 0, y: 10 }}
          animate={{ opacity: 1, y: 0 }}
          exit={{ opacity: 0, y: -10 }}
          style={{ 
            color: THEME.primary, fontSize: THEME.textBase,
            fontWeight: 500, marginBottom: THEME.sp6,
          }}
        >
          {etapas[etapa]?.texto}
        </motion.p>
      </AnimatePresence>

      {/* Progress bar */}
      <div style={{
        height: '4px', background: THEME.border,
        borderRadius: '2px', overflow: 'hidden',
        marginBottom: THEME.sp2,
      }}>
        <motion.div style={{
          height: '100%', width: `${progresso}%`,
          background: THEME.gradientPrimary, borderRadius: '2px',
          transition: 'width 0.1s linear',
        }} />
      </div>

      <p style={{ 
        color: THEME.textSecondary, fontWeight: 600, 
        fontSize: THEME.textSm, fontVariantNumeric: 'tabular-nums',
        marginBottom: THEME.sp8,
      }}>
        {progresso}%
      </p>

      {/* Checklist */}
      <div style={{ 
        display: 'flex', flexDirection: 'column', gap: THEME.sp2,
        textAlign: 'left',
      }}>
        {etapas.map((e, i) => {
          const isCompleted = checkmarks.includes(i);
          const isCurrent = i === etapa;
          
          return (
            <motion.div
              key={i}
              initial={{ opacity: 0, x: -8 }}
              animate={{ opacity: isCompleted || isCurrent ? 1 : 0.35, x: 0 }}
              transition={{ delay: i * 0.05 }}
              style={{
                display: 'flex', alignItems: 'center', gap: THEME.sp3,
                padding: `${THEME.sp2} ${THEME.sp3}`,
                background: isCurrent ? 'rgba(221, 121, 212, 0.06)' : 'transparent',
                borderRadius: THEME.radiusSm,
                borderLeft: isCurrent ? `2px solid ${THEME.primary}` : '2px solid transparent',
              }}
            >
              {isCompleted ? (
                <CheckCircle size={16} color={THEME.success} />
              ) : isCurrent ? (
                <motion.div
                  animate={{ rotate: 360 }}
                  transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
                  style={{
                    width: '16px', height: '16px',
                    border: `2px solid ${THEME.border}`,
                    borderTopColor: THEME.primary,
                    borderRadius: '50%', flexShrink: 0,
                  }}
                />
              ) : (
                <div style={{ 
                  width: '16px', height: '16px', borderRadius: '50%',
                  border: `1px solid ${THEME.border}`, flexShrink: 0,
                }} />
              )}
              <span style={{ 
                fontSize: THEME.textSm, 
                color: isCompleted ? THEME.success : isCurrent ? THEME.textPrimary : THEME.textMuted,
                fontWeight: isCurrent ? 500 : 400,
              }}>
                {e.texto}
              </span>
            </motion.div>
          );
        })}
      </div>

      {/* Trust signal */}
      <AnimatePresence>
        {progresso > 50 && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            style={{
              marginTop: THEME.sp8,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              gap: '6px', fontSize: THEME.textXs, color: THEME.textMuted,
            }}
          >
            <Shield size={12} />
            Dados processados com criptografia
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  );
};

// =====================================================
// COMPONENTE PRINCIPAL: Quiz Unificado Adaptativo
// =====================================================
const QuizUnificado = () => {
  const navigate = useNavigate();
  const { user, userData, canDoQuiz, getDaysUntilNextFreeAnalysis } = useAuth();

  useSEO({
    title: 'Análise Hormonal Gratuita | Quiz HormoScan',
    description: 'Responda o quiz de 5 minutos e descubra quais hormônios estão desequilibrados. Resultado personalizado com IA.',
    canonical: 'https://hormoscan.com/quiz',
    ogType: 'website',
  });

  // Estados principais
  // Onda 3.4: 'estilo-vida' (fase pré-quiz de 7 etapas) foi removida.
  // Onda 4.2: fase 'email-capture' (Onda 3.6) revertida.
  // Onda 5.2: cinematica revertida — voz nativa do browser nao rendeu na pratica.
  // Fluxo agora: boas-vindas → quiz → processando.
  const [fase, setFase] = useState('boas-vindas');
  const [dadosUsuario, setDadosUsuario] = useState(null);
  const quizStartTimeRef = useRef(null);
  const [tempoDecorrido, setTempoDecorrido] = useState(0);

  // =====================================================
  // 🔒 LIMITE DE ANÁLISES — Plano Gratuito
  // =====================================================
  const limiteAtingido = useMemo(() => {
    // Não bloquear se não está logado (permite 1ª análise antes de login)
    if (!user || !userData) return false;
    return !canDoQuiz();
  }, [user, userData, canDoQuiz]);

  const diasParaProximaAnalise = useMemo(() => {
    if (!limiteAtingido) return 0;
    return getDaysUntilNextFreeAnalysis();
  }, [limiteAtingido, getDaysUntilNextFreeAnalysis]);

  // ✅ Callback memoizado para evitar re-criação
  const handleQuizComplete = useCallback(() => {
    setFase('processando');
  }, []);

  // Hook adaptativo - só inicializa quando temos dados do usuário
  // ✅ Memoizar valores derivados para evitar recálculo
  const sexoUsuario = useMemo(() => dadosUsuario?.sexo || null, [dadosUsuario?.sexo]);
  const idadeUsuario = useMemo(() => parseInt(dadosUsuario?.idade) || 30, [dadosUsuario?.idade]);
  
  const quiz = useQuizAdaptativo(
    sexoUsuario,
    idadeUsuario,
    handleQuizComplete
  );

  // Se limite atingido, mostrar tela de upgrade
  if (limiteAtingido) {
    return (
      <div style={{
        minHeight: '100vh',
        background: THEME.bgDark,
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        padding: '2rem 1rem',
        textAlign: 'center'
      }}>
        <Header showFullMenu={true} fixedPosition={false} />
        <div style={{
          maxWidth: '480px',
          width: '100%',
          background: THEME.bgCard,
          border: `1px solid ${THEME.border}`,
          borderRadius: THEME.radiusXl,
          padding: '2.5rem 2rem',
          marginTop: 'calc(env(safe-area-inset-top, 0px) + 2rem)'
        }}>
          <div style={{ fontSize: '3rem', marginBottom: '1.5rem' }}>🔒</div>
          <h1 style={{
            fontSize: 'clamp(1.3rem, 4vw, 1.6rem)',
            fontWeight: 800,
            color: THEME.textPrimary,
            marginBottom: '1rem',
            lineHeight: 1.3
          }}>
            Limite de análise atingido
          </h1>
          <p style={{
            color: THEME.textSecondary,
            fontSize: '1rem',
            lineHeight: 1.6,
            marginBottom: '0.75rem'
          }}>
            No plano gratuito você tem direito a <strong style={{ color: THEME.accent }}>1 análise por mês</strong>. Assine o plano Básico para ter <strong>2 análises por mês</strong>.
          </p>
          {diasParaProximaAnalise > 0 && (
            <p style={{
              color: THEME.textMuted,
              fontSize: '0.9rem',
              marginBottom: '1.5rem'
            }}>
              Sua próxima análise gratuita estará disponível em <strong style={{ color: THEME.primaryLight }}>{diasParaProximaAnalise} dia{diasParaProximaAnalise !== 1 ? 's' : ''}</strong>.
            </p>
          )}
          <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', marginTop: '1.5rem' }}>
            <motion.button
              whileHover={{ scale: 1.02 }}
              whileTap={{ scale: 0.98 }}
              onClick={() => navigate('/planos')}
              style={{
                width: '100%',
                padding: '1rem',
                fontSize: '1rem',
                fontWeight: 700,
                background: THEME.gradientPrimary,
                border: 'none',
                borderRadius: THEME.radiusFull,
                color: '#fff',
                cursor: 'pointer',
                boxShadow: THEME.shadowCTA
              }}
            >
              ⚡ Fazer upgrade — mais análises
            </motion.button>
            <motion.button
              whileHover={{ scale: 1.02 }}
              whileTap={{ scale: 0.98 }}
              onClick={() => navigate('/dashboard')}
              style={{
                width: '100%',
                padding: '0.85rem',
                fontSize: '0.95rem',
                fontWeight: 600,
                background: 'transparent',
                border: `1px solid ${THEME.border}`,
                borderRadius: THEME.radiusMd,
                color: THEME.textSecondary,
                cursor: 'pointer'
              }}
            >
              📊 Ver meu resultado anterior
            </motion.button>
          </div>
        </div>
      </div>
    );
  }

  // ⏱ Timer ao vivo — tick a cada segundo durante a fase 'quiz'
  useEffect(() => {
    if (fase !== 'quiz') return;
    const interval = setInterval(() => {
      if (quizStartTimeRef.current) {
        setTempoDecorrido(Math.floor((Date.now() - quizStartTimeRef.current) / 1000));
      }
    }, 1000);
    return () => clearInterval(interval);
  }, [fase]);

  // Iniciar — vai direto pro quiz (Onda 3.4: fase estilo-vida foi removida)
  const handleStart = useCallback((dados) => {
    quizStartTimeRef.current = Date.now(); // inicia o timer
    setTempoDecorrido(0);
    setDadosUsuario(dados);
    setFase('quiz');
    // Salvar dados do usuário no localStorage para recuperar no resume
    try {
      localStorage.setItem('hormoscan_quiz_dados_usuario', JSON.stringify(dados));
    } catch {}
    // Meta Pixel: Lead (usuário iniciou o quiz)
    trackQuizStart();
    // 📊 Analytics: quiz started
    trackQuizFunnel.start(dados?.nome);
    trackQuizFunnel.enterQuestions();
  }, []);

  // 📊 Meta Pixel: detectar abandono do quiz (beforeunload + pagehide + visibilitychange)
  useEffect(() => {
    let abandonFired = false;
    const fireAbandon = () => {
      if (abandonFired) return;
      // Track abandon in any active phase (not after completion/processing)
      const isActivePhase = ['boas-vindas', 'quiz'].includes(fase);
      if (isActivePhase && !quiz.finalizado) {
        abandonFired = true;
        trackQuizAbandon(quiz.perguntasRespondidas, quiz.totalEstimado || 20);
        trackQuizFunnel.abandon(fase, quiz.perguntasRespondidas, quiz.perguntasRespondidas, quiz.totalEstimado || 20);
      }
    };

    const handleBeforeUnload = () => fireAbandon();
    const handlePageHide = () => fireAbandon();
    const handleVisibilityChange = () => {
      if (document.visibilityState === 'hidden') fireAbandon();
    };

    window.addEventListener('beforeunload', handleBeforeUnload);
    window.addEventListener('pagehide', handlePageHide);
    document.addEventListener('visibilitychange', handleVisibilityChange);
    return () => {
      window.removeEventListener('beforeunload', handleBeforeUnload);
      window.removeEventListener('pagehide', handlePageHide);
      document.removeEventListener('visibilitychange', handleVisibilityChange);
    };
  }, [fase, quiz.finalizado, quiz.carregando, quiz.perguntasRespondidas, quiz.totalEstimado]);

  // 📄 Page title
  useEffect(() => {
    const n = quiz.perguntasRespondidas;
    const contadorTitle = n <= 20 ? `${n}/20` : `${n}`;
    document.title = fase === 'quiz'
      ? `Análise Hormonal (${contadorTitle}) | HormoScan`
      : 'Análise Hormonal | HormoScan';
    return () => { document.title = 'HormoScan — Análise Hormonal Inteligente'; };
  }, [fase, quiz.perguntasRespondidas, quiz.totalEstimado]);

  // =====================================================
  // 🎓 Tutorial de primeira vez por tipo de input
  // =====================================================
  // Tipos que têm tutoriais: 'drag' (sliders) | 'press' (pressure_orb) | 'map' (body_map)
  const TUTORIAL_MAP = {
    battery_gauge:    { tipo: 'drag',  emoji: '👆', titulo: 'Como usar', texto: 'Arraste o cursor para ajustar o nível' },
    fuel_gauge:       { tipo: 'drag',  emoji: '👆', titulo: 'Como usar', texto: 'Arraste o cursor para indicar sua disposição' },
    flame_gauge:      { tipo: 'drag',  emoji: '👆', titulo: 'Como usar', texto: 'Arraste para indicar o nível' },
    power_meter:      { tipo: 'drag',  emoji: '👆', titulo: 'Como usar', texto: 'Arraste para ajustar a potência' },
    stress_meter:     { tipo: 'drag',  emoji: '👆', titulo: 'Como usar', texto: 'Arraste para indicar o nível de estresse' },
    slider:           { tipo: 'drag',  emoji: '👆', titulo: 'Como usar', texto: 'Arraste o ponto para ajustar' },
    pressure_orb:     { tipo: 'press', emoji: '✋', titulo: 'Segure e pressione', texto: 'Toque e segure o orbe — solte quando atingir a intensidade certa' },
    body_map:         { tipo: 'map',   emoji: '👆', titulo: 'Mapa corporal', texto: 'Toque nas regiões do corpo onde você sente mais os sintomas' },
  };
  const tutoriaisVistosRef = useRef(() => {
    try { return new Set(JSON.parse(sessionStorage.getItem('hs_tutorials') || '[]')); } catch { return new Set(); }
  });
  const [tutorialAtivo, setTutorialAtivo] = useState(null);
  const tutorialTimeoutRef = useRef(null);

  // Detecta novo tipo de pergunta e exibe tutorial se for a primeira vez
  useEffect(() => {
    if (fase !== 'quiz' || !quiz.perguntaAtual) return;
    const tipo = quiz.perguntaAtual.tipo || quiz.perguntaAtual.tipoInput || '';
    const tutorialDef = TUTORIAL_MAP[tipo];
    if (!tutorialDef) return;
    const vistosSet = tutoriaisVistosRef.current();
    if (vistosSet.has(tutorialDef.tipo)) return;
    // Primeira vez para este grupo de tipo — mostrar tutorial
    vistosSet.add(tutorialDef.tipo);
    try { sessionStorage.setItem('hs_tutorials', JSON.stringify([...vistosSet])); } catch {}
    setTutorialAtivo(tutorialDef);
    if (tutorialTimeoutRef.current) clearTimeout(tutorialTimeoutRef.current);
    tutorialTimeoutRef.current = setTimeout(() => setTutorialAtivo(null), 4000);
    return () => { if (tutorialTimeoutRef.current) clearTimeout(tutorialTimeoutRef.current); };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [quiz.perguntaAtual?.id, fase]);

  // ✅ Estados cinematográficos
  const [feedbackAtual, setFeedbackAtual] = useState(null);
  const [insightTeaser, setInsightTeaser] = useState(null);
  const [transicaoCategoria, setTransicaoCategoria] = useState(null);
  const [categoriasVisitadas, setCategoriasVisitadas] = useState(() => new Set());
  const categoriaAnteriorRef = useRef(null);
  const lastInsightCountRef = useRef(0);

  // 🧬 Insight teasers every ~5 questions (when no per-question feedback)
  const INSIGHT_TEASERS = useMemo(() => [
    { at: 5, emoji: '🔬', text: (previews) => previews.length > 0 ? `Suas respostas indicam atividade incomum em ${previews[0]?.nome || 'hormônios'}... continue para ver o resultado completo` : 'Padrões iniciais sendo detectados... continue para uma análise precisa' },
    { at: 10, emoji: '🧬', text: (previews) => previews.length >= 2 ? `Correlação detectada entre ${previews[0]?.nome} e ${previews[1]?.nome}... isso é significativo` : 'Seu perfil hormonal está tomando forma... quase na metade!' },
    { at: 15, emoji: '📊', text: (previews) => previews.length > 0 ? `${previews.length} hormônio(s) com indicadores relevantes encontrados até agora` : 'Análise quase completa — cada resposta aumenta a precisão' },
    { at: 18, emoji: '🎯', text: () => 'Últimas perguntas! Seu resultado personalizado está sendo preparado...' },
  ], []);

  // ✅ Responder pergunta - usar ref para evitar recreação desnecessária
  const perguntaAtualRef = useRef(null);
  perguntaAtualRef.current = quiz.perguntaAtual;
  
  const responderRef = useRef(quiz.responder);
  responderRef.current = quiz.responder;
  
  // Refs para timeouts de feedback/teaser (permitem dismiss antecipado)
  const feedbackTimeoutRef = useRef(null);
  const pendingRespostaRef = useRef(null);
  const isMountedRef = useRef(true);
  
  // Mark unmount to prevent stale timeout execution
  useEffect(() => {
    isMountedRef.current = true;
    return () => { isMountedRef.current = false; };
  }, []);
  
  // Dismiss feedback/teaser ao clicar na overlay
  const dismissOverlay = useCallback(() => {
    if (feedbackTimeoutRef.current) {
      clearTimeout(feedbackTimeoutRef.current);
      feedbackTimeoutRef.current = null;
    }
    setFeedbackAtual(null);
    setInsightTeaser(null);
    if (pendingRespostaRef.current && isMountedRef.current) {
      const { perguntaId, resposta } = pendingRespostaRef.current;
      pendingRespostaRef.current = null;
      responderRef.current(perguntaId, resposta);
    }
  }, []);
  
  const handleAnswer = useCallback((resposta) => {
    const pergunta = perguntaAtualRef.current;
    if (!pergunta) return;
    
    // 📊 Meta Pixel: rastrear cada resposta individual
    const qNum = quiz.perguntasRespondidas + 1;
    const totalEst = quiz.totalEstimado || 20;
    const catId = typeof quiz.categoriaAtual === 'object' ? quiz.categoriaAtual?.id : quiz.categoriaAtual;
    trackQuizAnswer(pergunta.id, catId || '', resposta, qNum, totalEst);
    
    // � Analytics: rastrear resposta
    trackQuizFunnel.answer(pergunta.id, qNum, totalEst, catId || '');
    
    // 💾 Progresso salvo automaticamente pelo hook (useQuizAdaptativo debouncedSave)
    // NÃO chamar saveQuizProgress aqui — ele sobrescreve a mesma key
    // (hormoscan_quiz_progress) com formato incompatível, apagando as respostas.
    // O QuizRecoveryBanner já lê totalRespondidas do formato do hook.
    
    // 📊 Meta Pixel & Analytics: marcos de progresso (25%, 50%, 75%)
    const pct = Math.round((qNum / totalEst) * 100);
    if ([25, 50, 75].includes(pct)) {
      trackQuizProgress(pct, qNum, totalEst);
      trackQuizFunnel.progress(pct, qNum, totalEst);
    }
    
    // 🎬 Feedback cinematográfico pós-resposta
    const feedbackMap = pergunta.feedback;
    let feedback = null;
    if (feedbackMap) {
      // Try exact match, then closest numeric match
      if (feedbackMap[resposta]) {
        feedback = feedbackMap[resposta];
      } else if (typeof resposta === 'number') {
        const keys = Object.keys(feedbackMap).map(Number).filter(n => !isNaN(n)).sort((a, b) => a - b);
        const closest = keys.reduce((prev, curr) => 
          Math.abs(curr - resposta) < Math.abs(prev - resposta) ? curr : prev
        , keys[0]);
        if (closest !== undefined) feedback = feedbackMap[closest];
      } else if (Array.isArray(resposta) && resposta.length > 0) {
        // For multi_select, show first matched feedback
        for (const r of resposta) {
          if (feedbackMap[r]) { feedback = feedbackMap[r]; break; }
        }
      }
    }
    
    if (feedback) {
      setFeedbackAtual(feedback);
      pendingRespostaRef.current = { perguntaId: pergunta.id, resposta };
      feedbackTimeoutRef.current = setTimeout(() => {
        if (!isMountedRef.current) return;
        setFeedbackAtual(null);
        pendingRespostaRef.current = null;
        responderRef.current(pergunta.id, resposta);
      }, 5000);
    } else {
      // Check for milestone insight teaser (every ~5 questions)
      const count = quiz.perguntasRespondidas + 1;
      const teaser = INSIGHT_TEASERS.find(t => t.at === count && count > lastInsightCountRef.current);
      if (teaser) {
        lastInsightCountRef.current = count;
        const teaserText = teaser.text(quiz.scoresPreview || []);
        setInsightTeaser({ emoji: teaser.emoji, text: teaserText });
        pendingRespostaRef.current = { perguntaId: pergunta.id, resposta };
        feedbackTimeoutRef.current = setTimeout(() => {
          if (!isMountedRef.current) return;
          setInsightTeaser(null);
          pendingRespostaRef.current = null;
          responderRef.current(pergunta.id, resposta);
        }, 3500);
      } else {
        responderRef.current(pergunta.id, resposta);
      }
    }
  }, [INSIGHT_TEASERS, quiz.perguntasRespondidas, quiz.scoresPreview, quiz.totalEstimado, quiz.categoriaAtual]);

  // Verificar se quiz finalizou - vai direto para processamento (estilo de vida já foi coletado)
  useEffect(() => {
    if (quiz.finalizado && fase === 'quiz') {
      setFase('processando');
      trackQuizFunnel.processing();
    }
  }, [quiz.finalizado, fase]);

  // 🎬 Detectar mudança de categoria para transição cinematográfica
  useEffect(() => {
    const catAtual = typeof quiz.categoriaAtual === 'object' ? quiz.categoriaAtual?.id : quiz.categoriaAtual;
    const catAnterior = categoriaAnteriorRef.current;

    // Marca categoria como visitada (independente de transicao — capta ja a 1a)
    if (catAtual && fase === 'quiz') {
      setCategoriasVisitadas((prev) => {
        if (prev.has(catAtual)) return prev;
        const next = new Set(prev);
        next.add(catAtual);
        return next;
      });
    }

    if (catAtual && catAnterior && catAtual !== catAnterior && fase === 'quiz') {
      const categoriaInfo = {
        energia: { nome: 'Energia', cor: '#F59E0B' },
        sono: { nome: 'Sono', cor: '#7DC7FA' },
        metabolismo: { nome: 'Metabolismo', cor: '#DC2626' },
        humor: { nome: 'Humor & Mente', cor: '#DD79D4' },
        fisico: { nome: 'Físico', cor: '#16A34A' },
        sexual: { nome: 'Saúde Íntima', cor: '#DD79D4' },
        hormonal: { nome: 'Hormonal', cor: '#DD79D4' }
      };

      const de = categoriaInfo[catAnterior] || { nome: catAnterior, cor: '#16A34A' };
      const para = categoriaInfo[catAtual] || { nome: catAtual, cor: '#DD79D4' };

      setTransicaoCategoria({ de, para });
      setTimeout(() => setTransicaoCategoria(null), 3000);
    }

    categoriaAnteriorRef.current = catAtual;
  }, [quiz.categoriaAtual, fase]);

  // Finalizar análise
  const handleComplete = async () => {
    // Gerar resultado do sistema adaptativo antigo (para compatibilidade)
    const resultadoAdaptativoAntigo = quiz.gerarResultado();

    // ========================================
    // 🧬 USAR NOVO MOTOR DE DIAGNÓSTICO AVANÇADO
    // ========================================
    const genero = dadosUsuario?.sexo || dadosUsuario?.genero || 'masculino';
    const idade = parseInt(dadosUsuario?.idade) || 30;

    // Onda 3.4: derivar estiloVida (formato antigo) das seleções multi do
    // pergunta `fatores_vida`. Ausência = baseline neutro.
    const estiloVidaDerivado = mapearFatoresVidaParaEstiloVida(quiz.respostas?.fatores_vida);
    if (estiloVidaDerivado) {
      trackEstiloVidaComplete(estiloVidaDerivado);
      trackQuizFunnel.estiloVidaComplete();
    }

    const diagnosticoAvancado = gerarDiagnosticoCompleto(
      quiz.respostas,
      genero,
      idade,
      estiloVidaDerivado
    );
    
    // Usar o score do novo motor
    const scoreTotal = diagnosticoAvancado.scoreGeralSaude;
    
    // Classificar nível de risco baseado no score de SAÚDE
    let nivelRisco = 'baixo';
    if (scoreTotal < 30) nivelRisco = 'critico';
    else if (scoreTotal < 50) nivelRisco = 'alto';
    else if (scoreTotal < 70) nivelRisco = 'moderado';
    
    // Combinar resultado do sistema adaptativo com o novo diagnóstico
    const resultadoAdaptativo = {
      ...resultadoAdaptativoAntigo,
      // Sobrescrever com dados do novo motor
      hormoniosDesequilibrados: diagnosticoAvancado.hormoniosDesequilibrados,
      todosHormonios: diagnosticoAvancado.todosHormonios,
      hormoniosSaudaveis: diagnosticoAvancado.hormoniosSaudaveis,
      perfis: diagnosticoAvancado.perfis,
      sintomasDetectados: diagnosticoAvancado.sintomasDetectados,
      scoreGeralSaude: diagnosticoAvancado.scoreGeralSaude,
      nivelGeral: diagnosticoAvancado.nivelGeral,
      confianca: diagnosticoAvancado.confianca,
      // ⭐ Incluir ajustes aplicados
      ajustesAplicados: diagnosticoAvancado.ajustesAplicados,
      validacaoCruzada: diagnosticoAvancado.validacaoCruzada
    };

    // Preparar dados para salvar
    const tempoGasto = quizStartTimeRef.current
      ? Math.round((Date.now() - quizStartTimeRef.current) / 1000)
      : 0;
    const dadosResultado = {
      respostas: quiz.respostas,
      dadosUsuario,
      estiloVida: estiloVidaDerivado,
      resultadoAdaptativo,
      diagnosticoAvancado,
      scoreSaude: scoreTotal,
      tempoGasto,
      timestamp: Date.now()
    };

    // Salvar no localStorage para recuperar após login
    secureStorage.setItem('hormoscan_quiz_resultado', JSON.stringify(dadosResultado));

    // Quiz completo — disparar tracking antes de qualquer redirect, para que sessões
    // não-logadas (que vão pra /login) também sejam contadas.
    trackQuizComplete(scoreTotal || 0);
    trackQuizFunnel.complete(scoreTotal || 0, nivelRisco || '', Object.keys(quiz?.respostas || {}).length);

    // Se não estiver logado, redirecionar direto pro /login (com Google bem visível).
    // Onda 4.2: revertida a fase email-capture (Onda 3.6) — fricção desnecessária pra
    // usuário mais velho que prefere login com Google sem digitar email.
    if (!user) {
      markQuizCompleted();
      navigate('/login', {
        state: {
          from: { pathname: '/resultado' },
          quizData: dadosResultado,
        },
      });
      return;
    }

    // Usuário logado - salvar e ir para resultado
    try {
      // Hormônios detectados do novo motor
      const hormoniosDeseq = diagnosticoAvancado.hormoniosDesequilibrados || [];

      // ========================================
      // 🛡️ VALIDAÇÃO COM ZOD ANTES DE SALVAR
      // ========================================
      const dadosParaSalvar = {
        user_id: user.id,
        respostas: quiz.respostas || {},
        resultado: {
          perfilPrimario: resultadoAdaptativo?.perfis?.[0]?.id || 'geral',
          perfilSecundario: resultadoAdaptativo?.perfis?.[1]?.id,
          scores: diagnosticoAvancado?.todosHormonios?.reduce((acc, h) => {
            acc[h.id] = h.scoreSaude;
            return acc;
          }, {}) || {},
          confianca: diagnosticoAvancado?.confianca || 0,
          recomendacoes: resultadoAdaptativo?.recomendacoes?.slice(0, 10) || []
        },
        metadata: {
          versaoQuiz: '2.0',
          dataInicio: new Date().toISOString(),
          dataFim: new Date().toISOString(),
          totalPerguntas: Object.keys(quiz.respostas || {}).length,
          tempoTotal: Date.now() - quizStartTimeRef.current,
          dispositivo: window.innerWidth < 768 ? 'mobile' : 'desktop',
          origem: 'quiz_unificado'
        }
      };

      const validacao = validarEsanitizarQuiz(dadosParaSalvar);
      
      if (!validacao.success) {
        logger.error('Validação falhou', null, { errors: validacao.errors });
        // Continuar mesmo com erro de validação, mas logar
      }
      
      if (validacao.warnings?.length > 0) {
        logger.warn('Avisos de validação:', validacao.warnings);
      }

      // Salvar no Supabase com dados validados (B2 fix 2026-04: agora capturamos
      // erro explicitamente — antes era await sem ler retorno, fazendo erros do
      // Supabase passarem em silencio e a analise nao aparecer no historico).
      const { error: insertError } = await supabase.from('quiz_results').insert({
        user_id: user.id,
        respostas: validacao.data?.respostas || quiz.respostas || {},
        score_total: scoreTotal,
        nivel_risco: nivelRisco,
        hormonios_detectados: hormoniosDeseq.map(h => h.id || h.nome),
        categorias_scores: resultadoAdaptativo?.categorias || {},
        genero_quiz: dadosUsuario?.sexo || dadosUsuario?.genero || null,
        idade_quiz: dadosUsuario?.idade || null,
        nome_quiz: dadosUsuario?.nome || null,
        peso_quiz: dadosUsuario?.peso || null,
        altura_quiz: dadosUsuario?.altura || null,
        resultado_completo: resultadoAdaptativo || {},
        created_at: new Date().toISOString()
      });
      if (insertError) {
        logger.error('Falha ao salvar quiz_results no Supabase', insertError, {
          code: insertError.code,
          message: insertError.message,
          details: insertError.details,
          hint: insertError.hint,
        });
        // Continua para /resultado mesmo em caso de erro — secureStorage tem
        // os dados como fallback e o user nao perde a experiencia.
      }

      // ✅ Marcar quiz como finalizado (limpar recovery)
      markQuizCompleted();
      // Navegar para resultados
      navigate('/resultado', { state: dadosResultado });
    } catch (error) {
      logger.error('Erro ao salvar quiz', error);
      // ✅ Marcar quiz como finalizado (limpar recovery)
      markQuizCompleted();
      // Navegar mesmo assim
      navigate('/resultado', { state: dadosResultado });
    }
  };

  // ✅ Interação memoizada - noop em produção
  const handleInteraction = useCallback((tipo, dados) => {
    // Registro de interação removido para produção
  }, []);

  return (
    <div style={{
      minHeight: '100vh',
      background: THEME.bgDark,
      position: 'relative',
      overflow: 'hidden'
    }}>
      {/* CSS para labels desktop + slider + page title */}
      <style>{`
        .step-label-desktop { display: none !important; }
        @media (min-width: 640px) { .step-label-desktop { display: inline !important; } }
        input[type=range]::-webkit-slider-thumb {
          -webkit-appearance: none;
          width: 28px; height: 28px;
          border-radius: 50%;
          background: linear-gradient(135deg, #DD79D4, #ADC1F9);
          box-shadow: 0 2px 8px rgba(26, 22, 37, 0.12);
          cursor: pointer;
          border: 3px solid #F4F1FB;
        }
        input[type=range]::-moz-range-thumb {
          width: 28px; height: 28px;
          border-radius: 50%;
          background: linear-gradient(135deg, #DD79D4, #ADC1F9);
          box-shadow: 0 2px 8px rgba(26, 22, 37, 0.12);
          cursor: pointer;
          border: 3px solid #F4F1FB;
        }
      `}</style>
      {/* Fundo sutil com gradientes suaves */}
      <div style={{
        position: 'fixed',
        inset: 0,
        overflow: 'hidden',
        pointerEvents: 'none',
        zIndex: 0
      }}>
        {/* Gradiente decorativo top-right */}
        <div style={{
          position: 'absolute',
          top: '5%',
          right: '-10%',
          width: '400px',
          height: '400px',
          background: 'radial-gradient(circle, rgba(221, 121, 212, 0.08) 0%, transparent 65%)',
          borderRadius: '50%',
          filter: 'blur(60px)'
        }} />
        {/* Gradiente decorativo bottom-left */}
        <div style={{
          position: 'absolute',
          bottom: '10%',
          left: '-5%',
          width: '350px',
          height: '350px',
          background: 'radial-gradient(circle, rgba(125, 199, 250, 0.06) 0%, transparent 65%)',
          borderRadius: '50%',
          filter: 'blur(60px)'
        }} />
      </div>

      {/* Header - Não flutuante no quiz */}
      <Header showFullMenu={true} fixedPosition={false} />

      {/* Conteúdo principal */}
      <div style={{ padding: '1rem', paddingTop: 'calc(env(safe-area-inset-top, 0px) + 5rem)' }}>
        <AnimatePresence mode="wait">
          {/* Fase: Boas-vindas */}
          {fase === 'boas-vindas' && (
            <TelaBoasVindas
              key="boas-vindas"
              onStart={handleStart}
              userData={userData}
            />
          )}

          {/* Fase: Quiz Adaptativo
              Onda 4.8.4: classe `quiz-fase-container` permite ambient orbs nas
              laterais em desktop XL (>1280px) — espaço vazio agora vira ambient. */}
          {fase === 'quiz' && quiz.perguntaAtual && !transicaoCategoria && (
            <motion.div
              key="quiz"
              className="quiz-fase-container"
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              style={{ maxWidth: '700px', margin: '0 auto', position: 'relative' }}
            >
              {/* Barra de progresso adaptativa */}
              <ProgressBar
                progresso={quiz.progresso}
                perguntasRespondidas={quiz.perguntasRespondidas}
                totalEstimado={quiz.totalEstimado}
                categoria={quiz.categoriaAtual}
                tipoPergunta={quiz.tipoPergunta}
                hormonioInvestigando={quiz.hormonioInvestigando}
                scoresPreview={quiz.scoresPreview}
                categoriasVisitadas={categoriasVisitadas}
                tempoDecorrido={tempoDecorrido}
              />

              {/* Pergunta — AnimatePresence com key para transição suave entre perguntas */}
              <AnimatePresence mode="wait">
                <motion.div
                  key={quiz.perguntaAtual?.id}
                  initial={{ opacity: 0, x: 28, filter: 'blur(4px)' }}
                  animate={{ opacity: 1, x: 0, filter: 'blur(0px)' }}
                  exit={{ opacity: 0, x: -28, filter: 'blur(4px)' }}
                  transition={{ duration: 0.22, ease: [0.25, 0.1, 0.25, 1] }}
                >
                  <PerguntaUniversal
                    pergunta={quiz.perguntaAtual}
                    onComplete={handleAnswer}
                    onInteraction={handleInteraction}
                  />
                </motion.div>
              </AnimatePresence>

              {/* 🎬 Feedback micro-insight overlay */}
              <AnimatePresence>
                {feedbackAtual && (
                  <motion.div
                    initial={{ opacity: 0, y: 60, scale: 0.95 }}
                    animate={{ opacity: 1, y: 0, scale: 1 }}
                    exit={{ opacity: 0, y: 60, scale: 0.95 }}
                    transition={{ type: 'spring', stiffness: 200, damping: 25 }}
                    className="quiz-feedback-overlay"
                    onClick={dismissOverlay}
                    style={{
                      padding: '1rem 1.25rem',
                      cursor: 'pointer',
                      background: feedbackAtual.tipo === 'alerta' 
                        ? 'rgba(239, 68, 68, 0.12)' 
                        : feedbackAtual.tipo === 'positivo'
                        ? 'rgba(34, 197, 94, 0.12)'
                        : 'rgba(125, 199, 250, 0.12)',
                      border: `1px solid ${
                        feedbackAtual.tipo === 'alerta' ? 'rgba(239, 68, 68, 0.4)' 
                        : feedbackAtual.tipo === 'positivo' ? 'rgba(34, 197, 94, 0.4)'
                        : 'rgba(125, 199, 250, 0.4)'
                      }`,
                      boxShadow: `0 10px 40px ${
                        feedbackAtual.tipo === 'alerta' ? 'rgba(239, 68, 68, 0.15)'
                        : feedbackAtual.tipo === 'positivo' ? 'rgba(34, 197, 94, 0.15)'
                        : 'rgba(125, 199, 250, 0.15)'
                      }`
                    }}
                  >
                    <p style={{ 
                      color: feedbackAtual.tipo === 'alerta' ? '#DC2626' 
                        : feedbackAtual.tipo === 'positivo' ? '#16A34A'
                        : '#7DC7FA',
                      fontSize: '0.95rem',
                      fontWeight: 500,
                      lineHeight: 1.5,
                      margin: 0
                    }}>
                      {feedbackAtual.texto}
                    </p>
                    {/* Progress bar da duração do feedback */}
                    <motion.div
                      initial={{ width: '100%' }}
                      animate={{ width: '0%' }}
                      transition={{ duration: 5, ease: 'linear' }}
                      style={{
                        height: '2px',
                        background: feedbackAtual.tipo === 'alerta' ? '#DC2626' 
                          : feedbackAtual.tipo === 'positivo' ? '#16A34A' : '#7DC7FA',
                        borderRadius: '1px',
                        marginTop: '0.5rem',
                        opacity: 0.5
                      }}
                    />
                  </motion.div>
                )}
              </AnimatePresence>

              {/* 🧬 Insight teaser overlay (every ~5 questions) */}
              <AnimatePresence>
                {insightTeaser && (
                  <motion.div
                    initial={{ opacity: 0, y: 60, scale: 0.95 }}
                    animate={{ opacity: 1, y: 0, scale: 1 }}
                    exit={{ opacity: 0, y: 60, scale: 0.95 }}
                    transition={{ type: 'spring', stiffness: 200, damping: 25 }}
                    className="quiz-feedback-overlay"
                    onClick={dismissOverlay}
                    style={{
                      padding: '1rem 1.25rem',
                      cursor: 'pointer',
                      background: 'rgba(221, 121, 212, 0.1)',
                      border: '1px solid rgba(221, 121, 212, 0.3)',
                      boxShadow: '0 10px 40px rgba(221, 121, 212, 0.12)',
                    }}
                  >
                    <div style={{ display: 'flex', alignItems: 'flex-start', gap: '10px' }}>
                      <span style={{ fontSize: '1.3rem', flexShrink: 0 }}>{insightTeaser.emoji}</span>
                      <p style={{ 
                        color: '#5C526E',
                        fontSize: '0.9rem',
                        fontWeight: 500,
                        lineHeight: 1.5,
                        margin: 0,
                      }}>
                        {insightTeaser.text}
                      </p>
                    </div>
                    <motion.div
                      initial={{ width: '100%' }}
                      animate={{ width: '0%' }}
                      transition={{ duration: 5, ease: 'linear' }}
                      style={{
                        height: '2px',
                        background: '#DD79D4',
                        borderRadius: '1px',
                        marginTop: '0.5rem',
                        opacity: 0.5,
                      }}
                    />
                  </motion.div>
                )}
              </AnimatePresence>

              {/* 🎓 Tutorial de primeira vez — aparece por 4s, depois some */}
              <AnimatePresence>
                {tutorialAtivo && (
                  <motion.div
                    initial={{ opacity: 0, y: 20, scale: 0.96 }}
                    animate={{ opacity: 1, y: 0, scale: 1 }}
                    exit={{ opacity: 0, y: 16, scale: 0.96 }}
                    transition={{ type: 'spring', stiffness: 260, damping: 22 }}
                    onClick={() => setTutorialAtivo(null)}
                    style={{
                      position: 'relative', overflow: 'hidden',
                      cursor: 'pointer',
                      padding: '0.85rem 1.1rem',
                      background: 'rgba(221, 121, 212, 0.12)',
                      border: '1.5px solid rgba(221, 121, 212, 0.35)',
                      borderRadius: '16px',
                      boxShadow: '0 6px 24px rgba(221, 121, 212, 0.15)',
                      display: 'flex', alignItems: 'flex-start', gap: '0.85rem',
                      maxWidth: '460px', margin: '0 auto',
                    }}
                  >
                    <motion.span
                      animate={{ scale: [1, 1.22, 1], rotate: [0, -10, 10, 0] }}
                      transition={{ duration: 1.2, repeat: 2 }}
                      style={{ fontSize: '1.5rem', flexShrink: 0 }}
                    >
                      {tutorialAtivo.emoji}
                    </motion.span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: '0.82rem', fontWeight: 800, color: '#DD79D4', marginBottom: '2px' }}>
                        {tutorialAtivo.titulo}
                      </div>
                      <div style={{ fontSize: '0.85rem', color: '#5C526E', lineHeight: 1.4 }}>
                        {tutorialAtivo.texto}
                      </div>
                    </div>
                    <span style={{ fontSize: '0.7rem', color: '#7A7189', flexShrink: 0, alignSelf: 'center' }}>Toque pra fechar</span>
                    {/* Barra de countdown */}
                    <motion.div
                      initial={{ width: '100%' }}
                      animate={{ width: '0%' }}
                      transition={{ duration: 4, ease: 'linear' }}
                      style={{
                        position: 'absolute', bottom: 0, left: 0, height: '2px',
                        background: 'rgba(221, 121, 212, 0.5)', borderRadius: '0 0 16px 16px',
                      }}
                    />
                  </motion.div>
                )}
              </AnimatePresence>

              {/* Botão voltar (se disponível) */}
              {quiz.podeVoltar && (
                <motion.button
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  whileTap={{ scale: 0.97 }}
                  onClick={quiz.voltar}
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: '4px',
                    margin: '1rem auto 0',
                    padding: '8px 16px',
                    background: 'transparent',
                    border: `1px solid ${THEME.border}`,
                    borderRadius: THEME.radiusSm,
                    color: THEME.textMuted,
                    fontSize: THEME.textSm,
                    cursor: 'pointer',
                    fontFamily: 'inherit',
                  }}
                >
                  <ChevronLeft size={16} /> Voltar
                </motion.button>
              )}

              {/* Info do usuário */}
              <div style={{
                textAlign: 'center',
                marginTop: THEME.sp6,
                fontSize: THEME.textXs,
                color: THEME.textMuted,
                display: 'flex', gap: THEME.sp4,
                justifyContent: 'center', flexWrap: 'wrap',
              }}>
                <span>{dadosUsuario?.nome}</span>
                <span>IMC: {dadosUsuario?.imc}</span>
                <span>
                  {dadosUsuario?.sexo === 'feminino' ? 'Fem.' : 'Masc.'} {dadosUsuario?.idade} anos
                </span>
              </div>

              {/* Indicador de confiança */}
            </motion.div>
          )}

          {/* 🎬 Transição entre categorias */}
          {fase === 'quiz' && transicaoCategoria && (
            <motion.div
              key="transicao-cat"
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              transition={{ duration: 0.35 }}
              className="category-transition"
              style={{
                display: 'flex', flexDirection: 'column', alignItems: 'center',
                justifyContent: 'center', minHeight: '60vh',
                position: 'relative', textAlign: 'center', padding: '2rem 1rem',
              }}
            >
              {/* Glow ambient da proxima categoria */}
              <motion.div
                aria-hidden
                initial={{ opacity: 0, scale: 0.6 }}
                animate={{ opacity: 0.55, scale: 1 }}
                transition={{ duration: 0.6 }}
                style={{
                  position: 'absolute', top: '40%', left: '50%',
                  transform: 'translate(-50%, -50%)',
                  width: '320px', height: '320px',
                  borderRadius: '50%',
                  background: `radial-gradient(circle, ${transicaoCategoria.para.cor}40 0%, transparent 70%)`,
                  filter: 'blur(40px)',
                  pointerEvents: 'none',
                  zIndex: 0,
                }}
              />

              {/* Pequenas particulas brilhantes (microconfete) */}
              {[...Array(6)].map((_, i) => (
                <motion.div
                  key={i}
                  aria-hidden
                  initial={{ opacity: 0, x: 0, y: 0, scale: 0 }}
                  animate={{
                    opacity: [0, 1, 0],
                    x: (i - 2.5) * 36,
                    y: -80 - i * 18,
                    scale: [0, 1, 0],
                  }}
                  transition={{ duration: 1.6, delay: 0.1 * i, repeat: Infinity, repeatDelay: 1.4 }}
                  style={{
                    position: 'absolute',
                    top: '45%', left: '50%',
                    width: 6, height: 6, borderRadius: '50%',
                    background: i % 2 ? transicaoCategoria.de.cor : transicaoCategoria.para.cor,
                    boxShadow: `0 0 12px ${i % 2 ? transicaoCategoria.de.cor : transicaoCategoria.para.cor}`,
                    pointerEvents: 'none',
                    zIndex: 1,
                  }}
                />
              ))}

              {/* Bloco "categoria completada" — mini celebracao */}
              <motion.div
                initial={{ scale: 0, rotate: -8 }}
                animate={{ scale: 1, rotate: 0 }}
                transition={{ type: 'spring', stiffness: 220, damping: 14 }}
                style={{
                  position: 'relative', zIndex: 2,
                  display: 'inline-flex', alignItems: 'center', gap: '0.5rem',
                  padding: '0.6rem 1.2rem',
                  background: `${transicaoCategoria.de.cor}18`,
                  border: `1.5px solid ${transicaoCategoria.de.cor}55`,
                  borderRadius: 999,
                  marginBottom: '1.5rem',
                }}
              >
                <CheckCircle size={18} color={transicaoCategoria.de.cor} />
                <span style={{
                  color: transicaoCategoria.de.cor,
                  fontWeight: 800,
                  fontSize: '0.92rem',
                  letterSpacing: '0.02em',
                }}>
                  {transicaoCategoria.de.nome} mapeado
                </span>
              </motion.div>

              {/* Headline com proxima categoria */}
              <motion.h2
                initial={{ opacity: 0, y: 16 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ delay: 0.3, duration: 0.45 }}
                style={{
                  position: 'relative', zIndex: 2,
                  fontSize: 'clamp(1.4rem, 6vw, 2rem)',
                  fontWeight: 900,
                  color: '#1A1625',
                  margin: '0 0 0.5rem',
                  letterSpacing: '-0.02em',
                  lineHeight: 1.15,
                }}
              >
                Vamos falar de{' '}
                <span style={{
                  background: `linear-gradient(135deg, ${transicaoCategoria.para.cor}, ${transicaoCategoria.para.cor}AA)`,
                  WebkitBackgroundClip: 'text',
                  WebkitTextFillColor: 'transparent',
                  backgroundClip: 'text',
                }}>
                  {transicaoCategoria.para.nome.toLowerCase()}
                </span>
              </motion.h2>

              <motion.p
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ delay: 0.55, duration: 0.4 }}
                style={{
                  position: 'relative', zIndex: 2,
                  color: '#5C526E',
                  fontSize: '0.95rem',
                  maxWidth: '320px',
                  lineHeight: 1.5,
                  margin: '0 0 1.75rem',
                }}
              >
                Próximas perguntas vão revelar mais sobre o seu perfil.
              </motion.p>

              {/* Loading dots */}
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ delay: 0.75 }}
                style={{ position: 'relative', zIndex: 2, display: 'flex', gap: '0.5rem' }}
              >
                {[0, 1, 2].map((i) => (
                  <motion.div
                    key={i}
                    animate={{ scale: [1, 1.5, 1], opacity: [0.3, 1, 0.3] }}
                    transition={{ duration: 0.8, repeat: Infinity, delay: i * 0.2 }}
                    style={{
                      width: 8, height: 8, borderRadius: '50%',
                      background: transicaoCategoria.para.cor,
                    }}
                  />
                ))}
              </motion.div>
            </motion.div>
          )}

          {/* Loading entre perguntas */}
          {fase === 'quiz' && quiz.carregando && (
            <motion.div
              key="loading"
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              style={{
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                minHeight: '300px'
              }}
            >
              <motion.div
                animate={{ rotate: 360 }}
                transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
                style={{
                  width: '40px',
                  height: '40px',
                  border: '3px solid rgba(221, 121, 212, 0.2)',
                  borderTopColor: '#DD79D4',
                  borderRadius: '50%'
                }}
              />
            </motion.div>
          )}

          {/* Fase: Processando */}
          {fase === 'processando' && (
            <TelaProcessamento
              key="processando"
              onComplete={handleComplete}
              dadosUsuario={dadosUsuario}
            />
          )}

        </AnimatePresence>
      </div>

      {/* Estilos globais para inputs */}
      <style>{`
        input[type="range"] {
          -webkit-appearance: none;
          appearance: none;
          height: 12px;
          border-radius: 6px;
          outline: none;
        }
        input[type="range"]:focus-visible {
          outline: 2px solid #DD79D4;
          outline-offset: 2px;
        }
        
        /* slider thumb styles defined in earlier style block */
        
        select {
          -webkit-appearance: none;
          appearance: none;
          background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23DD79D4' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
          background-repeat: no-repeat;
          background-position: right 1rem center;
          padding-right: 2.5rem;
        }
        
        input::placeholder {
          color: ${THEME.textMuted};
        }
        
        input:focus, select:focus {
          border-color: ${THEME.borderFocus} !important;
          box-shadow: 0 0 0 3px rgba(221, 121, 212, 0.1);
        }
        
        @media (max-width: 640px) {
          .desktop-menu {
            display: none !important;
          }
        }
      `}</style>
    </div>
  );
};

// Wrapper com Error Boundary
const QuizUnificadoWithErrorBoundary = (props) => (
  <QuizErrorBoundary>
    <QuizUnificado {...props} />
  </QuizErrorBoundary>
);

export default QuizUnificadoWithErrorBoundary;
