/* eslint-disable */
// ============================================================
// ASTEM — Main App
// Two top-level views:
//   - "schema" (default): dental chart + planning panel + summary
//   - "arbre":  decision tree (per-implant, 8 steps)
// ============================================================

const { useState, useMemo, useEffect, Fragment } = React;
const D = window.ASTEM_DATA;

// ── Compute case complexity from tree data ──
function computeComplexity(treeData, implantTeeth) {
  if (!implantTeeth.length) return "inconnue";
  const hasAnyData = implantTeeth.some(t => {
    const tdi = treeData.perImplant?.[t];
    return tdi && Object.keys(tdi).length > 0;
  }) || (treeData.edentement && treeData.edentement.length > 0);
  if (!hasAnyData) return "inconnue";

  const allActs = new Set();
  implantTeeth.forEach(t => {
    const tdi = treeData.perImplant?.[t];
    if (tdi) Object.values(tdi).forEach(path =>
      (path || []).forEach(p => (p.acts || []).forEach(a => allActs.add(a)))
    );
  });
  (treeData.edentement || []).forEach(p => (p.acts || []).forEach(a => allActs.add(a)));

  const EXPERT_ACTS  = new Set([2, 7, 12, 14, 20, 26]);
  const COMPLEX_ACTS = new Set([1, 3, 4, 5, 6, 11, 13, 17, 18, 21, 22, 24, 31]);
  if ([...allActs].some(a => EXPERT_ACTS.has(a)))  return "expert";
  if ([...allActs].some(a => COMPLEX_ACTS.has(a))) return "complexe";
  return "simple";
}

// pre-seeded planning to match the reference screenshot
// 45/46/47 form a plural implant rooted at 46 (45 + 47 auto-marked via expandedPlanning)
const INITIAL_PLANNING = {};

// ── Nom FDI pour une dent ──
function toothName(num) {
  const pos = num % 10;
  const names = {
    1: "Incisive centrale", 2: "Incisive latérale", 3: "Canine",
    4: "1ère prémolaire", 5: "2ème prémolaire",
    6: "1ère molaire", 7: "2ème molaire", 8: "Dent de sagesse",
  };
  return names[pos] || "";
}

function App() {
  // Top wizard step
  const [wizStep, setWizStep] = useState(1); // 0..4
  // 2D / 3D view for the chart
  const [chartMode, setChartMode] = useState("3d");
  // Schema state
  const [planning, setPlanning] = useState(INITIAL_PLANNING);
  const [activeSection, setActiveSection] = useState("prog");
  const [selectedTooth, setSelectedTooth] = useState(null);
  const [hoveredTooth, setHoveredTooth] = useState(null);

  // Arbre state
  // per-implant data: { [toothNum]: { [stepId]: pathArray } }
  // global section 2 (édentement): { type: 'unitaire' | 'plural' | ... }
  const [treeData, setTreeData] = useState({
    perImplant: {},
    edentement: null,
  });
  const [currentImplant, setCurrentImplant] = useState(null);
  const [currentTreeStep, setCurrentTreeStep] = useState(0);
  const [copyFromOpen, setCopyFromOpen] = useState(false);

  // Données d'entrée — état des fichiers uploadés
  const [uploadedFiles, setUploadedFiles] = useState({});
  const TWEAK_DEFAULS = /*EDITMODE-BEGIN*/{
    "accent": "#1FE0A8",
    "primary": "#1B0F8A",
    "showGrid": true,
    "density": "comfortable",
    "theme": "light",
    "lang": "fr"
  }/*EDITMODE-END*/;
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULS);
  useEffect(() => {
    const r = document.documentElement.style;
    r.setProperty("--accent", tweaks.accent);
    if (tweaks.theme === "dark") {
      // Dark theme owns its own --ink color (light text); don't override it.
      r.removeProperty("--ink");
    } else {
      r.setProperty("--ink", tweaks.primary);
    }
  }, [tweaks.accent, tweaks.primary, tweaks.theme]);
  useEffect(() => {
    document.documentElement.setAttribute("data-theme", tweaks.theme || "light");
  }, [tweaks.theme]);

  // Expand planning so plural-implant and plural-bridge neighbors are reflected too.
  // Also computes anchors vs. pontics for bridges.
  const expandedPlanning = useMemo(() => {
    const out = { ...planning };
    Object.entries(planning).forEach(([rootNumStr, p]) => {
      const rootNum = parseInt(rootNumStr);
      // -- IMPLANT plural --
      if (p?.prothese?.implant && p?.implant_type === "plural" && (p.implant_group || []).length) {
        p.implant_group.forEach(n => {
          if (!out[n]?.prothese?.implant) {
            out[n] = {
              ...(out[n] || {}),
              prothese: { implant: true },
              programme: "prothese-virt",
              implant_type: "plural",
              implant_group_root: rootNum,
            };
          }
        });
      }
      // -- BRIDGE: plural-style: choose adjacent teeth, end teeth are anchors --
      if (p?.prothese?.bridge && (p.bridge_group || []).length) {
        const all = [rootNum, ...p.bridge_group].sort((a, b) => a - b);
        const minN = all[0];
        const maxN = all[all.length - 1];
        // Apply role to root tooth itself
        out[rootNum] = {
          ...(out[rootNum] || {}),
          bridge_role: (rootNum === minN || rootNum === maxN) ? "anchor" : "pontic",
        };
        p.bridge_group.forEach(n => {
          out[n] = {
            ...(out[n] || {}),
            prothese: { bridge: true },
            programme: "prothese-virt",
            bridge_group_root: rootNum,
            bridge_role: (n === minN || n === maxN) ? "anchor" : "pontic",
          };
        });
      } else if (p?.prothese?.bridge) {
        // Single-tooth bridge → treat as anchor
        out[rootNum] = { ...(out[rootNum] || {}), bridge_role: "anchor" };
      }
    });
    return out;
  }, [planning]);

  const implantTeeth = useMemo(() =>
    Object.entries(expandedPlanning)
      .filter(([_, p]) => p?.prothese?.implant && !p?.implant_group_root)
      .map(([n]) => parseInt(n))
      .sort((a,b)=>a-b),
    [expandedPlanning]
  );

  const complexity = useMemo(() => computeComplexity(treeData, implantTeeth), [treeData, implantTeeth]);

  useEffect(() => {
    if (wizStep === 2 && !currentImplant && implantTeeth.length > 0) {
      setCurrentImplant(implantTeeth[0]);
    }
  }, [wizStep, implantTeeth, currentImplant]);

  const updateTooth = (num, patch) => {
    setPlanning(p => ({
      ...p,
      [num]: { ...(p[num] || {}), ...patch },
    }));
  };
  const updateManyTeeth = (updates) => {
    setPlanning(p => {
      const next = { ...p };
      Object.entries(updates).forEach(([num, patch]) => {
        next[num] = { ...(next[num] || {}), ...patch };
      });
      return next;
    });
  };

  // (legacy block removed — expansion now done once above)

  const resetPlanning = () => {
    setPlanning({});
    setTreeData({ perImplant: {}, edentement: null });
    setCurrentImplant(null);
    setCurrentTreeStep(0);
    setUploadedFiles({});
    setSelectedTooth(null);
    setWizStep(1);
  };

  const openArbre = () => {
    if (implantTeeth.length === 0) {
      alert("Marquez au moins une dent comme implant virtuel pour lancer l'arbre de décision.");
      return;
    }
    setWizStep(2);
    setCurrentTreeStep(0);
  };

  // ===== Tree helpers =====
  const getCurrentPath = () => {
    if (!currentImplant) return [];
    const step = D.TREE_STEPS[currentTreeStep];
    if (!step) return [];
    if (step.global) {
      return treeData.edentement || [];
    }
    return treeData.perImplant?.[currentImplant]?.[step.id] || [];
  };

  const setCurrentPath = (path) => {
    const step = D.TREE_STEPS[currentTreeStep];
    if (step.global) {
      setTreeData(t => ({ ...t, edentement: path }));
    } else {
      setTreeData(t => ({
        ...t,
        perImplant: {
          ...t.perImplant,
          [currentImplant]: {
            ...(t.perImplant[currentImplant] || {}),
            [step.id]: path,
          },
        },
      }));
    }
  };

  const stepIsDone = (idx, implantNum = currentImplant) => {
    const step = D.TREE_STEPS[idx];
    if (!step) return false;
    if (step.id === "synthese") return false;
    if (step.global) {
      const path = treeData.edentement;
      if (!path || path.length === 0) return false;
      // done si le dernier choix est une feuille (hasNext falsy)
      const last = path[path.length - 1];
      return !last.hasNext;
    }
    const path = treeData.perImplant?.[implantNum]?.[step.id];
    if (!path || path.length === 0) return false;
    // done si la feuille est atteinte (hasNext falsy ou absent pour rétrocompat)
    return !path[path.length - 1].hasNext;
  };

  const stepWarn = (idx, implantNum = currentImplant) => {
    const step = D.TREE_STEPS[idx];
    if (!step) return false;
    const path = step.global
      ? treeData.edentement
      : treeData.perImplant?.[implantNum]?.[step.id];
    if (!path) return false;
    return path.some(p => p.alert);
  };

  const treeDoneMap = useMemo(() => {
    const m = {};
    D.TREE_STEPS.forEach((s, i) => { m[s.id] = stepIsDone(i); });
    return m;
  }, [treeData, currentImplant]);

  const treeWarnMap = useMemo(() => {
    const m = {};
    D.TREE_STEPS.forEach((s, i) => { m[s.id] = stepWarn(i); });
    return m;
  }, [treeData, currentImplant]);

  // True once every implant has all per-implant steps filled
  const allImplantsDone = useMemo(() =>
    implantTeeth.length > 0 && implantTeeth.every(t =>
      D.TREE_STEPS.filter(s => !s.global && s.id !== "synthese")
        .every(s => stepIsDone(D.TREE_STEPS.findIndex(x => x.id === s.id), t))
    ),
    [treeData, implantTeeth]
  );

  function renderSchemaView() {
    return (
      <div className="page">
        <div className="page-head" style={{ display: "flex", alignItems: "center", justifyContent: "space-between", paddingBottom: 0, marginBottom: 8 }}>
          <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
            <h1 style={{ margin: 0 }}>Schéma dentaire programmatif</h1>
            {Object.keys(planning).length > 0 && (
              <button
                className="btn btn-ghost"
                style={{ alignSelf: "flex-start", fontSize: 12, padding: "5px 14px", gap: 6, height: 30 }}
                onClick={() => {
                  if (window.confirm("Réinitialiser complètement la planification ?\nToutes les dents seront remises à l'état naturel."))
                    resetPlanning();
                }}
              >
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" /><path d="M3 3v5h5" />
                </svg>
                Réinitialiser la planification
              </button>
            )}
          </div>
          <div className="view-mode-toggle">
            <button className={chartMode === "2d" ? "active" : ""} onClick={() => setChartMode("2d")}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 3v18"/></svg>
              2D
            </button>
            <button className={chartMode === "3d" ? "active" : ""} onClick={() => setChartMode("3d")}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 2 L2 7 L2 17 L12 22 L22 17 L22 7 Z"/><path d="M2 7 L12 12 L22 7"/><path d="M12 12 L12 22"/></svg>
              3D
            </button>
          </div>
        </div>
        {/* Vue d'ensemble — barre pleine largeur */}
        <window.AstemSummaryPanel planning={expandedPlanning} onOpenArbre={openArbre} horizontal={true} />
        {/* Détail dent + schéma */}
        <div style={{ display: "flex", gap: 20, flex: 1, minHeight: 0 }}>
          <window.AstemDentDetailPanel
            selected={selectedTooth}
            planning={planning}
            onSet={updateTooth}
            onSetMany={updateManyTeeth}
            onOpenArbre={openArbre}
          />
          <div style={{ flex: 1, position: "relative", display: "flex", alignItems: "center", justifyContent: "center", minWidth: 0 }}>
            {chartMode === "2d" ? (
              <div className="chart-wrap">
                <window.ToothChart
                  planning={expandedPlanning}
                  selected={selectedTooth}
                  onSelect={setSelectedTooth}
                  hovered={hoveredTooth}
                  onHover={setHoveredTooth}
                />
              </div>
            ) : (
              <window.AstemToothChart3D
                planning={expandedPlanning}
                selected={selectedTooth}
                onSelect={setSelectedTooth}
                hovered={hoveredTooth}
                onHover={setHoveredTooth}
              />
            )}
          </div>
        </div>
        <div className="bottombar">
          <button className="btn btn-ghost" onClick={() => setWizStep(0)}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M15 18l-6-6 6-6"/></svg>
            Infos patient
          </button>
          <div className="spacer" />
          <button className="btn btn-primary" onClick={() => implantTeeth.length > 0 ? openArbre() : setWizStep(3)}>
            {implantTeeth.length > 0 ? "Arbre de décision" : "Récapitulatif"}
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M9 18l6-6-6-6"/></svg>
          </button>
        </div>
      </div>
    );
  }

  // ===== Render arbre view =====
  function renderArbreView() {
    const step = D.TREE_STEPS[currentTreeStep];
    const isGlobal = step.global;
    const isSynthese = step.id === "synthese";
    const path = getCurrentPath();

    const recapItems = path.map(p => ({
      label: p.questionLabel,
      value: p.optLabel,
      alert: p.alert,
    }));

    const nextStep = () => setCurrentTreeStep(i => Math.min(D.TREE_STEPS.length - 1, i + 1));
    const prevStep = () => setCurrentTreeStep(i => Math.max(0, i - 1));
    const nextStepLabel = D.TREE_STEPS[currentTreeStep + 1]?.short || "Synthèse";

    // Contexte de visibilité pour les règles de masquage (col I du XLS)
    const absentCount = Object.values(expandedPlanning).filter(p =>
      p?.programme === "absente" || p?.programme === "extraction" || p?.prothese?.implant
    ).length;
    const visibilityCtx = {
      tooth: currentImplant,          // dent courante (étapes par implant)
      implantTeeth,                    // toutes les dents implant (étape 2 globale)
      absentCount,                     // nb dents absentes/extraites/implant (masquage "sans greffe")
    };

    return (
      <div className="page" style={{ paddingTop: 0 }}>
        {/* Mini dental chart */}
        <window.MiniDentalChart
          planning={expandedPlanning}
          currentImplant={currentImplant}
          onSelectImplant={(n) => { setCurrentImplant(n); }}
          treeData={treeData}
          treeStepsCount={D.TREE_STEPS.filter(s => !s.global && s.id !== "synthese").length}
        />

        {implantTeeth.length > 1 && currentImplant && (
          <div className="implant-tabs" style={{ marginBottom: 8, marginTop: 2 }}>
            <button className="add" onClick={() => setCopyFromOpen(true)}>
              Reprendre d'un implant…
            </button>
          </div>
        )}

        {/* Main layout: vertical stepper left + content + recap rail */}
        <div className="tree-layout">
          <div className="tree-stepper-column">
            {currentImplant && !isSynthese && (
              <div className="tooth-name-display">
                <div className="tnd-lbl">Implant</div>
                <div className="tnd-num">Dent {currentImplant}</div>
                <div className="tnd-name">{toothName(currentImplant)}</div>
              </div>
            )}
            <window.TreeStepper
              steps={D.TREE_STEPS}
              currentIdx={currentTreeStep}
              onStep={setCurrentTreeStep}
              done={treeDoneMap}
              warnings={treeWarnMap}
            />
          </div>

          {isSynthese ? (
            <SyntheseView
              implants={implantTeeth}
              treeData={treeData}
              currentImplant={currentImplant}
              onSelectImplant={(n) => setCurrentImplant(n)}
              expandedPlanning={expandedPlanning}
              onCopyRequest={implantTeeth.length > 1 ? () => setCopyFromOpen(true) : null}
            />
          ) : (
            <Fragment>
              <window.StepWalker
                step={step}
                value={path}
                onUpdate={setCurrentPath}
                onComplete={() => {}}
                gotoNextStep={nextStep}
                gotoPrevStep={prevStep}
                nextStepLabel={nextStepLabel}
                visibilityCtx={visibilityCtx}
              />
              {path.length > 0 && (
                <window.RecapRail
                  stepNum={step.num}
                  stepShort={step.title}
                  picks={recapItems}
                />
              )}
            </Fragment>
          )}
        </div>

        {/* Bottom nav — always visible */}
        <div className="bottombar">
          <button className="btn btn-ghost" onClick={() => setWizStep(1)}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M15 18l-6-6 6-6"/></svg>
            Schéma dentaire
          </button>
          <div className="spacer" />
          {!isSynthese && (
            <Fragment>
              <button className="btn btn-ghost" onClick={prevStep} disabled={currentTreeStep === 0}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M15 18l-6-6 6-6"/></svg>
                Précédente
              </button>
              <button className="btn btn-primary" onClick={nextStep}>
                {D.TREE_STEPS[currentTreeStep + 1]?.short || "Synthèse"}
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M9 18l6-6-6-6"/></svg>
              </button>
            </Fragment>
          )}
          <button
            className={`btn ${allImplantsDone ? "btn-accent" : "btn-ghost"}`}
            onClick={() => { if (allImplantsDone) setWizStep(3); }}
            style={{ opacity: allImplantsDone ? 1 : 0.42, cursor: allImplantsDone ? "pointer" : "not-allowed" }}
            title={allImplantsDone ? "Accéder au récapitulatif" : "Renseignez tous les implants pour continuer"}
          >
            Récapitulatif
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M9 18l6-6-6-6"/></svg>
          </button>
        </div>

        {/* Copy modal */}
        {copyFromOpen && (
          <CopyFromModal
            implantTeeth={implantTeeth}
            currentImplant={currentImplant}
            treeData={treeData}
            onClose={() => setCopyFromOpen(false)}
            onCopy={(fromTooth, destTeeth) => {
              setTreeData(t => {
                const nextPerImplant = { ...t.perImplant };
                destTeeth.forEach(dest => {
                  nextPerImplant[dest] = { ...(t.perImplant[fromTooth] || {}) };
                });
                return { ...t, perImplant: nextPerImplant };
              });
              setCopyFromOpen(false);
            }}
          />
        )}
      </div>
    );
  }

  // ===== Other wizard step pages =====
  function renderPatientPage() {
    return (
      <div className="page">
        <div className="page-head">
          <h1>Informations patient</h1>
          <p>Renseignez les données administratives et cliniques de base.</p>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(2, minmax(0, 1fr))", gap: 18, maxWidth: 760 }}>
          <FormField label="Nom" value="Dupont" />
          <FormField label="Prénom" value="Michel" />
          <FormField label="Date de naissance" value="28/01/1968" />
          <FormField label="Sexe" value="Masculin" />
          <FormField label="Médecin référent" value="Dr. Lambert" />
          <FormField label="Date de consultation" value="13/05/2026" />
        </div>
        <div className="bottombar">
          <div className="spacer" />
          <button className="btn btn-primary" onClick={() => setWizStep(1)}>
            Schéma dentaire programmatif
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M9 18l6-6-6-6"/></svg>
          </button>
        </div>
      </div>
    );
  }

  function renderRecapPage() {
    return (
      <div className="page" style={{ paddingTop: 6 }}>
        <RecapPage planning={planning} expandedPlanning={expandedPlanning} treeData={treeData} implantTeeth={implantTeeth} />
        <div className="bottombar">
          <button className="btn btn-ghost" onClick={() => setWizStep(1)}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M15 18l-6-6 6-6"/></svg>
            Schéma dentaire
          </button>
          <button className="btn btn-ghost" onClick={() => { setWizStep(2); }}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M15 18l-6-6 6-6"/></svg>
            Arbre de décision
          </button>
          <div className="spacer" />
          <button className="btn btn-primary" onClick={() => setWizStep(4)}>
            Données d'entrée
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M9 18l6-6-6-6"/></svg>
          </button>
        </div>
      </div>
    );
  }

  function renderDonneesPage() {
    const FILES_CONFIG = [
      { id: "cbct",        label: "CBCT",                required: true,  accept: ".dcm,.zip,.nii,.gz", hint: "Imagerie 3D DICOM (.dcm) ou archive (.zip)", icon: "scan3d" },
      { id: "max",         label: "Empreinte maxillaire", required: true,  accept: ".stl,.ply,.obj",     hint: "Scan numérique intra-oral (.stl, .ply)",       icon: "scan"   },
      { id: "mand",        label: "Empreinte mandibulaire", required: true, accept: ".stl,.ply,.obj",    hint: "Scan numérique intra-oral (.stl, .ply)",       icon: "scan"   },
      { id: "mordu",       label: "Mordu occlusal",      required: false, accept: ".stl,.ply,.obj",     hint: "Enregistrement d'occlusion",                   icon: "scan"   },
      { id: "facial",      label: "Scan facial",         required: false, accept: ".stl,.obj,.ply,.zip", hint: "Numérisation du visage",                      icon: "face"   },
      { id: "photo-face",  label: "Photo de face",       required: false, accept: "image/*",            hint: "Portrait frontal, lumière naturelle",           icon: "photo"  },
      { id: "photo-34d",   label: "Photo 3/4 droit",     required: false, accept: "image/*",            hint: "Profil 3/4, côté droit",                       icon: "photo"  },
      { id: "photo-34g",   label: "Photo 3/4 gauche",    required: false, accept: "image/*",            hint: "Profil 3/4, côté gauche",                      icon: "photo"  },
    ];

    const allRequired = FILES_CONFIG.filter(f => f.required).every(f => uploadedFiles[f.id]);

    function FileZone({ cfg }) {
      const file = uploadedFiles[cfg.id];
      const [drag, setDrag] = React.useState(false);
      const inputRef = React.useRef(null);

      function handleFiles(fileList) {
        const f = fileList[0];
        if (!f) return;
        setUploadedFiles(prev => ({ ...prev, [cfg.id]: f }));
      }

      function IconFor({ kind }) {
        const stroke = "var(--ink-2)";
        if (kind === "scan3d") return (
          <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke={stroke} strokeWidth="1.6">
            <path d="M12 2 L2 7 L2 17 L12 22 L22 17 L22 7 Z"/><path d="M2 7 L12 12 L22 7"/><path d="M12 12 L12 22"/>
          </svg>
        );
        if (kind === "scan") return (
          <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke={stroke} strokeWidth="1.6">
            <path d="M12 4Q8 4 7 8Q6 14 7 18Q8 22 12 22Q16 22 17 18Q18 14 17 8Q16 4 12 4Z"/>
            <path d="M9 9Q10 7 12 7Q14 7 15 9"/>
          </svg>
        );
        if (kind === "face") return (
          <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke={stroke} strokeWidth="1.6">
            <circle cx="12" cy="12" r="9"/><circle cx="9" cy="10" r="1.2" fill={stroke}/><circle cx="15" cy="10" r="1.2" fill={stroke}/>
            <path d="M8 15 Q12 18 16 15"/>
          </svg>
        );
        return (
          <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke={stroke} strokeWidth="1.6">
            <rect x="3" y="3" width="18" height="18" rx="3"/><circle cx="8.5" cy="8.5" r="1.5"/>
            <path d="M21 15l-5-5L5 21"/>
          </svg>
        );
      }

      return (
        <div
          className={`file-zone ${drag ? "drag" : ""} ${file ? "has-file" : ""}`}
          onDragOver={e => { e.preventDefault(); setDrag(true); }}
          onDragLeave={() => setDrag(false)}
          onDrop={e => { e.preventDefault(); setDrag(false); handleFiles(e.dataTransfer.files); }}
          onClick={() => inputRef.current?.click()}
        >
          <input ref={inputRef} type="file" accept={cfg.accept} style={{ display: "none" }}
            onChange={e => handleFiles(e.target.files)} />

          {file ? (
            <div className="file-zone-done">
              <div className="file-zone-icon ok">
                <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--accent-2)" strokeWidth="2.5"><path d="M5 12l5 5 9-9"/></svg>
              </div>
              <div className="file-zone-info">
                <div className="file-name">{file.name}</div>
                <div className="file-meta">{(file.size / 1024 / 1024).toFixed(1)} Mo</div>
              </div>
              <button className="file-zone-clear" onClick={e => { e.stopPropagation(); setUploadedFiles(p => { const n = {...p}; delete n[cfg.id]; return n; }); }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M18 6 6 18M6 6l12 12"/></svg>
              </button>
            </div>
          ) : (
            <div className="file-zone-empty">
              <div className="file-zone-icon"><IconFor kind={cfg.icon} /></div>
              <div className="file-zone-text">
                <span className="file-zone-drop">Déposer ou <span className="file-zone-link">choisir</span></span>
                <span className="file-zone-hint">{cfg.hint}</span>
              </div>
            </div>
          )}
        </div>
      );
    }

    const required = FILES_CONFIG.filter(f => f.required);
    const optional = FILES_CONFIG.filter(f => !f.required);

    return (
      <div className="page">
        <div className="page-head">
          <h1>Données d'entrée</h1>
          <p>Déposez ou choisissez les fichiers pour la planification. Les données obligatoires sont requises pour soumettre le cas.</p>
        </div>

        <div style={{ flex: 1, overflow: "auto", minHeight: 0, display: "flex", flexDirection: "column", gap: 22 }}>
          <div>
            <div className="data-group-title">
              <span>Obligatoires</span>
              <span className="data-group-badge">{required.filter(f => uploadedFiles[f.id]).length}/{required.length}</span>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12 }}>
              {required.map(cfg => (
                <div key={cfg.id}>
                  <div className="file-label">{cfg.label} <span className="req">*</span></div>
                  <FileZone cfg={cfg} />
                </div>
              ))}
            </div>
          </div>

          <div>
            <div className="data-group-title">
              <span>Facultatives</span>
              <span className="data-group-badge data-group-badge--opt">{optional.filter(f => uploadedFiles[f.id]).length}/{optional.length}</span>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12 }}>
              {optional.map(cfg => (
                <div key={cfg.id}>
                  <div className="file-label">{cfg.label}</div>
                  <FileZone cfg={cfg} />
                </div>
              ))}
            </div>
          </div>
        </div>

        <div className="bottombar">
          <button className="btn btn-ghost" onClick={() => setWizStep(3)}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M15 18l-6-6 6-6"/></svg>
            Récapitulatif
          </button>
          <div className="spacer" />
          <button
            className={`btn ${allRequired ? "btn-accent" : "btn-ghost"}`}
            style={{ opacity: allRequired ? 1 : 0.55, cursor: allRequired ? "pointer" : "not-allowed" }}
            onClick={() => allRequired && alert("Cas soumis !")}
          >
            Soumettre le cas
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M5 12l5 5 9-9"/></svg>
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className="shell">
      <div className="grid-bg" style={{ opacity: tweaks.showGrid ? 1 : 0 }} />
      <window.AstemHeader
        theme={tweaks.theme}
        onToggleTheme={() => setTweak("theme", tweaks.theme === "dark" ? "light" : "dark")}
        lang={tweaks.lang}
        onToggleLang={() => setTweak("lang", tweaks.lang === "fr" ? "en" : "fr")}
        complexity={complexity}
        wizStep={wizStep}
        disabledSteps={implantTeeth.length === 0 ? [2] : []}
        onWizStep={(i) => {
          if (i === 2 && implantTeeth.length === 0) return;
          setWizStep(i);
        }}
      />
      {wizStep === 0 && renderPatientPage()}
      {wizStep === 1 && renderSchemaView()}
      {wizStep === 2 && renderArbreView()}
      {wizStep === 3 && renderRecapPage()}
      {wizStep === 4 && renderDonneesPage()}

      <window.TweaksPanel title="Tweaks">
        <window.TweakSection title="Couleurs">
          <window.TweakColor label="Accent (mint)" value={tweaks.accent}
            options={["#1FE0A8", "#FF6E4A", "#3D7BFF", "#FFB22C"]}
            onChange={v => setTweak("accent", v)} />
          <window.TweakColor label="Primaire (indigo)" value={tweaks.primary}
            options={["#1B0F8A", "#0C2D7A", "#382F66", "#181E3D"]}
            onChange={v => setTweak("primary", v)} />
        </window.TweakSection>
        <window.TweakSection title="Décor">
          <window.TweakToggle label="Grille perspective" value={tweaks.showGrid}
            onChange={v => setTweak("showGrid", v)} />
        </window.TweakSection>
      </window.TweaksPanel>
    </div>
  );
}

// ----- small UI bits -----
function FormField({ label, value }) {
  return (
    <div>
      <div style={{ fontSize: 12, color: "var(--ink-3)", fontWeight: 600, marginBottom: 6 }}>{label}</div>
      <div style={{ background: "white", borderRadius: 12, padding: "12px 14px", border: "1.5px solid var(--line)", fontWeight: 500 }}>
        {value}
      </div>
    </div>
  );
}

function CopyFromModal({ implantTeeth, currentImplant, treeData, onClose, onCopy }) {
  const [sourceImplant, setSourceImplant] = React.useState(null);
  const [selectedDests, setSelectedDests] = React.useState(
    currentImplant ? [currentImplant] : []
  );

  // Teeth that have at least some tree data → valid sources
  const filledTeeth = implantTeeth.filter(t => {
    const tdi = treeData.perImplant?.[t];
    return tdi && Object.keys(tdi).length > 0;
  });

  // Destinations = all implants except source
  const destCandidates = implantTeeth.filter(t => t !== sourceImplant);

  const toggleDest = (t) => {
    setSelectedDests(prev =>
      prev.includes(t) ? prev.filter(x => x !== t) : [...prev, t]
    );
  };

  // When source changes, reset destinations to all others
  const pickSource = (t) => {
    setSourceImplant(t);
    setSelectedDests(implantTeeth.filter(x => x !== t));
  };

  const canConfirm = sourceImplant && selectedDests.length > 0;

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()} style={{ maxWidth: 440 }}>
        <h3>Reprendre les choix d'un implant</h3>

        {/* Step 1: source */}
        <p className="modal-sub" style={{ marginBottom: 8 }}>
          <strong>1.</strong> Implant source (arbre déjà renseigné) :
        </p>
        {filledTeeth.length === 0 && (
          <div style={{ color: "var(--ink-3)", fontSize: 13, marginBottom: 12 }}>
            Aucun implant avec des données à reprendre.
          </div>
        )}
        <div style={{ display: "flex", flexDirection: "column", gap: 7, marginBottom: 16 }}>
          {filledTeeth.map(t => {
            const filled = D.TREE_STEPS.filter(s => !s.global && s.id !== "synthese")
              .reduce((n, s) => n + (treeData.perImplant?.[t]?.[s.id] ? 1 : 0), 0);
            const isSelected = sourceImplant === t;
            return (
              <div key={t} onClick={() => pickSource(t)}
                style={{
                  border: `1.5px solid ${isSelected ? "var(--accent-2)" : "var(--line)"}`,
                  background: isSelected ? "var(--accent-soft)" : "white",
                  borderRadius: 12, padding: "10px 14px", cursor: "pointer",
                  display: "flex", alignItems: "center", gap: 12, transition: "all .15s",
                }}>
                <div style={{
                  width: 34, height: 34, borderRadius: 9,
                  background: isSelected ? "var(--accent-2)" : "var(--surface-tint)",
                  display: "grid", placeItems: "center",
                  fontWeight: 700, color: isSelected ? "white" : "var(--ink)",
                }}>{t}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 600, fontSize: 13 }}>Dent {t}</div>
                  <div style={{ fontSize: 11, color: "var(--ink-3)" }}>{filled} étape(s) renseignée(s)</div>
                </div>
                {isSelected && (
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--accent-2)" strokeWidth="3"><path d="M5 12l5 5 9-9"/></svg>
                )}
              </div>
            );
          })}
        </div>

        {/* Step 2: destinations (multi-select) */}
        {sourceImplant && (
          <>
            <p className="modal-sub" style={{ marginBottom: 8 }}>
              <strong>2.</strong> Appliquer à (plusieurs choix possibles) :
            </p>
            <div style={{ display: "flex", flexDirection: "column", gap: 7, marginBottom: 16 }}>
              {destCandidates.map(t => {
                const checked = selectedDests.includes(t);
                return (
                  <div key={t} onClick={() => toggleDest(t)}
                    style={{
                      border: `1.5px solid ${checked ? "var(--ink-2)" : "var(--line)"}`,
                      background: checked ? "var(--surface-tint)" : "white",
                      borderRadius: 12, padding: "10px 14px", cursor: "pointer",
                      display: "flex", alignItems: "center", gap: 12, transition: "all .15s",
                    }}>
                    <div style={{
                      width: 18, height: 18, borderRadius: 5,
                      border: `2px solid ${checked ? "var(--ink-2)" : "var(--line)"}`,
                      background: checked ? "var(--ink-2)" : "white",
                      display: "grid", placeItems: "center", flexShrink: 0,
                    }}>
                      {checked && <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" strokeWidth="3.5"><path d="M5 12l5 5 9-9"/></svg>}
                    </div>
                    <div style={{ flex: 1, fontWeight: 600, fontSize: 13 }}>Dent {t}</div>
                  </div>
                );
              })}
            </div>
          </>
        )}

        <div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 4 }}>
          <button className="btn btn-ghost" onClick={onClose}>Annuler</button>
          <button
            className="btn btn-primary"
            style={{ opacity: canConfirm ? 1 : 0.45, cursor: canConfirm ? "pointer" : "not-allowed" }}
            onClick={() => canConfirm && onCopy(sourceImplant, selectedDests)}
          >
            Copier → {selectedDests.length} implant{selectedDests.length > 1 ? "s" : ""}
          </button>
        </div>
      </div>
    </div>
  );
}

// ---- Small tooth SVG for inline use ----
function SmallToothSVG({ num, planning, size }) {
  const sz = size || 34;
  const p = planning ? planning[num] : null;
  const pos = num % 10;
  const type = pos <= 2 ? "incisor" : pos === 3 ? "canine" : pos <= 5 ? "premolar" : "molar";
  const W = type === "molar" ? 22 : type === "premolar" ? 17 : type === "canine" ? 15 : 13;
  const H = type === "molar" ? 26 : type === "premolar" ? 22 : type === "canine" ? 28 : 22;
  const hw = W / 2, hh = H / 2;

  let fill = "#F5F2FC", stroke = "#C9C2E3", dashed = false;
  if (p) {
    if (p.prothese?.implant)  { fill = "#C8F5E2"; stroke = "#00C691"; }
    else if (p.prothese?.couronne) { fill = "#EDE8A0"; stroke = "#C8A800"; }
    else if (p.prothese?.bridge)   { fill = "#DDD6F2"; stroke = "#3D2EB8"; }
    else if (p.programme === "absente")    { fill = "none"; stroke = "#6A5FCC"; dashed = true; }
    else if (p.programme === "extraction") { fill = "#FFD4C5"; stroke = "#E85029"; }
  }

  const pad = 4;
  const vbW = W + pad * 2, vbH = H + pad * 2;
  const pathD = `M ${-hw} ${-hh+3} Q 0 ${-hh-4} ${hw} ${-hh+3} L ${hw} ${hh-3} Q 0 ${hh+4} ${-hw} ${hh-3} Z`;

  return (
    <svg
      width={Math.round(sz * vbW / vbH)}
      height={sz}
      viewBox={`${-hw - pad} ${-hh - pad} ${vbW} ${vbH}`}
      style={{ flexShrink: 0 }}
    >
      <path d={pathD} fill={fill} stroke={stroke} strokeWidth="1.5"
        strokeDasharray={dashed ? "2 2" : undefined} />
    </svg>
  );
}

// ---- Card for one tree step in synthèse (compact) ----
function SyntheseCard({ num, title, path }) {
  const hasData = path && path.length > 0;
  return (
    <div style={{
      background: "white", borderRadius: 10, padding: "7px 10px",
      boxShadow: "var(--shadow-card)",
      borderLeft: `3px solid ${hasData ? "var(--accent)" : "var(--line)"}`,
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: hasData ? 4 : 0 }}>
        <div style={{
          width: 20, height: 20, borderRadius: 999,
          background: hasData ? "var(--accent-soft)" : "var(--surface-tint)",
          color: hasData ? "var(--accent-2)" : "var(--ink-3)",
          display: "grid", placeItems: "center", fontWeight: 700, fontSize: 10,
        }}>{num}</div>
        <span style={{ fontWeight: 600, fontSize: 12 }}>{title}</span>
        {!hasData && <span style={{ marginLeft: "auto", fontSize: 11, color: "var(--ink-3)" }}>—</span>}
      </div>
      {(path || []).map((pick, i) => (
        <div key={i} style={{
          display: "flex", gap: 8, alignItems: "baseline", fontSize: 11,
          padding: "2px 0", borderTop: i > 0 ? "1px solid var(--line-2)" : "none",
        }}>
          <span style={{ color: "var(--ink-3)", minWidth: 90, flexShrink: 0, fontSize: 10 }}>{pick.questionLabel}</span>
          <span style={{ fontWeight: 600, color: pick.alert ? "var(--alert)" : "var(--ink)" }}>
            {pick.optLabel}{pick.alert ? " ⚠" : ""}
          </span>
        </div>
      ))}
    </div>
  );
}

// Synthèse view — per implant, with navigation between teeth
function SyntheseView({ implants, treeData, currentImplant, onSelectImplant, expandedPlanning, onCopyRequest, compact, hideActs }) {
  const perStep = treeData.perImplant?.[currentImplant] || {};
  const globalPath = treeData.edentement || [];
  const implantSteps = D.TREE_STEPS.filter(s => !s.global && s.id !== "synthese");

  const acts = useMemo(() => {
    const all = new Set();
    Object.values(perStep).forEach(path => {
      (path || []).forEach(p => (p.acts || []).forEach(a => all.add(a)));
    });
    globalPath.forEach(p => (p.acts || []).forEach(a => all.add(a)));
    return [...all].sort((a, b) => a - b);
  }, [perStep, globalPath]);

  if (!currentImplant) return (
    <div className="tree-main" style={{ color: "var(--ink-3)", paddingTop: 24 }}>Sélectionnez un implant.</div>
  );

  // Non-compact : 2/3 choices + 1/3 acts rail (no vue d'ensemble)
  if (!compact) {
    return (
      <Fragment>
        <div className="tree-main" style={{ flex: "0 0 62%", maxWidth: "none", paddingTop: 0 }}>
          {/* Header compact */}
          <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 6 }}>
            <SmallToothSVG num={currentImplant} planning={expandedPlanning} size={34} />
            <div>
              <h2 style={{ margin: 0, fontSize: 18 }}>Synthèse — Dent {currentImplant}</h2>
            </div>
          </div>
          {/* Step cards — 2 colonnes compactes */}
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 7 }}>
            {globalPath.length > 0 && (
              <SyntheseCard num={D.STEP_EDENTEMENT.num} title={D.STEP_EDENTEMENT.short} path={globalPath} />
            )}
            {implantSteps.map(step => (
              <SyntheseCard key={step.id} num={step.num} title={step.short} path={perStep[step.id] || []} />
            ))}
          </div>
        </div>

        {/* Right rail 1/3 : actes uniquement */}
        <aside className="recap-rail" style={{ flex: "0 0 26%", overflowY: "auto" }}>
          <div className="head">
            <div className="num">Ω</div>
            <div className="ttl">Actes requis</div>
            <div className="doc-ic">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M9 12l2 2 4-4"/><rect x="5" y="3" width="14" height="18" rx="2"/>
              </svg>
            </div>
          </div>
          {acts.length > 0 ? (
            <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
              {acts.map(a => (
                <div key={a} style={{
                  display: "flex", gap: 8, alignItems: "center",
                  padding: "6px 10px",
                  background: a === 26 ? "var(--alert-soft)" : "var(--surface-soft)",
                  borderRadius: 8,
                }}>
                  <span style={{
                    background: a === 26 ? "var(--alert)" : "var(--ink)",
                    color: "white", borderRadius: 999,
                    minWidth: 24, height: 18, padding: "0 6px",
                    display: "grid", placeItems: "center", fontWeight: 700, fontSize: 10, flexShrink: 0,
                  }}>{a}</span>
                  <span style={{ fontSize: 12, lineHeight: 1.35 }}>{D.ACTS[a]}</span>
                </div>
              ))}
            </div>
          ) : (
            <div style={{ color: "var(--ink-3)", fontSize: 13 }}>Aucun acte requis.</div>
          )}
        </aside>
      </Fragment>
    );
  }

  // Compact (RecapPage) : colonne unique
  return (
    <div style={{ maxWidth: "100%" }}>
      {/* Header */}
      <div style={{ display: "flex", alignItems: "center", gap: 14, marginBottom: 16 }}>
        <SmallToothSVG num={currentImplant} planning={expandedPlanning} size={46} />
        <div>
          <h2 style={{ margin: 0 }}>Synthèse — Dent {currentImplant}</h2>
          <p className="lede" style={{ margin: 0 }}>Récapitulatif des choix pour cet implant.</p>
        </div>
      </div>
      {/* Reprendre d'un autre implant */}
      {onCopyRequest && implants.length > 1 && (
        <div className="implant-tabs" style={{ marginBottom: 8 }}>
          <button className="add" onClick={onCopyRequest}>
            Reprendre d'un implant…
          </button>
        </div>
      )}
      {/* Step cards — 2 colonnes */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 7 }}>
        {globalPath.length > 0 && (
          <SyntheseCard num={D.STEP_EDENTEMENT.num} title={D.STEP_EDENTEMENT.short} path={globalPath} />
        )}
        {implantSteps.map(step => (
          <SyntheseCard key={step.id} num={step.num} title={step.short} path={perStep[step.id] || []} />
        ))}
      </div>
      {/* Acts */}
      {acts.length > 0 && !hideActs && (
        <div style={{ background: "white", borderRadius: 14, padding: "14px 18px", boxShadow: "var(--shadow-card)", marginTop: 10 }}>
          <div style={{ fontWeight: 700, fontSize: 13, marginBottom: 8, color: "var(--ink-2)" }}>Actes requis</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
            {acts.map(a => (
              <div key={a} style={{ display: "flex", gap: 8, alignItems: "center", padding: "5px 8px", background: a === 26 ? "var(--alert-soft)" : "var(--surface-soft)", borderRadius: 7 }}>
                <span style={{ background: a === 26 ? "var(--alert)" : "var(--ink)", color: "white", borderRadius: 999, minWidth: 22, height: 16, padding: "0 5px", display: "grid", placeItems: "center", fontWeight: 700, fontSize: 9, flexShrink: 0 }}>{a}</span>
                <span style={{ fontSize: 11 }}>{D.ACTS[a]}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// Page-level recap (wizard step 3)
function RecapPage({ planning, expandedPlanning, treeData, implantTeeth }) {
  const [recapImplant, setRecapImplant] = React.useState(implantTeeth[0] || null);
  const effPlanning = expandedPlanning || planning;

  const allActs = useMemo(() => {
    const acts = new Set();
    implantTeeth.forEach(t => {
      const tdi = treeData.perImplant?.[t];
      if (tdi) Object.values(tdi).forEach(path =>
        (path || []).forEach(p => (p.acts || []).forEach(a => acts.add(a)))
      );
    });
    (treeData.edentement || []).forEach(p => (p.acts || []).forEach(a => acts.add(a)));
    return [...acts].sort((a, b) => a - b);
  }, [treeData, implantTeeth]);

  return (
    <div style={{ flex: 1, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, minHeight: 0, overflow: "hidden" }}>
      {/* Left: mini chart + schéma summary + actes chirurgicaux */}
      <div className="card recap-card" style={{ padding: "14px 16px", display: "flex", flexDirection: "column", gap: 10, minHeight: 0, overflow: "hidden" }}>
        <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 16, flexShrink: 0 }}>Schéma dentaire</div>
        {/* Icônes schéma dentaire, bien visibles au dessus */}
        <div style={{ flexShrink: 0 }}>
          <window.AstemSummaryPanel planning={effPlanning} horizontal={true} />
        </div>
        <div style={{ flexShrink: 0 }}>
          <window.MiniDentalChart
            planning={effPlanning}
            currentImplant={recapImplant}
            onSelectImplant={n => setRecapImplant(n)}
            treeData={treeData}
            treeStepsCount={D.TREE_STEPS.filter(s => !s.global && s.id !== "synthese").length}
          />
        </div>
        {/* Actes chirurgicaux */}
        <div style={{ flex: 1, minHeight: 0, overflow: "auto" }}>
          <div style={{ fontWeight: 700, fontSize: 13, color: "var(--ink-2)", marginBottom: 8 }}>Actes chirurgicaux</div>
          {allActs.length > 0 ? (
            <div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
              {allActs.map(a => (
                <div key={a} style={{
                  display: "flex", gap: 8, alignItems: "center",
                  padding: "5px 8px",
                  background: a === 26 ? "var(--alert-soft)" : "var(--surface-soft)",
                  borderRadius: 8,
                }}>
                  <span style={{
                    background: a === 26 ? "var(--alert)" : "var(--ink)",
                    color: "white", borderRadius: 999,
                    minWidth: 22, height: 18, padding: "0 5px",
                    display: "grid", placeItems: "center", fontWeight: 700, fontSize: 9, flexShrink: 0,
                  }}>{a}</span>
                  <span style={{ fontSize: 11, lineHeight: 1.35 }}>{D.ACTS[a]}</span>
                </div>
              ))}
            </div>
          ) : (
            <div style={{ color: "var(--ink-3)", fontSize: 13 }}>Aucun acte planifié.</div>
          )}
        </div>
      </div>
      {/* Right: arbre de décision — sans les actes requis (déjà dans schéma) */}
      <div className="card" style={{ padding: "14px 16px", display: "flex", flexDirection: "column", minHeight: 0, overflow: "hidden" }}>
        <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 16, marginBottom: 8, flexShrink: 0 }}>Arbre de décision</div>
        <div style={{ flex: 1, minHeight: 0, overflow: "auto" }}>
          {implantTeeth.length > 0 ? (
            <SyntheseView
              implants={implantTeeth}
              treeData={treeData}
              currentImplant={recapImplant}
              onSelectImplant={setRecapImplant}
              expandedPlanning={effPlanning}
              compact={true}
              hideActs={true}
            />
          ) : (
            <div style={{ color: "var(--ink-3)", fontSize: 14 }}>Aucun implant planifié.</div>
          )}
        </div>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("app")).render(<App />);
