// Sou Coluna — Ficha v2 · Light "Soft Clinical" redesign
// Airy white dashboard, left sidebar, teal brand + coral pain accents,
// info cards floating anchored to spine regions. 3D kit reused as-is.
const { useState, useEffect, useRef, useMemo } = React;

const PALETTE_A = {
  // surfaces
  appBg: "#fff5ec",
  card: "#ffffff",
  panel: "#fff0ef",
  panelAlt: "#fde2d7",
  border: "rgba(74,39,35,0.09)",
  borderStrong: "rgba(74,39,35,0.16)",
  // ink
  text: "#4a2723",
  text2: "#6b4b45",
  muted: "#806660",
  mutedSolid: "#806660",
  // teal brand
  teal: "#ef7b60",
  tealDeep: "#b75746",
  tealSoft: "rgba(239,123,96,0.10)",
  tealSofter: "rgba(239,123,96,0.06)",
  // coral pain
  accent: "#ff6b4a",
  accentDeep: "#f4502c",
  accentSoft: "rgba(255,107,74,0.10)",
  // gradients
  tealGrad: "linear-gradient(135deg, #fcc89b 0%, #e8927c 100%)",
  // 3D
  bone: 0xf3f5f4,
  skin: 0xeadccb,
  accentHex: 0xff6b4a,
  accentLight: 0xffb59e,
};

const STEPS_A = [
  "welcome", "clinic", "personal", "origin", "quiz", "motivacao",
  "symptoms", "spine", "body", "sobreVoce", "exploracao",
  "historico", "estiloVida", "impacto", "objetivos", "summary",
];

const PREVENTIVE_SKIP = ["symptoms", "spine", "body", "sobreVoce", "exploracao"];

// step → phase grouping for the sidebar
const PHASES = [
  { id: "inicio", label: "Início", sub: "Boas-vindas", steps: ["welcome"], icon: "home" },
  { id: "cadastro", label: "Cadastro", sub: "Seus dados", steps: ["clinic", "personal", "origin"], icon: "id" },
  { id: "intencao", label: "Sua intenção", sub: "Método & motivo", steps: ["quiz", "motivacao"], icon: "compass" },
  { id: "mapa", label: "Mapa da dor", sub: "Coluna 3D & corpo", steps: ["symptoms", "spine", "body"], icon: "spine" },
  { id: "condicao", label: "Sua condição", sub: "Histórico do sintoma", steps: ["sobreVoce", "exploracao"], icon: "pulse" },
  { id: "historico", label: "Histórico & vida", sub: "Saúde e hábitos", steps: ["historico", "estiloVida"], icon: "clock" },
  { id: "qualidade", label: "Qualidade de vida", sub: "Impacto & objetivos", steps: ["impacto", "objetivos"], icon: "heart" },
  { id: "resumo", label: "Resumo", sub: "Ficha enviada", steps: ["summary"], icon: "check" },
];

// ── icons ──────────────────────────────────────────────────────────────
function Icon({ name, size = 18, color = "currentColor", stroke = 1.8 }) {
  const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case "home": return <svg {...p}><path d="M3 11l9-7 9 7" /><path d="M5 10v10h14V10" /></svg>;
    case "id": return <svg {...p}><rect x="3" y="5" width="18" height="14" rx="3" /><circle cx="9" cy="11" r="2" /><path d="M14 10h4M14 14H7" /></svg>;
    case "compass": return <svg {...p}><circle cx="12" cy="12" r="9" /><path d="m15 9-2 5-4 1 2-5 4-1z" /></svg>;
    case "spine": return <svg {...p}><path d="M12 3v18" /><path d="M9 5h6M8.5 9h7M8.5 13h7M9 17h6" /></svg>;
    case "pulse": return <svg {...p}><path d="M3 12h4l2-6 4 12 2-6h6" /></svg>;
    case "clock": return <svg {...p}><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></svg>;
    case "heart": return <svg {...p}><path d="M12 20s-7-4.6-7-10a4 4 0 0 1 7-2.5A4 4 0 0 1 19 10c0 5.4-7 10-7 10z" /></svg>;
    case "check": return <svg {...p}><circle cx="12" cy="12" r="9" /><path d="m8.5 12 2.5 2.5 4.5-5" /></svg>;
    case "lock": return <svg {...p}><rect x="5" y="11" width="14" height="9" rx="2" /><path d="M8 11V8a4 4 0 0 1 8 0v3" /></svg>;
    case "pin": return <svg {...p}><path d="M12 21s7-6.3 7-11a7 7 0 0 0-14 0c0 4.7 7 11 7 11z" /><circle cx="12" cy="10" r="2.5" /></svg>;
    case "arrow": return <svg {...p}><path d="M5 12h14M13 6l6 6-6 6" /></svg>;
    case "back": return <svg {...p}><path d="M19 12H5M11 6l-6 6 6 6" /></svg>;
    case "shield": return <svg {...p}><path d="M12 3 5 6v5c0 5 3 8 7 10 4-2 7-5 7-10V6l-7-3z" /></svg>;
    case "alert": return <svg {...p}><path d="M12 8v5M12 16h.01" /><circle cx="12" cy="12" r="9" /></svg>;
    case "rotate": return <svg {...p}><path d="M3 12a9 9 0 1 0 3-6.7" /><path d="M3 4v4h4" /></svg>;
    default: return null;
  }
}

// ── brand mark ───────────────────────────────────────────────────────────
function BrandMark({ size = 38 }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: 12,
      background: PALETTE_A.tealGrad,
      display: "grid", placeItems: "center", flexShrink: 0,
      boxShadow: "0 6px 16px -4px rgba(239,123,96,0.55)",
    }}>
      <svg width={size * 0.5} height={size * 0.5} viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.1" strokeLinecap="round">
        <path d="M12 3v18" />
        <path d="M9.5 5.5h5M9 9.2h6M9 12.8h6M9.5 16.5h5" />
      </svg>
    </div>
  );
}

// ── buttons ───────────────────────────────────────────────────────────────
function Btn({ children, onClick, disabled, variant = "primary", full }) {
  const [hover, setHover] = useState(false);
  const styles = {
    primary: {
      background: disabled ? "rgba(239,123,96,0.30)" : PALETTE_A.tealGrad,
      color: "#fff", border: "none",
      boxShadow: disabled ? "none" : (hover ? "0 12px 26px -8px rgba(239,123,96,0.6)" : "0 8px 20px -10px rgba(239,123,96,0.55)"),
    },
    coral: {
      background: disabled ? "rgba(255,107,74,0.3)" : `linear-gradient(135deg, #ff8765, ${PALETTE_A.accent})`,
      color: "#fff", border: "none",
      boxShadow: disabled ? "none" : (hover ? "0 12px 26px -8px rgba(255,90,60,0.5)" : "0 8px 20px -10px rgba(255,90,60,0.45)"),
    },
    ghost: {
      background: hover ? PALETTE_A.panel : "transparent",
      color: PALETTE_A.text2, border: `1px solid ${PALETTE_A.borderStrong}`,
      boxShadow: "none",
    },
  }[variant];
  return (
    <button
      onClick={onClick} disabled={disabled}
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        appearance: "none", cursor: disabled ? "not-allowed" : "pointer",
        padding: variant === "ghost" ? "13px 22px" : "14px 28px", borderRadius: 999,
        fontFamily: "'Inter', sans-serif", fontSize: 14.5, fontWeight: 600,
        letterSpacing: "0.005em", width: full ? "100%" : "auto",
        display: "inline-flex", alignItems: "center", gap: 9, justifyContent: "center",
        transform: hover && !disabled ? "translateY(-1px)" : "none",
        transition: "all 0.22s cubic-bezier(.2,.8,.2,1)",
        opacity: disabled ? 0.55 : 1, ...styles,
      }}>
      {children}
    </button>
  );
}

function Kicker({ children }) {
  return (
    <div style={{
      fontSize: 11.5, color: PALETTE_A.teal, fontWeight: 700,
      letterSpacing: "0.14em", textTransform: "uppercase", marginBottom: 12,
    }}>{children}</div>
  );
}

function StepHeader({ kicker, title, sub }) {
  return (
    <div style={{ marginBottom: 26 }}>
      <Kicker>{kicker}</Kicker>
      <h2 style={{ fontSize: 34, fontWeight: 700, margin: 0, letterSpacing: "-0.025em", lineHeight: 1.08, color: PALETTE_A.text }}>{title}</h2>
      {sub && <p style={{ color: PALETTE_A.text2, marginTop: 12, fontSize: 15.5, lineHeight: 1.5, maxWidth: 520 }}>{sub}</p>}
    </div>
  );
}

function NavBar({ onBack, onNext, nextLabel = "Continuar", canNext = true, showBack = true }) {
  return (
    <div style={{ display: "flex", justifyContent: showBack ? "space-between" : "flex-end", alignItems: "center", marginTop: 36 }}>
      {showBack && <Btn variant="ghost" onClick={onBack}><Icon name="back" size={16} /> Voltar</Btn>}
      <Btn onClick={onNext} disabled={!canNext}>{nextLabel} <Icon name="arrow" size={16} color="#fff" /></Btn>
    </div>
  );
}

// soft floating info card
function FloatCard({ children, style }) {
  return (
    <div style={{
      background: "rgba(255,255,255,0.86)", backdropFilter: "blur(14px)", WebkitBackdropFilter: "blur(14px)",
      border: `1px solid ${PALETTE_A.border}`, borderRadius: 18,
      boxShadow: "0 18px 44px -16px rgba(20,50,55,0.28)", padding: 16,
      ...style,
    }}>{children}</div>
  );
}

// ── sidebar ───────────────────────────────────────────────────────────────
function Sidebar({ stepName, isPreventive }) {
  const activePhase = PHASES.find((p) => p.steps.includes(stepName)) || PHASES[0];
  const activeIdx = PHASES.indexOf(activePhase);
  return (
    <div style={{
      flex: "0 0 256px", background: PALETTE_A.card,
      borderRight: `1px solid ${PALETTE_A.border}`,
      display: "flex", flexDirection: "column", padding: "30px 22px",
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 6, padding: "0 6px" }}>
        <BrandMark />
        <div>
          <div style={{ fontSize: 16.5, fontWeight: 700, color: PALETTE_A.text, letterSpacing: "-0.01em", lineHeight: 1 }}>Sou Coluna</div>
          <div style={{ fontSize: 11, color: PALETTE_A.mutedSolid, marginTop: 3, letterSpacing: "0.04em" }}>Ficha digital · v2</div>
        </div>
      </div>

      <div style={{ fontSize: 10.5, color: PALETTE_A.mutedSolid, fontWeight: 700, letterSpacing: "0.16em", textTransform: "uppercase", margin: "32px 8px 14px" }}>
        Sua avaliação
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 3, flex: 1 }}>
        {PHASES.map((ph, i) => {
          const isActive = i === activeIdx;
          const isDone = i < activeIdx;
          const dimmed = isPreventive && ["mapa", "condicao"].includes(ph.id);
          return (
            <div key={ph.id} style={{
              display: "flex", alignItems: "center", gap: 12,
              padding: "11px 12px", borderRadius: 13,
              background: isActive ? PALETTE_A.tealSoft : "transparent",
              opacity: dimmed && !isActive ? 0.4 : 1,
              transition: "all 0.3s",
            }}>
              <div style={{
                width: 32, height: 32, borderRadius: 9, flexShrink: 0,
                display: "grid", placeItems: "center",
                background: isActive ? PALETTE_A.teal : (isDone ? PALETTE_A.tealSoft : PALETTE_A.panel),
                color: isActive ? "#fff" : (isDone ? PALETTE_A.tealDeep : PALETTE_A.mutedSolid),
                transition: "all 0.3s",
              }}>
                {isDone ? <Icon name="check" size={17} color={PALETTE_A.tealDeep} stroke={2} /> : <Icon name={ph.icon} size={17} stroke={isActive ? 2 : 1.8} />}
              </div>
              <div style={{ minWidth: 0 }}>
                <div style={{
                  fontSize: 13.5, fontWeight: isActive ? 700 : 600,
                  color: isActive ? PALETTE_A.tealDeep : (isDone ? PALETTE_A.text2 : PALETTE_A.text2),
                  lineHeight: 1.1, whiteSpace: "nowrap",
                }}>{ph.label}</div>
                <div style={{ fontSize: 10.5, color: PALETTE_A.mutedSolid, marginTop: 2, whiteSpace: "nowrap" }}>{ph.sub}</div>
              </div>
            </div>
          );
        })}
      </div>

      <div style={{
        marginTop: 18, padding: "13px 14px", borderRadius: 14,
        background: PALETTE_A.panel, display: "flex", alignItems: "center", gap: 11,
      }}>
        <div style={{ width: 30, height: 30, borderRadius: 8, background: PALETTE_A.tealSoft, display: "grid", placeItems: "center", color: PALETTE_A.tealDeep }}>
          <Icon name="lock" size={15} color={PALETTE_A.tealDeep} />
        </div>
        <div style={{ fontSize: 11, color: PALETTE_A.text2, lineHeight: 1.4 }}>
          Dados protegidos<br /><span style={{ color: PALETTE_A.mutedSolid }}>conforme a LGPD</span>
        </div>
      </div>
    </div>
  );
}

// ── topbar (inside content) ─────────────────────────────────────────────
function TopBar({ step, total }) {
  const pct = ((step + 1) / total) * 100;
  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 20,
      padding: "22px 56px 0", flexShrink: 0,
    }}>
      <div style={{ flex: 1, height: 5, borderRadius: 3, background: PALETTE_A.panelAlt, overflow: "hidden" }}>
        <div style={{ width: `${pct}%`, height: "100%", background: PALETTE_A.tealGrad, borderRadius: 3, transition: "width .5s cubic-bezier(.2,.8,.2,1)" }} />
      </div>
      <div style={{ fontSize: 12.5, color: PALETTE_A.mutedSolid, fontWeight: 600, whiteSpace: "nowrap" }}>
        Etapa <span style={{ color: PALETTE_A.tealDeep, fontWeight: 700 }}>{String(step + 1).padStart(2, "0")}</span> <span style={{ opacity: 0.6 }}>/ {total}</span>
      </div>
    </div>
  );
}

// ── 3D viewport backdrop (gives the near-white model contrast) ───────────
const viewportBg = "radial-gradient(ellipse 70% 60% at 50% 38%, #fff0ef 0%, #f9d5bd 78%)";

function GlowHalo({ color = "rgba(239,123,96,0.20)", size = "60%" }) {
  return (
    <div style={{
      position: "absolute", inset: 0,
      background: `radial-gradient(circle at 50% 42%, ${color}, transparent ${size})`,
      filter: "blur(14px)", pointerEvents: "none",
    }} />
  );
}

function emptyFichaData() {
  return {
    clinica: "", nome: "", nascimento: "", cpf: "", cep: "", telefone: "", email: "",
    origem: "", quiz: {}, symptoms: [], symptomVerts: {}, vertebrae: {}, painPoints: [], side: "front",
    motivacao: "",
    sobreVoce: {}, exploracao: {}, historico: {}, estiloVida: {}, impacto: {}, objetivos: {},
  };
}

function VarA() {
  const [step, setStep] = useState(0);
  const [data, setData] = useState(emptyFichaData);
  const [submitting, setSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState("");
  const [receiptId, setReceiptId] = useState("");
  const idempotencyKey = useRef("");

  const update = (k, v) => setData((d) => ({ ...d, [k]: v }));
  const isPreventive = data.motivacao === "B";
  const stepName = STEPS_A[step];

  const advance = (dir) => {
    let i = step;
    while (true) {
      i += dir;
      if (i < 0 || i >= STEPS_A.length) { i = Math.max(0, Math.min(STEPS_A.length - 1, i)); break; }
      const nm = STEPS_A[i];
      if (isPreventive && PREVENTIVE_SKIP.includes(nm)) continue;
      break;
    }
    setStep(i);
  };
  const submitFicha = async () => {
    if (submitting) return;
    const errors = window.FichaValidation.validateSubmission(data);
    if (Object.keys(errors).length > 0) {
      setSubmitError(Object.values(errors)[0]);
      return;
    }
    setSubmitting(true);
    setSubmitError("");
    if (!idempotencyKey.current) idempotencyKey.current = crypto.randomUUID();
    try {
      const response = await fetch("/api/intake", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Idempotency-Key": idempotencyKey.current,
        },
        body: JSON.stringify(window.FichaValidation.payload(data)),
        signal: AbortSignal.timeout(15_000),
      });
      const result = await response.json().catch(() => ({}));
      if (!response.ok) {
        const fieldMessage = result.fields && result.fields[0] && result.fields[0].message;
        throw new Error(fieldMessage || "Não foi possível enviar a ficha.");
      }
      setReceiptId(result.id || idempotencyKey.current);
      advance(1);
    } catch (error) {
      setSubmitError(error instanceof Error ? error.message : "Falha de conexão. Tente novamente.");
    } finally {
      setSubmitting(false);
    }
  };
  const next = () => stepName === "objetivos" ? void submitFicha() : advance(1);
  const prev = () => advance(-1);
  const isWelcome = stepName === "welcome";

  return (
    <div style={{
      position: "relative", width: 1300, height: 850,
      background: PALETTE_A.card, color: PALETTE_A.text,
      fontFamily: "'Inter', sans-serif",
      borderRadius: 28, overflow: "hidden", display: "flex",
      boxShadow: "0 50px 120px -30px rgba(20,50,55,0.4), 0 0 0 1px rgba(74,39,35,0.04)",
    }}>
      <Sidebar stepName={stepName} isPreventive={isPreventive} />

      <div style={{ flex: 1, minWidth: 0, position: "relative", display: "flex", flexDirection: "column", background: PALETTE_A.card }}>
        {!isWelcome && <TopBar step={step} total={STEPS_A.length} />}
        <div style={{ flex: 1, minHeight: 0, position: "relative", display: "flex" }}>
          {stepName === "welcome" && <WelcomeA next={next} />}
          {stepName === "clinic" && <ClinicA data={data} update={update} next={next} prev={prev} />}
          {stepName === "personal" && <PersonalA data={data} update={update} next={next} prev={prev} />}
          {stepName === "origin" && <OriginA data={data} update={update} next={next} prev={prev} />}
          {stepName === "quiz" && <QuizA data={data} update={update} next={next} prev={prev} />}
          {stepName === "motivacao" && <window.ExtraSteps.MotivacaoStep data={data} update={update} next={next} prev={prev} />}
          {stepName === "symptoms" && <SymptomsA data={data} update={update} next={next} prev={prev} />}
          {stepName === "spine" && <SpineA data={data} update={update} next={next} prev={prev} />}
          {stepName === "body" && <BodyA data={data} update={update} next={next} prev={prev} />}
          {stepName === "sobreVoce" && <window.ExtraSteps.SobreVoceStep data={data} update={update} next={next} prev={prev} />}
          {stepName === "exploracao" && <window.ExtraSteps.ExploracaoStep data={data} update={update} next={next} prev={prev} />}
          {stepName === "historico" && <window.ExtraSteps.HistoricoStep data={data} update={update} next={next} prev={prev} />}
          {stepName === "estiloVida" && <window.ExtraSteps.EstiloVidaStep data={data} update={update} next={next} prev={prev} />}
          {stepName === "impacto" && <window.ExtraSteps.ImpactoStep data={data} update={update} next={next} prev={prev} />}
          {stepName === "objetivos" && <window.ExtraSteps.ObjetivosStep data={data} update={update} next={next} prev={prev} submitting={submitting} submitError={submitError} />}
          {stepName === "summary" && <SummaryA data={data} receiptId={receiptId} prev={prev} reset={() => { setStep(0); setData(emptyFichaData()); setReceiptId(""); setSubmitError(""); idempotencyKey.current = ""; }} />}
        </div>
      </div>
    </div>
  );
}

// ── shared 3D spine helpers ───────────────────────────────────────────────
function MiniSpine({ size = 220 }) {
  const ref = useRef(null);
  useEffect(() => {
    let api; let cancelled = false;
    window.SpineKit.mountSpine({
      container: ref.current,
      palette: { bone: PALETTE_A.bone, accent: PALETTE_A.accentHex, accentLight: PALETTE_A.accentLight },
      interactive: false,
    }).then((a) => { if (cancelled) a.dispose(); else api = a; });
    return () => { cancelled = true; if (api) api.dispose(); };
  }, []);
  return <div ref={ref} style={{ width: size, height: size * 1.4 }} />;
}

function SketchfabSpine({ modelUrl = "spine-model-2.glb" }) {
  return (
    <window.GLBSpine
      modelUrl={modelUrl}
      palette={{ bone: PALETTE_A.bone, accent: PALETTE_A.accent, accentLight: PALETTE_A.accentLight, muted: PALETTE_A.mutedSolid }}
      fallback={<MiniSpine size={320} />}
    />
  );
}

// ── WELCOME ────────────────────────────────────────────────────────────────
function WelcomeA({ next }) {
  return (
    <div style={{ display: "flex", width: "100%" }}>
      <div style={{ flex: 1, padding: "0 0 0 64px", display: "flex", flexDirection: "column", justifyContent: "center" }}>
        <div style={{
          display: "inline-flex", alignItems: "center", gap: 9, alignSelf: "flex-start",
          padding: "7px 14px", borderRadius: 999,
          background: PALETTE_A.tealSoft, color: PALETTE_A.tealDeep,
          fontSize: 12, fontWeight: 600, letterSpacing: "0.04em", marginBottom: 26,
        }}>
          <span style={{ width: 7, height: 7, borderRadius: 4, background: PALETTE_A.teal, animation: "pulse 1.6s ease-in-out infinite" }} />
          Avaliação inicial · coluna vertebral
        </div>
        <h1 style={{ fontSize: 68, fontWeight: 700, lineHeight: 0.98, margin: 0, letterSpacing: "-0.04em", color: PALETTE_A.text }}>
          Vamos cuidar<br />da sua <span style={{ color: PALETTE_A.teal }}>coluna</span>.
        </h1>
        <p style={{ fontSize: 18, color: PALETTE_A.text2, marginTop: 24, lineHeight: 1.55, maxWidth: 440 }}>
          Sua avaliação em ~8 minutos. Mapeamos sua coluna em 3D e organizamos seu histórico — clínico, mas humano.
        </p>
        <div style={{ display: "flex", gap: 28, marginTop: 32 }}>
          {[
            { n: "8 min", l: "para concluir" },
            { n: "100%", l: "confidencial" },
            { n: "3D", l: "mapa da coluna" },
          ].map((s) => (
            <div key={s.l}>
              <div style={{ fontSize: 26, fontWeight: 700, color: PALETTE_A.text, letterSpacing: "-0.02em" }}>{s.n}</div>
              <div style={{ fontSize: 12.5, color: PALETTE_A.mutedSolid, marginTop: 2 }}>{s.l}</div>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 36 }}>
          <Btn onClick={next}>Iniciar avaliação <Icon name="arrow" size={17} color="#fff" /></Btn>
        </div>
      </div>

      <div style={{ flex: "0 0 480px", position: "relative", margin: "28px 28px 28px 0", borderRadius: 24, overflow: "hidden", background: viewportBg }}>
        <GlowHalo color="rgba(239,123,96,0.22)" />
        <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center" }}>
          <div style={{ width: 360, height: 600 }}><SketchfabSpine /></div>
        </div>
        {/* floating stat cards anchored to the column */}
        <FloatCard style={{ position: "absolute", top: 60, right: 30, width: 168 }}>
          <div style={{ fontSize: 11, color: PALETTE_A.mutedSolid, fontWeight: 600, letterSpacing: "0.04em" }}>Relatam melhora</div>
          <div style={{ display: "flex", alignItems: "baseline", gap: 4, marginTop: 6 }}>
            <span style={{ fontSize: 34, fontWeight: 700, color: PALETTE_A.tealDeep, letterSpacing: "-0.02em" }}>95</span>
            <span style={{ fontSize: 16, fontWeight: 700, color: PALETTE_A.tealDeep }}>%</span>
          </div>
          <div style={{ display: "flex", gap: 3, marginTop: 8 }}>
            {[0.4, 0.6, 0.5, 0.85, 0.7, 1, 0.8].map((h, i) => (
              <div key={i} style={{ flex: 1, height: 26 * h, borderRadius: 2, background: PALETTE_A.tealGrad, alignSelf: "flex-end", opacity: 0.85 }} />
            ))}
          </div>
        </FloatCard>
        <FloatCard style={{ position: "absolute", bottom: 54, left: 26, width: 184, display: "flex", alignItems: "center", gap: 12 }}>
          <div style={{ width: 38, height: 38, borderRadius: 11, background: PALETTE_A.accentSoft, display: "grid", placeItems: "center", flexShrink: 0 }}>
            <Icon name="spine" size={20} color={PALETTE_A.accent} />
          </div>
          <div>
            <div style={{ fontSize: 14, fontWeight: 700, color: PALETTE_A.text, lineHeight: 1.1 }}>33 vértebras</div>
            <div style={{ fontSize: 11.5, color: PALETTE_A.mutedSolid, marginTop: 2 }}>mapeadas em 3D</div>
          </div>
        </FloatCard>
        <div style={{ position: "absolute", bottom: 18, left: 0, right: 0, textAlign: "center", fontSize: 11, color: PALETTE_A.mutedSolid, fontWeight: 500, letterSpacing: "0.04em", pointerEvents: "none" }}>
          ⟳ Arraste para explorar
        </div>
      </div>
    </div>
  );
}

// ── content shell for form steps ───────────────────────────────────────────
function FormPane({ children }) {
  return <div style={{ width: "100%", padding: "34px 56px 40px", display: "flex", flexDirection: "column", overflow: "hidden" }}>{children}</div>;
}

// ── CLINIC ────────────────────────────────────────────────────────────────
function ClinicA({ data, update, next, prev }) {
  const [open, setOpen] = useState(false);
  return (
    <div style={{ width: "100%", display: "flex" }}>
      <div style={{ flex: 1, padding: "34px 48px 40px 56px", display: "flex", flexDirection: "column", justifyContent: "center", maxWidth: 580 }}>
        <StepHeader kicker="Cadastro · Localização" title="Em qual unidade você está hoje?" sub="Direcionamos seu atendimento à equipe certa da sua cidade." />
        <div style={{ position: "relative" }}>
          <button onClick={() => setOpen(!open)} style={{
            width: "100%", padding: "17px 20px", textAlign: "left",
            background: PALETTE_A.panel, border: `1.5px solid ${data.clinica ? PALETTE_A.teal : PALETTE_A.border}`,
            borderRadius: 16, color: data.clinica ? PALETTE_A.text : PALETTE_A.mutedSolid,
            fontSize: 15, cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center",
            fontFamily: "'Inter', sans-serif", fontWeight: 500,
          }}>
            <span style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <span style={{ width: 30, height: 30, borderRadius: 9, background: PALETTE_A.tealSoft, display: "grid", placeItems: "center" }}>
                <Icon name="pin" size={16} color={PALETTE_A.teal} />
              </span>
              {data.clinica || "Escolha uma unidade…"}
            </span>
            <span style={{ color: PALETTE_A.mutedSolid, transform: open ? "rotate(180deg)" : "none", transition: "transform 0.2s" }}>▾</span>
          </button>
          {open && (
            <div style={{
              position: "absolute", top: "calc(100% + 8px)", left: 0, right: 0,
              background: PALETTE_A.card, border: `1px solid ${PALETTE_A.border}`,
              borderRadius: 16, overflow: "hidden", zIndex: 20,
              maxHeight: 280, overflowY: "auto",
              boxShadow: "0 24px 50px -16px rgba(20,50,55,0.3)",
            }}>
              {window.FichaData.cidades.map((c) => (
                <div key={c} onClick={() => { update("clinica", c); setOpen(false); }}
                  style={{ padding: "14px 20px", cursor: "pointer", fontSize: 14, color: PALETTE_A.text2, borderBottom: `1px solid ${PALETTE_A.border}`, transition: "all 0.15s" }}
                  onMouseEnter={(e) => { e.currentTarget.style.background = PALETTE_A.tealSoft; e.currentTarget.style.color = PALETTE_A.tealDeep; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; e.currentTarget.style.color = PALETTE_A.text2; }}>
                  {c}
                </div>
              ))}
            </div>
          )}
        </div>
        <NavBar onBack={prev} onNext={next} canNext={!!data.clinica} />
      </div>
      <div style={{ flex: "0 0 360px", position: "relative", margin: "24px 24px 24px 0", borderRadius: 22, overflow: "hidden", background: viewportBg }}>
        <GlowHalo />
        <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center" }}>
          <div style={{ width: 260, height: 440 }}><SketchfabSpine modelUrl="spine-model-clinic.glb" /></div>
        </div>
      </div>
    </div>
  );
}

// ── inputs ──────────────────────────────────────────────────────────────
function FieldA({ label, children }) {
  return (
    <div style={{ marginBottom: 18 }}>
      <div style={{ fontSize: 12, color: PALETTE_A.text2, fontWeight: 600, letterSpacing: "0.02em", marginBottom: 9 }}>{label}</div>
      {children}
    </div>
  );
}

function FieldErrorA({ message }) {
  if (!message) return null;
  return <div role="alert" style={{ color: "#c2412d", fontSize: 11.5, marginTop: 6 }}>{message}</div>;
}

const inputStyleA = {
  width: "100%", padding: "15px 18px",
  background: PALETTE_A.panel, border: `1.5px solid ${PALETTE_A.border}`,
  borderRadius: 14, color: PALETTE_A.text, fontSize: 15,
  fontFamily: "'Inter', sans-serif", outline: "none",
};

function PersonalA({ data, update, next, prev }) {
  const errors = window.FichaValidation.personalErrors(data);
  const valid = Object.keys(errors).length === 0;
  const fmtCPF = (v) => v.replace(/\D/g, "").slice(0, 11).replace(/(\d{3})(\d)/, "$1.$2").replace(/(\d{3})\.(\d{3})(\d)/, "$1.$2.$3").replace(/(\d{3})\.(\d{3})\.(\d{3})(\d)/, "$1.$2.$3-$4");
  const fmtCEP = (v) => v.replace(/\D/g, "").slice(0, 8).replace(/(\d{5})(\d)/, "$1-$2");
  const fmtPhone = (v) => {
    const d = v.replace(/\D/g, "").slice(0, 11);
    return d.length > 10
      ? d.replace(/(\d{2})(\d{5})(\d{4})/, "($1) $2-$3")
      : d.replace(/(\d{2})(\d{4})(\d{0,4})/, "($1) $2-$3").replace(/-$/, "");
  };
  const today = new Date().toISOString().slice(0, 10);
  return (
    <div style={{ width: "100%", display: "flex" }}>
      <div style={{ flex: 1, padding: "34px 48px 40px 56px", display: "flex", flexDirection: "column", justifyContent: "center", maxWidth: 560 }}>
        <StepHeader kicker="Cadastro · Identificação" title="Alguns dados pessoais" sub="Para manter seu histórico clínico vinculado e seguro." />
        <FieldA label="Nome completo">
          <input value={data.nome} onChange={(e) => update("nome", e.target.value.slice(0, 200))} autoComplete="name" maxLength={200} aria-invalid={!!errors.nome} style={inputStyleA} />
          <FieldErrorA message={data.nome ? errors.nome : ""} />
        </FieldA>
        <FieldA label="Data de nascimento">
          <input type="date" value={data.nascimento} max={today} min="1906-01-01" onChange={(e) => update("nascimento", e.target.value)} autoComplete="bday" aria-invalid={!!errors.nascimento} style={inputStyleA} />
          <FieldErrorA message={data.nascimento ? errors.nascimento : ""} />
        </FieldA>
        <FieldA label="CPF">
          <input value={data.cpf} onChange={(e) => update("cpf", fmtCPF(e.target.value))} placeholder="000.000.000-00" inputMode="numeric" autoComplete="off" maxLength={14} aria-invalid={!!errors.cpf} style={inputStyleA} />
          <FieldErrorA message={data.cpf ? errors.cpf : ""} />
        </FieldA>
        <FieldA label="CEP">
          <input value={data.cep} onChange={(e) => update("cep", fmtCEP(e.target.value))} placeholder="00000-000" inputMode="numeric" autoComplete="postal-code" maxLength={9} aria-invalid={!!errors.cep} style={inputStyleA} />
          <FieldErrorA message={data.cep ? errors.cep : ""} />
        </FieldA>
        <FieldA label="Telefone">
          <input value={data.telefone} onChange={(e) => update("telefone", fmtPhone(e.target.value))} placeholder="(00) 00000-0000" inputMode="tel" autoComplete="tel" maxLength={15} aria-invalid={!!errors.telefone} style={inputStyleA} />
          <FieldErrorA message={data.telefone ? errors.telefone : ""} />
        </FieldA>
        <FieldA label="E-mail">
          <input type="email" value={data.email} onChange={(e) => update("email", e.target.value.slice(0, 254))} placeholder="voce@exemplo.com" autoComplete="email" maxLength={254} aria-invalid={!!errors.email} style={inputStyleA} />
          <FieldErrorA message={data.email ? errors.email : ""} />
        </FieldA>
        <NavBar onBack={prev} onNext={next} canNext={valid} />
      </div>
      <div style={{ flex: "0 0 320px", margin: "34px 56px 40px 0", display: "flex", alignItems: "center" }}>
        <div style={{ width: "100%", padding: 26, borderRadius: 20, background: PALETTE_A.panel, border: `1px solid ${PALETTE_A.border}` }}>
          <div style={{ width: 44, height: 44, borderRadius: 13, background: PALETTE_A.tealSoft, display: "grid", placeItems: "center", marginBottom: 16 }}>
            <Icon name="lock" size={22} color={PALETTE_A.tealDeep} />
          </div>
          <div style={{ fontSize: 15, fontWeight: 700, color: PALETTE_A.text, marginBottom: 8 }}>Seus dados, protegidos</div>
          <div style={{ fontSize: 13.5, color: PALETTE_A.text2, lineHeight: 1.6 }}>
            Tratados conforme a LGPD. Apenas a equipe clínica responsável pelo seu atendimento tem acesso.
          </div>
          <div style={{ marginTop: 18, display: "flex", gap: 5 }}>
            {[1, 2, 3, 4, 5, 6, 7, 8].map((i) => (
              <div key={i} style={{ flex: 1, height: 4, borderRadius: 2, background: PALETTE_A.teal, opacity: 0.18 + (i / 13) }} />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ── ORIGIN ────────────────────────────────────────────────────────────────
function OriginIcon({ icon, color }) {
  const s = { width: 18, height: 18, fill: "none", stroke: color, strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round" };
  if (icon === "instagram") return <svg viewBox="0 0 24 24" {...s}><rect x="3" y="3" width="18" height="18" rx="5" /><circle cx="12" cy="12" r="4" /><circle cx="17.5" cy="6.5" r="0.8" fill={color} /></svg>;
  if (icon === "search") return <svg viewBox="0 0 24 24" {...s}><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>;
  if (icon === "users") return <svg viewBox="0 0 24 24" {...s}><circle cx="9" cy="8" r="3.5" /><path d="M2 21c0-3 3-5 7-5s7 2 7 5" /><circle cx="17" cy="9" r="2.5" /><path d="M16 21c0-2 2-3.5 5-3.5" /></svg>;
  if (icon === "facebook") return <svg viewBox="0 0 24 24" {...s}><path d="M14 8h2V5h-2c-2 0-3 1.5-3 3.5V11H9v3h2v7h3v-7h2.5l.5-3H14V9c0-.5.4-1 1-1z" /></svg>;
  if (icon === "pin") return <svg viewBox="0 0 24 24" {...s}><path d="M12 2C8 2 5 5 5 9c0 5 7 13 7 13s7-8 7-13c0-4-3-7-7-7z" /><circle cx="12" cy="9" r="2.5" /></svg>;
  return <svg viewBox="0 0 24 24" {...s}><circle cx="6" cy="12" r="1.5" fill={color} /><circle cx="12" cy="12" r="1.5" fill={color} /><circle cx="18" cy="12" r="1.5" fill={color} /></svg>;
}

function OriginA({ data, update, next, prev }) {
  return (
    <FormPane>
      <StepHeader kicker="Cadastro · Origem" title="Como você conheceu a Sou Coluna?" sub="Essa informação ajuda nossa equipe a entender melhor nossos pacientes." />
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 14, maxWidth: 880 }}>
        {window.FichaData.origens.map((o) => {
          const sel = data.origem === o.id;
          return (
            <button key={o.id} onClick={() => update("origem", o.id)} style={{
              padding: "20px 22px", textAlign: "left",
              background: sel ? PALETTE_A.tealSoft : PALETTE_A.panel,
              border: `1.5px solid ${sel ? PALETTE_A.teal : PALETTE_A.border}`,
              borderRadius: 16, cursor: "pointer", color: PALETTE_A.text,
              display: "flex", alignItems: "center", gap: 14,
              transition: "all 0.22s", transform: sel ? "translateY(-2px)" : "none",
              boxShadow: sel ? "0 12px 26px -12px rgba(239,123,96,0.45)" : "none",
            }}>
              <div style={{ width: 38, height: 38, borderRadius: 11, background: sel ? PALETTE_A.teal : PALETTE_A.tealSoft, display: "grid", placeItems: "center", transition: "background 0.22s" }}>
                <OriginIcon icon={o.icon} color={sel ? "#fff" : PALETTE_A.teal} />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 15, fontWeight: 600 }}>{o.label}</div>
                {o.sub && <div style={{ fontSize: 12, color: PALETTE_A.mutedSolid, marginTop: 2 }}>{o.sub}</div>}
              </div>
              <div style={{ width: 20, height: 20, borderRadius: 10, border: `1.5px solid ${sel ? PALETTE_A.teal : PALETTE_A.borderStrong}`, background: sel ? PALETTE_A.teal : "transparent", display: "grid", placeItems: "center", transition: "all 0.22s" }}>
                {sel && <Icon name="check" size={13} color="#fff" stroke={2.4} />}
              </div>
            </button>
          );
        })}
      </div>
      <NavBar onBack={prev} onNext={next} canNext={!!data.origem} />
    </FormPane>
  );
}

// ── QUIZ ──────────────────────────────────────────────────────────────────
function QuizA({ data, update, next, prev }) {
  const setAnswer = (id, val) => update("quiz", { ...data.quiz, [id]: val });
  const allAnswered = window.FichaData.quiz.every((q) => data.quiz[q.id]);
  return (
    <div style={{ width: "100%", padding: "30px 56px 36px", display: "flex", flexDirection: "column", overflow: "hidden" }}>
      <StepHeader kicker="Sua intenção · Você sabia?" title="Conhecendo o método" sub="Marque o que você já sabia sobre nosso trabalho." />
      <div style={{ flex: 1, overflowY: "auto", paddingRight: 10, marginRight: -10 }}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, maxWidth: 980 }}>
          {window.FichaData.quiz.map((q, i) => {
            const ans = data.quiz[q.id];
            return (
              <div key={q.id} style={{
                padding: "15px 17px", background: PALETTE_A.panel,
                border: `1.5px solid ${ans ? PALETTE_A.teal + "55" : PALETTE_A.border}`,
                borderRadius: 14, display: "flex", alignItems: "center", gap: 13, transition: "all 0.22s",
              }}>
                <div style={{ width: 26, height: 26, borderRadius: 8, background: PALETTE_A.tealSoft, color: PALETTE_A.tealDeep, display: "grid", placeItems: "center", fontSize: 11.5, fontWeight: 700, flexShrink: 0 }}>{String(i + 1).padStart(2, "0")}</div>
                <div style={{ flex: 1, fontSize: 12.5, lineHeight: 1.4, color: PALETTE_A.text2 }}>{q.text}</div>
                <div style={{ display: "flex", gap: 5, flexShrink: 0 }}>
                  {[{ v: "sim", l: "Sim" }, { v: "nao", l: "Não" }].map(({ v, l }) => (
                    <button key={v} onClick={() => setAnswer(q.id, v)} style={{
                      padding: "7px 14px", borderRadius: 999,
                      background: ans === v ? (v === "sim" ? PALETTE_A.teal : PALETTE_A.panelAlt) : "transparent",
                      border: `1.5px solid ${ans === v ? "transparent" : PALETTE_A.border}`,
                      color: ans === v && v === "sim" ? "#fff" : PALETTE_A.text2,
                      fontSize: 12, cursor: "pointer", fontWeight: 600, transition: "all 0.2s",
                    }}>{l}</button>
                  ))}
                </div>
              </div>
            );
          })}
        </div>
      </div>
      <NavBar onBack={prev} onNext={next} canNext={allAnswered} />
    </div>
  );
}

// ── SPINE 3D (with floating anchored cards) ──────────────────────────────
function SpineA({ data, update, next, prev }) {
  const ref = useRef(null);
  const apiRef = useRef(null);
  const [picked, setPicked] = useState(data.vertebrae || {});
  const [activeVert, setActiveVert] = useState(null);

  useEffect(() => {
    let cancelled = false;
    const mountFn = (window.SpineKitGLB && window.SpineKitGLB.mountSpine) || window.SpineKit.mountSpine;
    Promise.resolve(mountFn({
      container: ref.current,
      palette: { bone: PALETTE_A.bone, accent: PALETTE_A.accentHex, accentLight: PALETTE_A.accentLight },
      modelUrl: "spine-model-2.glb",
      interactive: true,
      onPick: (name) => {
        setActiveVert(name);
        setPicked((prev) => (prev[name] ? prev : { ...prev, [name]: 6 }));
      },
    })).then((api) => {
      if (cancelled) api.dispose();
      else { apiRef.current = api; const map = {}; Object.entries(picked).forEach(([k, v]) => map[k] = v / 10); api.setHighlight(map); }
    });
    return () => { cancelled = true; if (apiRef.current) apiRef.current.dispose(); };
  }, []);

  useEffect(() => {
    if (apiRef.current) {
      const map = {};
      Object.entries(picked).forEach(([k, v]) => { map[k] = v / 10; });
      apiRef.current.setHighlight(map);
      if (apiRef.current.setSelection && activeVert) apiRef.current.setSelection(activeVert);
    }
    update("vertebrae", picked);
  }, [picked, activeVert]);

  const applyIntensity = (val) => { if (activeVert) setPicked({ ...picked, [activeVert]: val }); };
  const removeVert = (name) => {
    const nx = { ...picked }; delete nx[name]; setPicked(nx);
    if (activeVert === name) setActiveVert(null);
  };

  const regions = [
    { label: "Cervical", code: "C1–C7", top: "13%" },
    { label: "Torácica", code: "T1–T12", top: "40%" },
    { label: "Lombar", code: "L1–L5", top: "68%" },
    { label: "Sacro", code: "S1", top: "86%" },
  ];

  return (
    <div style={{ width: "100%", position: "relative", display: "flex", padding: "28px 32px 28px 56px", gap: 24 }}>
      <div style={{ flex: "0 0 290px", display: "flex", flexDirection: "column" }}>
        <StepHeader kicker="Mapa da dor · Coluna 3D" title="Onde está doendo?" sub="Gire a coluna e toque nas vértebras com dor." />
        <div style={{ fontSize: 12, color: PALETTE_A.text2, fontWeight: 600, marginBottom: 10 }}>
          Pontos marcados · <span style={{ color: PALETTE_A.accent }}>{Object.keys(picked).length}</span>
        </div>
        <div style={{ flex: 1, overflowY: "auto", display: "flex", flexDirection: "column", gap: 7, minHeight: 0, paddingRight: 6, marginRight: -6 }}>
          {Object.entries(picked).length === 0 && (
            <div style={{ fontSize: 13, color: PALETTE_A.mutedSolid, fontStyle: "italic", padding: "8px 0" }}>Nenhum ponto marcado ainda. Clique numa vértebra no modelo.</div>
          )}
          {Object.entries(picked).map(([name, intensity]) => (
            <button key={name} onClick={() => setActiveVert(name)} style={{
              padding: "10px 12px", borderRadius: 12, textAlign: "left", cursor: "pointer",
              background: activeVert === name ? PALETTE_A.accentSoft : PALETTE_A.panel,
              border: `1.5px solid ${activeVert === name ? PALETTE_A.accent + "70" : PALETTE_A.border}`,
              display: "flex", alignItems: "center", gap: 10, fontSize: 12.5, transition: "all 0.18s",
            }}>
              <span style={{ fontWeight: 700, color: PALETTE_A.accentDeep, minWidth: 28 }}>{name}</span>
              <div style={{ flex: 1, height: 5, background: PALETTE_A.panelAlt, borderRadius: 3, overflow: "hidden" }}>
                <div style={{ width: `${intensity * 10}%`, height: "100%", background: `linear-gradient(90deg,#ff8765,${PALETTE_A.accent})` }} />
              </div>
              <span style={{ color: PALETTE_A.mutedSolid, fontWeight: 600, minWidth: 16 }}>{intensity}</span>
              <span onClick={(e) => { e.stopPropagation(); removeVert(name); }} style={{ color: PALETTE_A.mutedSolid, cursor: "pointer", fontSize: 16, lineHeight: 1 }}>×</span>
            </button>
          ))}
        </div>
        <NavBar onBack={prev} onNext={next} nextLabel="Próximo: corpo" />
      </div>

      <div style={{ flex: 1, position: "relative", borderRadius: 22, overflow: "hidden", background: viewportBg }}>
        <GlowHalo color="rgba(255,107,74,0.16)" />
        <div ref={ref} style={{ width: "100%", height: "100%" }} />

        <div style={{ position: "absolute", top: 16, left: 18, fontSize: 11, color: PALETTE_A.mutedSolid, fontWeight: 500, letterSpacing: "0.03em" }}>
          ⟳ Arraste para girar · clique para selecionar
        </div>

        {/* region labels anchored on the right edge */}
        {regions.map((r) => (
          <div key={r.code} style={{ position: "absolute", right: 16, top: r.top, transform: "translateY(-50%)", textAlign: "right", pointerEvents: "none" }}>
            <div style={{ fontSize: 12.5, fontWeight: 700, color: PALETTE_A.text2 }}>{r.label}</div>
            <div style={{ fontSize: 10.5, color: PALETTE_A.mutedSolid, fontWeight: 600, letterSpacing: "0.06em" }}>{r.code}</div>
          </div>
        ))}

        {/* live selected-vertebra floating card (anchored bottom-right of viewport) */}
        <FloatCard style={{ position: "absolute", bottom: 22, right: 22, width: 230 }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
            <div style={{ fontSize: 11, color: PALETTE_A.mutedSolid, fontWeight: 600, letterSpacing: "0.04em" }}>Vértebra selecionada</div>
          </div>
          <div style={{ fontSize: 30, fontWeight: 700, color: activeVert ? PALETTE_A.accentDeep : PALETTE_A.mutedSolid, letterSpacing: "-0.02em", marginTop: 2 }}>
            {activeVert || "—"}
          </div>
          {activeVert ? (
            <div style={{ marginTop: 12 }}>
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11, color: PALETTE_A.text2, fontWeight: 600, marginBottom: 6 }}>
                <span>Intensidade da dor</span>
                <span style={{ color: PALETTE_A.accentDeep }}>{picked[activeVert] || 0}/10</span>
              </div>
              <input type="range" min="0" max="10" value={picked[activeVert] || 0} onChange={(e) => applyIntensity(+e.target.value)} style={{ width: "100%", accentColor: PALETTE_A.accent }} />
              <div style={{ display: "flex", justifyContent: "space-between", marginTop: 3, fontSize: 10, color: PALETTE_A.mutedSolid }}>
                <span>sem dor</span><span>insuportável</span>
              </div>
            </div>
          ) : (
            <div style={{ fontSize: 11.5, color: PALETTE_A.mutedSolid, marginTop: 6, lineHeight: 1.4 }}>Toque numa vértebra para registrar a dor.</div>
          )}
        </FloatCard>
      </div>
    </div>
  );
}

// ── BODY SCAN ───────────────────────────────────────────────────────────────
function BodyA({ data, update, next, prev }) {
  const ref = useRef(null);
  const apiRef = useRef(null);
  const [side, setSide] = useState(data.side || "front");
  const [count, setCount] = useState((data.painPoints || []).length);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    let cancelled = false;
    const onPaint = (m) => {
      const limited = m.slice(0, 50);
      setCount(limited.length);
      update("painPoints", limited.map((x) => ({ id: x.id, x: x.pos.x, y: x.pos.y, z: x.pos.z, intensity: x.intensity })));
    };
    window.SpineKit.mountBodyGLB({
      container: ref.current,
      palette: { accent: PALETTE_A.accentHex, accentLight: PALETTE_A.accentLight },
      side, onPaint,
      onReady: () => { if (!cancelled) setLoaded(true); },
      onError: () => {
        if (cancelled) return;
        if (apiRef.current) { try { apiRef.current.dispose(); } catch (e) {} apiRef.current = null; }
        window.SpineKit.mountBody({
          container: ref.current,
          palette: { skin: PALETTE_A.skin, accent: PALETTE_A.accentHex, accentLight: PALETTE_A.accentLight },
          side, onPaint,
        }).then((api) => { if (cancelled) api.dispose(); else { apiRef.current = api; setLoaded(true); } });
      },
    }).then((api) => { if (cancelled) api.dispose(); else apiRef.current = api; }).catch(() => {});
    return () => { cancelled = true; if (apiRef.current) apiRef.current.dispose(); };
  }, []);

  useEffect(() => { if (apiRef.current) apiRef.current.setSide(side); update("side", side); }, [side]);

  return (
    <div style={{ width: "100%", display: "flex", padding: "28px 32px 28px 56px", gap: 24 }}>
      <div style={{ flex: "0 0 290px", display: "flex", flexDirection: "column" }}>
        <StepHeader kicker="Mapa da dor · Corpo" title="Outros pontos de dor" sub="Toque no corpo onde sente dor. Gire arrastando lateralmente." />
        <div style={{ display: "flex", gap: 6, marginBottom: 16, padding: 4, background: PALETTE_A.panel, border: `1px solid ${PALETTE_A.border}`, borderRadius: 999 }}>
          {[{ s: "front", l: "Frente" }, { s: "back", l: "Costas" }].map(({ s, l }) => (
            <button key={s} onClick={() => setSide(s)} style={{
              flex: 1, padding: "10px 16px", borderRadius: 999,
              background: side === s ? PALETTE_A.teal : "transparent",
              color: side === s ? "#fff" : PALETTE_A.text2,
              border: "none", cursor: "pointer", fontSize: 13, fontWeight: 600, transition: "all 0.22s",
            }}>{l}</button>
          ))}
        </div>
        <div style={{ padding: 18, background: PALETTE_A.panel, border: `1px solid ${PALETTE_A.border}`, borderRadius: 16, marginBottom: 16 }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
            <div style={{ fontSize: 12, color: PALETTE_A.text2, fontWeight: 600 }}>Pontos marcados</div>
            <div style={{ fontSize: 30, fontWeight: 700, color: PALETTE_A.accentDeep, letterSpacing: "-0.02em" }}>{String(count).padStart(2, "0")}</div>
          </div>
          <button onClick={() => apiRef.current?.clearMarkers()} style={{
            marginTop: 12, width: "100%", padding: "9px", background: "transparent",
            border: `1px solid ${PALETTE_A.borderStrong}`, borderRadius: 999, color: PALETTE_A.text2,
            cursor: "pointer", fontSize: 12, fontWeight: 600,
          }}>Limpar todos</button>
        </div>
        <div style={{ fontSize: 12.5, color: PALETTE_A.text2, lineHeight: 1.55 }}>
          Cada toque adiciona um ponto. Depois nossa equipe cruza com sua avaliação da coluna.
        </div>
        <NavBar onBack={prev} onNext={next} nextLabel="Finalizar" />
      </div>

      <div style={{ flex: 1, position: "relative", borderRadius: 22, overflow: "hidden", background: viewportBg }}>
        <GlowHalo color="rgba(255,107,74,0.14)" />
        <div ref={ref} style={{ width: "100%", height: "100%" }} />
        <div style={{ position: "absolute", top: 16, left: 18, fontSize: 11, color: PALETTE_A.mutedSolid, fontWeight: 500, letterSpacing: "0.03em" }}>
          Body scan · {side === "front" ? "anterior" : "posterior"} · toque para marcar
        </div>
        {!loaded && (
          <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", color: PALETTE_A.mutedSolid, fontSize: 12, fontWeight: 500, pointerEvents: "none" }}>
            <div style={{ textAlign: "center" }}>
              <div style={{ display: "flex", gap: 5, justifyContent: "center", marginBottom: 12 }}>
                {[0, 1, 2].map((i) => (
                  <div key={i} style={{ width: 7, height: 7, borderRadius: 4, background: PALETTE_A.teal, animation: "pulse 1.2s ease-in-out infinite", animationDelay: `${i * 0.15}s` }} />
                ))}
              </div>
              Carregando modelo anatômico
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ── SUMMARY ─────────────────────────────────────────────────────────────────
function SummaryA({ data, receiptId, prev, reset }) {
  const vertCount = Object.keys(data.vertebrae || {}).length;
  const ptCount = (data.painPoints || []).length;
  const avgInt = vertCount > 0 ? (Object.values(data.vertebrae).reduce((a, b) => a + b, 0) / vertCount).toFixed(1) : "0.0";
  return (
    <div style={{ width: "100%", display: "flex", padding: "34px 40px 40px 56px", gap: 32 }}>
      <div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center" }}>
        <StepHeader kicker="Avaliação concluída" title="Ficha recebida com segurança" sub="Um profissional vai analisar suas respostas e entrar em contato." />
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 14 }}>
          {[
            { k: "Vértebras", v: vertCount, unit: "pts", grad: true },
            { k: "Pontos no corpo", v: ptCount, unit: "pts" },
            { k: "Intensidade média", v: avgInt, unit: "/10" },
          ].map((s) => (
            <div key={s.k} style={{
              padding: 20, borderRadius: 18,
              background: s.grad ? PALETTE_A.tealGrad : PALETTE_A.panel,
              border: s.grad ? "none" : `1px solid ${PALETTE_A.border}`,
              boxShadow: s.grad ? "0 14px 30px -14px rgba(239,123,96,0.5)" : "none",
            }}>
              <div style={{ fontSize: 11.5, color: s.grad ? "rgba(255,255,255,0.85)" : PALETTE_A.mutedSolid, fontWeight: 600, marginBottom: 10 }}>{s.k}</div>
              <div style={{ fontSize: 34, fontWeight: 700, color: s.grad ? "#fff" : PALETTE_A.tealDeep, letterSpacing: "-0.02em" }}>
                {s.v}<span style={{ fontSize: 14, color: s.grad ? "rgba(255,255,255,0.8)" : PALETTE_A.mutedSolid, marginLeft: 4, fontWeight: 600 }}>{s.unit}</span>
              </div>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 18, padding: 22, background: PALETTE_A.panel, border: `1px solid ${PALETTE_A.border}`, borderRadius: 18 }}>
          <div style={{ fontSize: 11.5, color: PALETTE_A.mutedSolid, fontWeight: 600, marginBottom: 14 }}>Resumo do cadastro</div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, fontSize: 13.5, color: PALETTE_A.text2 }}>
            <div><span style={{ color: PALETTE_A.mutedSolid }}>Paciente · </span>{data.nome || "—"}</div>
            <div><span style={{ color: PALETTE_A.mutedSolid }}>Unidade · </span>{data.clinica || "—"}</div>
            <div><span style={{ color: PALETTE_A.mutedSolid }}>Origem · </span>{window.FichaData.origens.find((o) => o.id === data.origem)?.label || "—"}</div>
            <div><span style={{ color: PALETTE_A.mutedSolid }}>Nascimento · </span>{data.nascimento || "—"}</div>
            <div><span style={{ color: PALETTE_A.mutedSolid }}>CPF · </span>{data.cpf || "—"}</div>
            <div><span style={{ color: PALETTE_A.mutedSolid }}>Protocolo · </span>{receiptId ? receiptId.slice(0, 8).toUpperCase() : "—"}</div>
          </div>
        </div>
        <div style={{ display: "flex", gap: 14, marginTop: 30 }}>
          <Btn onClick={reset}>Nova ficha</Btn>
          <Btn variant="ghost" onClick={prev}>Editar pontos</Btn>
        </div>
      </div>

      <div style={{ flex: "0 0 300px", display: "grid", placeItems: "center" }}>
        <div style={{
          width: "100%", height: 360, borderRadius: 24, position: "relative", overflow: "hidden",
          background: "radial-gradient(ellipse at center, rgba(239,123,96,0.14), rgba(239,123,96,0.03) 70%)",
          border: `1px solid ${PALETTE_A.teal}33`, display: "grid", placeItems: "center", textAlign: "center", padding: 24,
        }}>
          <div>
            <div style={{ width: 76, height: 76, borderRadius: "50%", background: PALETTE_A.tealGrad, display: "grid", placeItems: "center", margin: "0 auto", boxShadow: "0 16px 34px -12px rgba(239,123,96,0.6)" }}>
              <Icon name="check" size={40} color="#fff" stroke={2.2} />
            </div>
            <div style={{ fontSize: 18, fontWeight: 700, marginTop: 18, color: PALETTE_A.tealDeep }}>Recebido</div>
            <div style={{ fontSize: 12, color: PALETTE_A.mutedSolid, marginTop: 6, fontWeight: 600, letterSpacing: "0.06em" }}>
              ID #{Math.random().toString(36).slice(2, 8).toUpperCase()}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── SYMPTOMS (neuro map) ────────────────────────────────────────────────────
function SymptomsA({ data, update, next, prev }) {
  return (
    <div style={{ width: "100%", padding: "30px 56px 30px", display: "flex", flexDirection: "column", overflow: "hidden" }}>
      <StepHeader kicker="Mapa da dor · Neuro-vertebral" title="Conectando sintomas à coluna" sub="Cada vértebra liga-se a órgãos e sintomas. Marque o que sente — destacamos as vértebras prováveis." />
      <window.SymptomMapper
        palette={{ bone: PALETTE_A.bone, accentHex: PALETTE_A.accentHex, accentLight: PALETTE_A.accentLight, accent: PALETTE_A.accent, accentSoft: PALETTE_A.accentSoft, border: PALETTE_A.border, text: PALETTE_A.text, muted: PALETTE_A.mutedSolid }}
        initial={{ symptoms: data.symptoms || [], focused: null }}
        height={420}
        onChange={({ symptoms, vertMap }) => { update("symptoms", symptoms); update("symptomVerts", vertMap); }}
      />
      <NavBar onBack={prev} onNext={next} nextLabel="Continuar" />
    </div>
  );
}

window.VarA = VarA;
window.PALETTE_LIGHT = PALETTE_A;
