/* ============================================================
   EDUCARE — Teste ABC (Lourenço Filho)
   Maturidade para a aprendizagem da leitura/escrita — 8 subtestes (0–3) → NM (0–24)
   Teste de papel e lápis: o app administra, registra e calcula.
   ============================================================ */
(function () {
  const { useState, useEffect } = React;
  const Icon = window.Icon;

  const ABC_KEY = "educare-abc-config";
  const ABC_VERSION = 6;

  // Figuras do Teste 3 (movimentos no ar)
  const SPIRAL_D = (function () {
    let d = ""; const cx = 58, cy = 56, turns = 3.1, maxR = 44, steps = 170;
    for (let i = 0; i <= steps; i++) { const t = i / steps; const a = t * turns * 2 * Math.PI; const r = t * maxR; d += (i === 0 ? "M" : "L") + (cx + r * Math.cos(a)).toFixed(1) + " " + (cy + r * Math.sin(a)).toFixed(1) + " "; }
    return d;
  })();
  const MOV2_PTS = "8,82 42,16 76,70 110,16 124,82";
  const MOV3_LEFT = "M14 20 L78 62 L14 104 Z";
  const MOV3_RIGHT = "M138 20 L78 62 L138 104 Z";
  const ROMAN = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII"];

  // Textos PROVISÓRIOS (padrão Teste ABC) — editáveis em "Gerenciar teste".
  const DEFAULT_SUBTESTS = [
    {
      n: 1, name: "Coordenação visomotora", measures: "Cópia de 3 figuras-modelo", type: "qual", extra: false,
      formula: "Apresente as 3 figuras-modelo, uma de cada vez, e peça: “Faça um desenho igualzinho a este.” Não permita apagar.",
      material: "Folha com as 3 figuras-modelo (Teste 1).",
      criteria: [
        "0 — Não reproduz / apenas rabiscos sem relação com os modelos.",
        "1 — Reproduz com grande distorção de forma e proporção.",
        "2 — Reproduz de forma reconhecível, com pequenas distorções.",
        "3 — Reproduz as três figuras com boa precisão de forma e proporção.",
      ],
    },
    {
      n: 2, name: "Memória visual imediata", measures: "Reproduzir 7 figuras vistas por 30s", type: "count", extra: true,
      unit: "figuras corretas",
      formula: "Mostre a cartela com 7 figuras por 30 segundos: “Olhe bem e guarde na memória.” Retire e peça que a criança diga (ou aponte) as figuras que viu.",
      material: "Cartela com 7 figuras (Teste 2).",
      rule: [[7, 7, 3], [4, 6, 2], [2, 3, 1], [0, 1, 0]],
    },
    {
      n: 3, name: "Memória motora", measures: "Reproduzir 3 movimentos no ar", type: "qual", extra: false,
      figset: "mov3",
      formula: "Coloque-se ao lado da criança (mesmo ponto de vista). Trace no ar, com o dedo, cada um dos três movimentos abaixo, um de cada vez: “Faça com a mão igual eu fiz.”",
      material: "Não requer material impresso.",
      note: "Prova de técnica delicada: a criança deve ficar ao lado do examinador (mesmo ponto de vista), não à frente.",
      criteria: [
        "0 — Três traçados iguais (modelo imaginado pela criança), ou, embora diferentes, que em nada lembrem os movimentos sugeridos.",
        "1 — Boa reprodução de uma só figura, sendo irreconhecíveis as demais; ou as três figuras, mesmo imperfeitas, diferentes umas das outras.",
        "2 — Boa reprodução de duas figuras (qualquer que seja a imperfeição da outra); ou as três reconhecíveis e não invertidas, com menor atenção à proporção.",
        "3 — Boa reprodução das três figuras (forma global e proporção geral), não invertidas nem como vistas ao espelho.",
      ],
    },
    {
      n: 4, name: "Memória auditiva", measures: "Repetir 7 palavras", type: "count", extra: true,
      unit: "palavras corretas",
      formula: "Vou dizer sete palavras. Preste muita atenção, porque depois vai dizê-las também. Escute: ÁRVORE – CADEIRA – PEDRA – CACHORRO – FLOR – CASA – PETECA. Repita agora o que eu disse.",
      material: "Não requer material impresso.",
      stimulus: ["ÁRVORE", "CADEIRA", "PEDRA", "CACHORRO", "FLOR", "CASA", "PETECA"],
      rule: [[7, 7, 3], [4, 6, 2], [2, 3, 1], [0, 1, 0]],
    },
    {
      n: 5, name: "Memória lógica", measures: "Recontar uma história", type: "qual", extra: true,
      formula: "Você gosta de histórias? Vou contar uma. Preste atenção porque depois você vai me contar esta mesma história. (Pausa) Maria comprou uma boneca. Era uma linda boneca de louça. A boneca tinha os olhos azuis e um vestido amarelo. Mas, no mesmo dia em que Maria a comprou, a boneca caiu e partiu-se. Maria chorou muito. (Pausa) Agora conte esta mesma história.",
      material: "História no protocolo (anotar a narração da criança).",
      note: "Variante (meninos): João comprou um cavalinho. Era um bonito cavalinho de massa. O cavalinho tinha as pernas pretas e o corpo amarelo. Mas, no mesmo dia em que João o comprou, o cavalinho caiu e quebrou. João chorou muito.\nElementos: 3 ações (comprou, quebrou/partiu, chorou) e 3 minúcias (de louça, olhos azuis, vestido amarelo / de massa, pernas pretas, corpo amarelo).",
      criteria: [
        "0 — Duas ações apenas, ou uma ação e minúcias.",
        "1 — Somente as três ações, ou duas ações e minúcias.",
        "2 — As três ações e uma minúcia.",
        "3 — As três ações capitais e as três minúcias.",
      ],
    },
    {
      n: 6, name: "Linguagem / pronúncia", measures: "Repetir 10 palavras", type: "count", extra: true,
      unit: "palavras corretas",
      formula: "Diga alto: “Cavalheiro!” (pronuncie devagar, mas sem escandir as sílabas). “Muito bem. Agora eu vou dizer outras palavras e você vai repetindo.” Após cada palavra, aguarde a repetição, anotando as mal reproduzidas. Se a criança falar baixo: “Mais alto!”; se atropeladamente: “Mais devagar!”.",
      material: "Não requer material impresso.",
      note: "Palavra de treino (não pontua): Cavalheiro.",
      stimulus: ["Tombadouro", "Pindamonhangaba", "Nabucodonosor", "Desengonçado", "Sardanapalo", "Constantinopla", "Ingrediente", "Cosmopolitismo", "Familiaridade", "Itapetininga"],
      rule: [[9, 10, 3], [5, 8, 2], [2, 4, 1], [0, 1, 0]],
    },
    {
      n: 7, name: "Coordenação motora", measures: "Recorte de 2 traçados", type: "qual", extra: false,
      formula: "Você vai cortar este desenho, o mais depressa que você puder, passando a tesoura bem pelo meio do risco, assim! (Indica-se a operação, dando um ligeiro corte no início do traço sinuoso; coloca-se a tesoura sobre a mesa.) Pode começar. (Marca-se um minuto.) Pare! Agora corte no outro risco. Pode começar! (Marca-se um minuto.) Pare! Muito bem!",
      material: "Folha com os 2 traçados para recorte (Teste 7).",
      note: "A avaliação leva em conta a quantidade e a qualidade do trabalho.",
      criteria: [
        "0 — Não respeitando de modo algum o traçado.",
        "1 — Cortando com regularidade relativa, até metade num dos desenhos e parte do outro.",
        "2 — Cortando mais da metade, saindo do traço; ou, respeitando o traço, cortando menos da metade.",
        "3 — Cortando mais da metade de cada desenho, no tempo de um minuto para cada, sem sair do traço.",
      ],
    },
    {
      n: 8, name: "Atenção e resistência à fadiga", measures: "Pontilhação em 30s", type: "count", extra: false,
      unit: "pontos",
      formula: "No quadriculado: “Faça um pontinho dentro de cada quadradinho, o mais rápido que puder, até eu mandar parar.” Marque 30 segundos.",
      material: "Folha quadriculada (Teste 8).",
      rule: [[51, 99999, 3], [26, 50, 2], [10, 25, 1], [0, 9, 0]],
    },
  ];

  function loadConfig() {
    try {
      const s = JSON.parse(localStorage.getItem(ABC_KEY) || "null");
      if (s && Array.isArray(s.subtests) && s.subtests.length === 8 && s.version === ABC_VERSION) return s;
    } catch (e) { /* ignora */ }
    return { version: ABC_VERSION, subtests: JSON.parse(JSON.stringify(DEFAULT_SUBTESTS)) };
  }
  function saveConfig(cfg) { try { localStorage.setItem(ABC_KEY, JSON.stringify({ ...cfg, version: ABC_VERSION })); } catch (e) { /* indisponível */ } }

  function countToPoints(rule, qty) {
    if (qty === "" || qty == null) return null;
    const q = Number(qty);
    if (isNaN(q)) return null;
    for (let i = 0; i < rule.length; i++) { const r = rule[i]; if (q >= r[0] && q <= r[1]) return r[2]; }
    return 0;
  }
  function ruleText(rule, unit) {
    return rule.map((r) => {
      const range = r[1] >= 9999 ? `> ${r[0] - 1}` : (r[0] === r[1] ? `${r[0]}` : `${r[0]}–${r[1]}`);
      return `${range} ${unit} → ${r[2]}`;
    }).join("  ·  ");
  }
  function subPoints(st, sub) {
    if (st.type === "count") return countToPoints(st.rule, sub.qty);
    return sub.level == null ? null : sub.level;
  }
  function classifyNM(nm) {
    if (nm <= 11) return { label: "Inferior", msg: "A criança não aprenderá, necessitando intervenções." };
    if (nm <= 16) return { label: "Médio", msg: "A aprendizagem se dará facilmente no decurso de um ano letivo." };
    return { label: "Superior", msg: "Permite previsão de que a criança aprenderá a ler e a escrever em um semestre letivo, sem maiores dificuldades." };
  }

  /* ---------------- Material de impressão (abre o PDF oficial) ----------------
     Para ficar idêntico ao manual, o app abre o PDF oficial que você salva na
     pasta do app. Caminho padrão: uploads/teste-abc-material.pdf */
  const ABC_MATERIAL_PDF = "uploads/teste-abc-material.pdf";
  function printMaterial() {
    fetch(ABC_MATERIAL_PDF, { method: "GET" })
      .then((r) => {
        if (!r.ok) throw new Error("not found");
        window.open(ABC_MATERIAL_PDF, "_blank");
      })
      .catch(() => {
        alert("Material oficial não encontrado.\n\nPara imprimir o material IDÊNTICO ao manual, salve o PDF oficial do Teste ABC dentro da pasta do app como:\n\n" + ABC_MATERIAL_PDF + "\n\nDepois clique novamente em “Imprimir material do teste”.");
      });
  }

  function esc(s) { return String(s == null ? "" : s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); }

  /* ---------------- Exportar PDF da folha preenchida ---------------- */
  function exportPDF({ patientName, date, rows, nm, cls, analysis }) {
    const rowsHtml = rows.map((r, i) => `<tr><td class="c">${ROMAN[i]}</td><td>${esc(r.name)}</td><td class="c">${r.pts == null ? "—" : r.pts}</td><td>${esc(r.obs || "")}</td></tr>`).join("");
    const html = `<!DOCTYPE html><html lang="pt-BR"><head><meta charset="UTF-8"><title>Folha — Teste ABC — ${esc(patientName)}</title>
      <style>body{font-family:Arial,Helvetica,sans-serif;color:#142826;padding:24px;font-size:12px}
      h1{font-size:16px;text-align:center;margin:0 0 4px}.meta{margin:8px 0}
      table{width:100%;border-collapse:collapse;margin-top:6px}th,td{border:1px solid #B9C9C5;padding:6px 8px;text-align:left}th{background:#D8E5E2}td.c{text-align:center}
      .nm{margin-top:14px;font-size:14px}.an{margin-top:14px;line-height:1.5}.foot{margin-top:12px;font-size:10px;color:#666}</style></head><body>
      <h1>FOLHA DE REGISTRO — TESTE ABC (Lourenço Filho)</h1>
      <div class="meta"><b>Paciente:</b> ${esc(patientName) || "—"} &nbsp;&nbsp; <b>Data:</b> ${esc(date)}</div>
      <table><tr><th>#</th><th>Subteste</th><th>Nota (0–3)</th><th>Observações</th></tr>${rowsHtml}</table>
      <p class="nm"><b>Nível de Maturidade (NM):</b> ${nm} / 24 &nbsp;—&nbsp; <b>${esc(cls.label)}</b><br/>${esc(cls.msg)}</p>
      ${analysis ? `<p class="an"><b>Análise:</b> ${esc(analysis)}</p>` : ""}
      <p class="foot">Teste ABC de Lourenço Filho. Registro de apoio — não substitui o julgamento clínico.</p>
      </body></html>`;
    const w = window.open("", "_blank");
    if (!w) { alert("Permita pop-ups para exportar o PDF."); return; }
    w.document.write(html); w.document.close(); w.focus();
    setTimeout(() => { try { w.print(); } catch (e) { /* manual */ } }, 300);
  }

  /* ---------------- Editor (Gerenciar teste) ---------------- */
  function ConfigEditor({ config, onSave, onClose }) {
    const [c, setC] = useState(() => JSON.parse(JSON.stringify(config)));
    const upd = (i, field, val) => setC((prev) => ({ ...prev, subtests: prev.subtests.map((s, idx) => (idx === i ? { ...s, [field]: val } : s)) }));
    const updCrit = (i, lvl, val) => setC((prev) => ({ ...prev, subtests: prev.subtests.map((s, idx) => idx === i ? { ...s, criteria: s.criteria.map((cc, k) => (k === lvl ? val : cc)) } : s) }));
    return (
      <div className="form-wrap">
        <button className="pt-back" onClick={onClose}><Icon name="chevL" size={16} /> Voltar</button>
        <div className="page-head"><div><h1>Gerenciar teste — Teste ABC</h1><p className="sub">Edite as fórmulas verbais, materiais e critérios (cole o texto exato do seu protocolo). Fica salvo neste dispositivo.</p></div></div>
        {c.subtests.map((s, i) => (
          <div className="form-card" key={i}>
            <div className="sec-head">Teste {s.n} — {s.name}</div>
            <div className="fld"><label>Fórmula verbal (instrução)</label><textarea className="ctrl" value={s.formula} onChange={(e) => upd(i, "formula", e.target.value)}></textarea></div>
            <div className="fld"><label>Material</label><input className="ctrl" value={s.material} onChange={(e) => upd(i, "material", e.target.value)} /></div>
            {Array.isArray(s.stimulus) && (
              <div className="fld"><label>Estímulos (palavras, separadas por vírgula)</label>
                <input className="ctrl" value={s.stimulus.join(", ")} onChange={(e) => upd(i, "stimulus", e.target.value.split(/[,;]+/).map((x) => x.trim()).filter(Boolean))} /></div>
            )}
            {typeof s.note === "string" && (
              <div className="fld"><label>Referência (variante/elementos)</label>
                <textarea className="ctrl" value={s.note} onChange={(e) => upd(i, "note", e.target.value)}></textarea></div>
            )}
            {s.type === "qual" && (
              <div className="fld" style={{ marginBottom: 0 }}><label>Critérios (níveis 0 a 3)</label>
                {s.criteria.map((cc, k) => <input key={k} className="ctrl" style={{ marginBottom: 6 }} value={cc} onChange={(e) => updCrit(i, k, e.target.value)} />)}
              </div>
            )}
            {s.type === "count" && <p className="help-text" style={{ marginBottom: 0 }}>Conversão automática: {ruleText(s.rule, s.unit)}.</p>}
          </div>
        ))}
        <div className="save-bar"><button className="btn btn-primary" onClick={() => onSave(c)}><Icon name="clipboardCheck" size={18} /> Salvar configuração</button></div>
        <div style={{ textAlign: "center", marginTop: 8 }}><button className="text-link" onClick={() => setC({ version: ABC_VERSION, subtests: JSON.parse(JSON.stringify(DEFAULT_SUBTESTS)) })}>Restaurar padrão</button></div>
      </div>
    );
  }

  function MovFigures() {
    const S = { fill: "none", stroke: "var(--text)", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" };
    return (
      <div className="abc-figs">
        <figure className="abc-fig"><svg viewBox="0 0 116 112">{React.createElement("path", Object.assign({ d: SPIRAL_D }, S))}</svg><figcaption>Movimento 1</figcaption></figure>
        <figure className="abc-fig"><svg viewBox="0 0 132 98">{React.createElement("polyline", Object.assign({ points: MOV2_PTS }, S))}</svg><figcaption>Movimento 2</figcaption></figure>
        <figure className="abc-fig"><svg viewBox="0 0 152 124">{React.createElement("path", Object.assign({ d: MOV3_LEFT }, S))}{React.createElement("path", Object.assign({ d: MOV3_RIGHT }, S))}</svg><figcaption>Movimento 3</figcaption></figure>
      </div>
    );
  }

  /* ---------------- Wizard ---------------- */
  function newSubs() { return Array.from({ length: 8 }, () => ({ qty: "", level: null, obs: "", extra: "" })); }

  function AbcTest({ onBack, onOpenPatient }) {
    const [config, setConfig] = useState(loadConfig);
    const [editing, setEditing] = useState(false);
    const [step, setStep] = useState(1); // 1=ident, 2..9=subtests, 10=resultado
    const [pid, setPid] = useState("");
    const [date, setDate] = useState(window.todayISO());
    const [subs, setSubs] = useState(newSubs);
    const [err, setErr] = useState("");
    const [saved, setSaved] = useState(false);
    const [avalId, setAvalId] = useState(null);
    const [ia, setIa] = useState(null);
    const [iaBusy, setIaBusy] = useState(false);
    const [iaErro, setIaErro] = useState("");

    if (editing) return <ConfigEditor config={config} onClose={() => setEditing(false)} onSave={(c) => { saveConfig(c); setConfig(c); setEditing(false); }} />;

    const patient = (window.PATIENTS || []).find((p) => p.id === pid);
    const ptsArr = config.subtests.map((st, i) => subPoints(st, subs[i]));
    const nm = ptsArr.reduce((s, p) => s + (p || 0), 0);
    const cls = classifyNM(nm);
    const STEPS = ["Ident."].concat(config.subtests.map((s) => "T" + s.n)).concat(["Result."]);

    function goTop() { const el = document.querySelector(".main-scroll"); if (el) el.scrollTop = 0; }
    function next() { if (step === 1 && !pid) { setErr("Selecione o paciente."); return; } setErr(""); setStep((s) => Math.min(10, s + 1)); goTop(); }
    function prev() { if (step === 1) { onBack(); return; } setStep((s) => s - 1); goTop(); }
    const setSub = (i, v) => setSubs((arr) => arr.map((it, idx) => (idx === i ? v : it)));

    function analysisText() {
      const scored = config.subtests.map((st, i) => ({ name: st.name, p: ptsArr[i] })).filter((x) => x.p != null);
      if (!scored.length) return "";
      const max = Math.max.apply(null, scored.map((x) => x.p));
      const min = Math.min.apply(null, scored.map((x) => x.p));
      const fortes = scored.filter((x) => x.p === max).map((x) => x.name);
      const fracas = scored.filter((x) => x.p === min).map((x) => x.name);
      let t = `NM ${nm}/24 — nível ${cls.label}. ${cls.msg}`;
      if (max !== min) t += ` Áreas mais fortes: ${fortes.join(", ")}. Áreas mais frágeis: ${fracas.join(", ")}.`;
      return t;
    }

    /* Payload da IA — só o necessário para interpretar: escores já
       calculados aqui, primeiro nome e contexto escolar. Nunca o nome
       completo nem o prontuário. */
    function payloadIA() {
      return {
        primeiro_nome: patient ? String(patient.name).split(" ")[0] : "",
        idade: patient ? patient.age : null,
        ano_escolar: patient ? patient.grade : null,
        data: date,
        nm, nm_maximo: 24,
        classificacao: cls.label,
        leitura_da_faixa: cls.msg,
        subtestes: config.subtests.map((st, i) => ({
          n: st.n,
          nome: st.name,
          mede: st.measures,
          nota: ptsArr[i],
          nota_maxima: 3,
          quantidade_acertos: st.type === "count" ? subs[i].qty : null,
          unidade: st.type === "count" ? st.unit : null,
          respostas_da_crianca: subs[i].extra || "",
          observacoes_do_aplicador: subs[i].obs || "",
        })),
      };
    }
    async function gerarIA() {
      setIaBusy(true); setIaErro("");
      try { setIa(await window.EducareIA.gerar("abc", payloadIA())); }
      catch (e) { setIaErro(e.message || "Falha ao gerar a análise."); }
      finally { setIaBusy(false); }
    }
    /* Texto único usado no prontuário e no PDF: laudo da IA quando houver,
       senão o texto das regras locais. */
    const analiseFinal = window.EducareIA.texto(ia, analysisText());

    /* Conteúdo gravado no prontuário. Sai numa função só porque é usado tanto
       ao salvar quanto ao ressincronizar depois que a IA responde. */
    function registro() {
      const rows = config.subtests.map((st, i) => ({ name: st.name, pts: ptsArr[i], obs: subs[i].obs, extra: subs[i].extra, qty: subs[i].qty, level: subs[i].level, type: st.type }));
      return {
        result: `NM ${nm}/24 · ${cls.label}`,
        note: analiseFinal,
        sheet: { kind: "abc", nm, cls, rows, ia },
      };
    }

    function save() {
      const rec = window.addAvaliacao({ pid, name: "Teste ABC", date, ...registro() });
      setAvalId(rec ? rec.id : null);
      setSaved(true);
    }

    /* Gerar a análise depois de salvar não pode deixar a ficha com o texto
       antigo: assim que o laudo chega, o registro já gravado é reescrito. */
    useEffect(() => {
      if (!avalId || !ia) return;
      window.atualizarAvaliacao(avalId, registro());
    }, [ia, avalId]);

    const stIdx = step - 2; // índice do subteste quando 2..9
    const st = config.subtests[stIdx];
    const sub = subs[stIdx];
    const livePts = st ? subPoints(st, sub) : null;

    return (
      <div className="form-wrap">
        <div className="hay-top">
          <button className="pt-back" onClick={onBack}><Icon name="chevL" size={16} /> Voltar para avaliações</button>
          <span style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
            <button className="btn btn-ghost btn-xs" onClick={() => printMaterial(patient ? patient.name : "")}><Icon name="download" size={14} /> Imprimir material do teste</button>
            {step === 1 && <button className="btn btn-ghost btn-xs" onClick={() => setEditing(true)}><Icon name="fileText" size={14} /> Gerenciar teste</button>}
          </span>
        </div>

        <div className="page-head" style={{ marginBottom: 14 }}>
          <div><h1><Icon name="clipboardList" size={25} /> Teste ABC</h1><p className="sub">Maturidade para a aprendizagem da leitura e escrita (Lourenço Filho) — 8 subtestes.</p></div>
        </div>

        <div className="hay-stepper">
          {STEPS.map((s, i) => (
            <button type="button" key={i} className={"hs" + (i + 1 === step ? " on" : "") + (i + 1 < step ? " done" : "")} onClick={() => { setStep(i + 1); goTop(); }}>
              <span className="hs-n">{i + 1 < step ? <Icon name="clipboardCheck" size={14} stroke={3} /> : (i === 0 ? "•" : (i === STEPS.length - 1 ? "✓" : s.replace("T", "")))}</span>{s}
            </button>
          ))}
        </div>

        {step === 1 && (
          <div className="form-card">
            <div className="sec-head"><span className="si"><Icon name="users" size={18} /></span> Identificação</div>
            <div className="fld"><label>Paciente <span className="req">*</span></label><window.PatientPicker value={pid} onChange={setPid} /></div>
            <div className="fld" style={{ marginBottom: 0 }}><label>Data</label><input className="ctrl" type="date" value={date} onChange={(e) => setDate(e.target.value)} /></div>
          </div>
        )}

        {step >= 2 && step <= 9 && st && (
          <div className="form-card">
            <div className="sec-head"><span className="si">{st.n}</span> {st.name}</div>
            <p className="help-text" style={{ marginTop: 0 }}>O que mede: {st.measures}.</p>
            <div className="hay-instruction"><Icon name="help" size={18} /> {st.formula}</div>
            <p className="help-text"><b>Material:</b> {st.material}</p>

            {Array.isArray(st.stimulus) && st.stimulus.length > 0 && (
              <div className="abc-stim">
                <b>Estímulos — ler para a criança</b>
                <div className="abc-stim-list">{st.stimulus.map((w, i) => <span className="abc-stim-chip" key={i}>{w}</span>)}</div>
              </div>
            )}

            {st.note && (
              <div className="abc-note"><b>Referência</b><p style={{ whiteSpace: "pre-line" }}>{st.note}</p></div>
            )}

            {st.figset === "mov3" && (
              <div className="fld">
                <label>Figuras-modelo (traçar no ar para a criança)</label>
                <MovFigures />
              </div>
            )}

            {st.type === "count" ? (
              <div className="grid-2">
                <div className="fld" style={{ marginBottom: 0 }}>
                  <label>Quantidade de acertos ({st.unit})</label>
                  <input className="ctrl" type="number" min="0" value={sub.qty} onChange={(e) => setSub(stIdx, { ...sub, qty: e.target.value })} placeholder="0" />
                  <p className="help-text">Conversão: {ruleText(st.rule, st.unit)}.</p>
                </div>
                <div className="fld" style={{ marginBottom: 0 }}>
                  <label>Pontuação</label>
                  <div className="pont-box">{livePts == null ? "—" : livePts}</div>
                </div>
              </div>
            ) : (
              <div className="fld" style={{ marginBottom: 0 }}>
                <label>Pontuação (0 a 3)</label>
                <div className="abc-levels">
                  {st.criteria.map((cc, lvl) => (
                    <button type="button" key={lvl} className={"abc-lv" + (sub.level === lvl ? " on" : "")} onClick={() => setSub(stIdx, { ...sub, level: lvl })}>
                      <span className="abc-lv-n">{lvl}</span><span className="abc-lv-t">{cc.replace(/^\d+\s*—\s*/, "")}</span>
                    </button>
                  ))}
                </div>
              </div>
            )}

            {st.extra && (
              <div className="fld" style={{ marginTop: 14, marginBottom: 0 }}>
                <label>Respostas/anotações da criança</label>
                <textarea className="ctrl" value={sub.extra} onChange={(e) => setSub(stIdx, { ...sub, extra: e.target.value })} placeholder="Palavras, figuras nomeadas ou narração ditas pela criança..."></textarea>
              </div>
            )}

            <div className="fld" style={{ marginTop: 14, marginBottom: 0 }}>
              <label>Observações</label>
              <textarea className="ctrl" value={sub.obs} onChange={(e) => setSub(stIdx, { ...sub, obs: e.target.value })} placeholder="Comportamento, estratégias, dificuldades observadas..."></textarea>
            </div>
          </div>
        )}

        {step === 10 && (
          <>
            <div className="hay-sheet-id">
              <span><b>Paciente:</b> {patient ? patient.name : "—"}</span>
              <span><b>Data:</b> {date}</span>
            </div>
            <div className="form-card" style={{ paddingBottom: 8 }}>
              <div className="sec-head">Resumo dos subtestes</div>
              <table className="hay-sheet">
                <thead><tr><th>#</th><th>Subteste</th><th>Nota (0–3)</th></tr></thead>
                <tbody>
                  {config.subtests.map((s, i) => (
                    <tr key={i}><td className="c">{ROMAN[i]}</td><td>{s.name}</td><td className="c">{ptsArr[i] == null ? "—" : ptsArr[i]}</td></tr>
                  ))}
                </tbody>
              </table>
            </div>

            <div className="hay-scores">
              <div className="hsc"><span>Nível de Maturidade</span><b>{nm}/24</b><i>soma dos 8 subtestes</i></div>
              <div className="hsc"><span>Classificação</span><b style={{ fontSize: 20 }}>{cls.label}</b><i>faixa do NM</i></div>
            </div>
            <div className="plan-goal" style={{ marginTop: 14 }}>
              <div className="k">RESULTADO</div>
              <p>{cls.msg}</p>
            </div>
            <window.IaBloco
              report={ia} fallback={analysisText()}
              busy={iaBusy} erro={iaErro} onGerar={gerarIA}
            />

            {saved && (
              <div className="save-ok" style={{ marginTop: 14 }}><span className="so-ic"><Icon name="clipboardCheck" size={18} stroke={2.6} /></span><div><b>Avaliação salva!</b><span>Vinculada ao prontuário{patient ? " de " + patient.name : ""}.</span></div></div>
            )}

            <div className="save-bar" style={{ gap: 10, display: "flex", flexWrap: "wrap" }}>
              {!saved
                ? <button className="btn btn-primary" onClick={save}><Icon name="clipboardCheck" size={18} /> Salvar no prontuário</button>
                : <button className="btn btn-primary" onClick={() => onOpenPatient && pid && onOpenPatient(pid)}><Icon name="users" size={18} /> Ver no prontuário</button>}
              <button className="btn btn-ghost" onClick={() => exportPDF({ patientName: patient ? patient.name : "", date, rows: config.subtests.map((s, i) => ({ name: s.name, pts: ptsArr[i], obs: subs[i].obs })), nm, cls, analysis: analiseFinal })}><Icon name="download" size={18} /> Exportar PDF da folha</button>
              <button className="btn btn-ghost" onClick={() => printMaterial(patient ? patient.name : "")}><Icon name="download" size={18} /> Imprimir material</button>
            </div>
          </>
        )}

        {err && step === 1 && <p className="form-err" style={{ display: "flex", alignItems: "center", gap: 7, color: "#EF4444", fontWeight: 700, fontSize: 13.5, margin: "12px 0 0" }}><Icon name="x" size={15} /> {err}</p>}

        {step < 10 && (
          <div className="hay-nav">
            <button className="btn btn-ghost btn-sm" onClick={prev}><Icon name="chevL" size={16} /> {step === 1 ? "Cancelar" : "Voltar"}</button>
            <button className="btn btn-primary btn-sm" onClick={next}>{step === 9 ? "Ver resultado" : "Continuar"} <Icon name="arrowRight" size={16} /></button>
          </div>
        )}
      </div>
    );
  }

  window.AbcTest = AbcTest;
})();
