/* simulator.jsx — Simulation du parcours côté adhérent (client du client), mode web desktop.
   Toggle : connecteurs Natif Doxallia (marque blanche, sans rupture) vs Externes (redirections). */
const { useState, useEffect, useRef } = React;

/* ---------- thèmes d'hôte ---------- */
function hostThemes(tenant) {
  return {
    mutuelle: { name: tenant.name, accent: tenant.color, domain: "espace.mutuelle-horizon.fr/adhesion", chip: tenant.initials, external:false },
    idnow:    { name: "IDnow",   accent: "#0f9d8c", domain: "identity.idnow.io/verify", chip: "ID", external:true, real:"IDnow" },
    yousign:  { name: "Yousign", accent: "#6a4cff", domain: "app.yousign.com/sign", chip: "YS", external:true, real:"Yousign" },
  };
}

/* ---------- petits éléments ---------- */
function Spinner({ color = "var(--primary)", size = 34 }) {
  return <div className="spin" style={{ width:size, height:size, borderRadius:"50%", border:`3px solid color-mix(in oklch, ${color} 20%, transparent)`, borderTopColor:color }} />;
}
function Field({ label, children, req }) {
  return <div style={{ marginBottom:13 }}>
    <label style={{ display:"block", fontSize:12.5, fontWeight:600, color:"#334", marginBottom:5 }}>{label} {req && <span style={{color:"#c0392b"}}>*</span>}</label>
    {children}
  </div>;
}
const inputStyle = { width:"100%", border:"1px solid #d4d7dd", borderRadius:8, padding:"9px 11px", fontSize:13.5, fontFamily:"var(--sans)", color:"#222", background:"#fff", boxSizing:"border-box" };

/* ---------- étapes propres aux prestataires externes ----------
   Reproduisent fidèlement la séquence réelle d'un parcours d'identification à
   distance (type IDnow AutoIdent) et d'une signature qualifiée (type Yousign) :
   plusieurs écrans dédiés, là où le natif Doxallia tient en un seul écran intégré. */
const PVID_PHASES = [
  { id:"consent",  label:"Consentement" },
  { id:"docpick",  label:"Pièce" },
  { id:"front",    label:"Recto" },
  { id:"back",     label:"Verso" },
  { id:"liveness", label:"Vidéo selfie" },
];
const ESIGN_PHASES = [
  { id:"identity", label:"Coordonnées" },
  { id:"read",     label:"Lecture" },
  { id:"adopt",    label:"Signature" },
  { id:"otp",      label:"Code OTP" },
];
const extPhases = (serviceId) => serviceId === "pvid" ? PVID_PHASES : ESIGN_PHASES;

/* ---------- construction des scènes ---------- */
function buildScenes(journey, external) {
  const D = window.DATA;
  const scenes = [{ t:"welcome", host:"mutuelle" }];
  journey.steps.forEach(step => {
    if (step.kind === "gate") return;
    if (step.kind === "form") { scenes.push({ t:"form", host:"mutuelle", step }); return; }
    const svc = D.svc(step.serviceId);
    const interactive = step.serviceId === "pvid" || step.serviceId === "esign";
    const backend = step.serviceId === "kyc" || step.serviceId === "sae";
    if (interactive && external) {
      const host = step.serviceId === "pvid" ? "idnow" : "yousign";
      const phases = extPhases(step.serviceId);
      scenes.push({ t:"redirect", host, step, svc });
      phases.forEach((ph, i) => scenes.push({ t:"ext", host, step, svc, phase:ph.id, phaseIdx:i, phases }));
      scenes.push({ t:"extproc", host, step, svc });
      scenes.push({ t:"return", host:"mutuelle", step, svc, from:host });
    } else if (interactive) {
      scenes.push({ t:"step", host:"mutuelle", step, svc, external:false });
    } else if (backend) {
      scenes.push({ t:"processing", host:"mutuelle", step, svc, external });
    } else {
      scenes.push({ t:"notify", host:"mutuelle", step, svc, external });
    }
  });
  scenes.push({ t:"done", host:"mutuelle" });
  return scenes;
}

/* ============================================================ */
function JourneySimulator({ journey, external, setExternal, tenant, onClose }) {
  const D = window.DATA;
  const THEMES = hostThemes(tenant);
  const scenes = buildScenes(journey, external);
  const [idx, setIdx] = useState(0);
  const scene = scenes[Math.min(idx, scenes.length - 1)];
  const theme = THEMES[scene.host];
  const next = () => setIdx(i => Math.min(i + 1, scenes.length - 1));
  const restart = () => setIdx(0);

  // reset quand on change de mode
  useEffect(() => { setIdx(0); }, [external]);

  // auto-avance sur les écrans de transition / traitement
  useEffect(() => {
    if (["redirect","return","processing","extproc"].includes(scene.t)) {
      const ms = scene.t === "processing" ? 2100 : scene.t === "extproc" ? 2400 : scene.t === "redirect" ? 1700 : 1400;
      const id = setTimeout(next, ms);
      return () => clearTimeout(id);
    }
  }, [idx, scene.t]);

  // stats
  const ruptures = scenes.filter(s => s.t === "redirect").length;
  const domains = new Set(scenes.map(s => THEMES[s.host].domain.split("/")[0])).size;

  // étapes logiques pour la timeline
  const logical = journey.steps.filter(s => s.kind !== "gate");
  const currentStepId = scene.step ? (scene.step._id || scene.step.serviceId || scene.step.label) : null;

  return (
    <div style={{ position:"fixed", inset:0, zIndex:120, background:"oklch(0.22 0.02 255)", display:"flex", flexDirection:"column", animation:"fade .15s ease" }}>
      {/* header */}
      <div style={{ display:"flex", alignItems:"center", gap:14, padding:"13px 20px", borderBottom:"1px solid oklch(0.32 0.02 255)", color:"#fff" }}>
        <span style={{ width:34, height:34, borderRadius:9, display:"grid", placeItems:"center", background:"oklch(0.32 0.02 255)" }}><Ic name="Eye" width={18} height={18}/></span>
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ fontSize:15, fontWeight:600 }}>Simulation · {journey.name}</div>
          <div style={{ fontSize:12, color:"oklch(0.72 0.02 255)" }}>Vue de l'adhérent — le client de votre client</div>
        </div>
        <div className="seg" style={{ background:"oklch(0.3 0.02 255)", borderColor:"oklch(0.36 0.02 255)" }}>
          <button className={!external?"is-active":""} onClick={()=>setExternal(false)} style={{ color: !external?"var(--text)":"oklch(0.78 0.02 255)" }}>Natif Doxallia</button>
          <button className={external?"is-active":""} onClick={()=>setExternal(true)} style={{ color: external?"var(--text)":"oklch(0.78 0.02 255)" }}>Connecteurs externes</button>
        </div>
        <button className="btn" onClick={onClose} style={{ background:"oklch(0.3 0.02 255)", borderColor:"oklch(0.4 0.02 255)", color:"#fff" }}><Ic name="X" /> Fermer</button>
      </div>

      {/* body */}
      <div className="sim-body" style={{ flex:1, display:"grid", gridTemplateColumns:"1fr 340px", gap:18, padding:18, minHeight:0 }}>
        {/* browser */}
        <div style={{ minWidth:0, minHeight:0, display:"flex", flexDirection:"column" }}>
          <FakeBrowser theme={theme}>
            <SceneView scene={scene} theme={theme} idx={idx} total={scenes.length} next={next} restart={restart}
              tenant={tenant} journey={journey} THEMES={THEMES} external={external} />
          </FakeBrowser>
        </div>

        {/* control panel */}
        <div style={{ overflowY:"auto", display:"flex", flexDirection:"column", gap:14 }}>
          {/* mode explainer */}
          <div className="card" style={{ padding:0, overflow:"hidden" }}>
            <div style={{ padding:"13px 15px", background: external ? "var(--amber-soft)" : "var(--green-soft)", borderBottom:"1px solid var(--border)" }}>
              <div style={{ display:"flex", alignItems:"center", gap:8, fontWeight:600, fontSize:13.5, color: external ? "oklch(0.45 0.12 60)" : "oklch(0.4 0.09 156)" }}>
                <Ic name={external?"Branch":"ShieldCheck"} width={17} height={17}/>
                {external ? "Connecteurs externes" : "Natif Doxallia · marque blanche"}
              </div>
              <p style={{ margin:"6px 0 0", fontSize:12, color:"var(--text-2)", lineHeight:1.5 }}>
                {external
                  ? "Les briques interactives basculent vers des prestataires tiers. Chaque bascule impose une redirection : l'adhérent quitte votre espace, change de domaine, puis revient."
                  : "Doxallia publie des composants UI en marque blanche. Le parcours s'enchaîne de bout en bout dans votre espace, sans redirection ni changement de domaine."}
              </p>
            </div>
            <div style={{ display:"flex" }}>
              {[["Ruptures", ruptures, external&&ruptures?"var(--amber)":"var(--green)"],["Domaines", domains, null],["Écrans", scenes.length, null]].map(([l,v,c],i)=>(
                <div key={i} style={{ flex:1, padding:"11px 12px", borderLeft:i?"1px solid var(--border)":"none", textAlign:"center" }}>
                  <div className="mono" style={{ fontSize:18, fontWeight:700, color: c||"var(--text)" }}>{v}</div>
                  <div style={{ fontSize:10.5, color:"var(--text-3)" }}>{l}</div>
                </div>
              ))}
            </div>
          </div>

          {/* timeline */}
          <div className="card">
            <div className="card__head"><div><h3 style={{ fontSize:13.5 }}>Enchaînement</h3><p>fournisseur & comportement</p></div></div>
            <div style={{ padding:"6px 0" }}>
              {logical.map((st, i) => {
                const svc = st.kind==="service" ? D.svc(st.serviceId) : null;
                const interactive = st.serviceId==="pvid" || st.serviceId==="esign";
                let provName, behave, btone;
                if (st.kind==="form") { provName = tenant.name; behave="Formulaire intégré"; btone="green"; }
                else if (!external) { provName = "Doxallia (natif)"; behave="Marque blanche"; btone="green"; }
                else if (interactive) { provName = st.serviceId==="pvid" ? "IDnow" : "Yousign"; behave=`Redirection · ${extPhases(st.serviceId).length} écrans`; btone="amber"; }
                else { provName = st.serviceId==="kyc" ? "Sis ID" : st.serviceId==="sae" ? "Arkhineo" : "AR24"; behave="Transparent (API)"; btone="gray"; }
                const active = scene.step && (scene.step._id===st._id || (scene.step.serviceId&&scene.step.serviceId===st.serviceId) || scene.step.label===st.label);
                return (
                  <div key={i} style={{ display:"flex", gap:11, alignItems:"center", padding:"9px 15px", background: active?"var(--primary-soft)":"transparent" }}>
                    <span className="svc-ic" style={{ width:30, height:30, borderRadius:8, background: svc?toneSoft(svc.tone):"var(--surface-3)", color: svc?toneVar(svc.tone):"var(--text-2)" }}>
                      <Ic name={svc?svc.icon:"Form"} width={15} height={15}/>
                    </span>
                    <div style={{ flex:1, minWidth:0 }}>
                      <div style={{ fontSize:12.5, fontWeight:600 }}>{st.label}</div>
                      <div style={{ fontSize:11, color:"var(--text-3)" }}>{provName}</div>
                    </div>
                    <Badge tone={btone} dot={btone==="amber"}>{behave}</Badge>
                  </div>
                );
              })}
            </div>
          </div>

          <button className="btn" onClick={restart} style={{ justifyContent:"center" }}><Ic name="ArrowUp" style={{transform:"rotate(-90deg)"}} width={15} height={15}/> Rejouer depuis le début</button>
        </div>
      </div>
    </div>
  );
}

/* ---------- navigateur factice (fluide) ---------- */
function FakeBrowser({ theme, children }) {
  return (
    <div style={{ borderRadius:12, overflow:"hidden", display:"flex", flexDirection:"column", height:"100%", background:"#fff", boxShadow:"0 30px 70px rgba(0,0,0,.4)", border:"1px solid rgba(0,0,0,.2)" }}>
      <div style={{ background:"#e7e8eb", padding:"9px 13px", display:"flex", alignItems:"center", gap:11, flex:"none" }}>
        <div style={{ display:"flex", gap:7 }}>
          {["#ff5f57","#febc2e","#28c840"].map(c=><span key={c} style={{ width:11, height:11, borderRadius:"50%", background:c }}/>)}
        </div>
        <div style={{ display:"flex", gap:5, color:"#9aa0a6" }}>
          <Ic name="ChevRight" width={15} height={15} style={{ transform:"rotate(180deg)" }}/>
          <Ic name="ChevRight" width={15} height={15} style={{ opacity:.4 }}/>
        </div>
        <div style={{ flex:1, background:"#fff", borderRadius:20, padding:"6px 13px", display:"flex", alignItems:"center", gap:8, minWidth:0, transition:"all .3s" }}>
          <Ic name="Lock" width={13} height={13} style={{ color: theme.external?theme.accent:"#3a9b6a", flex:"none" }}/>
          <span style={{ flex:1, fontSize:12.5, color:"#333", whiteSpace:"nowrap", overflow:"hidden", textOverflow:"ellipsis", fontFamily:"var(--mono)" }}>{theme.domain}</span>
          {theme.external && <span style={{ fontSize:10.5, fontWeight:700, color:"#fff", background:theme.accent, padding:"2px 7px", borderRadius:5, flex:"none" }}>SITE EXTERNE</span>}
        </div>
      </div>
      <div style={{ flex:1, overflow:"auto", background:"#f4f5f7", minHeight:0 }}>{children}</div>
    </div>
  );
}

/* ---------- bandeau de marque (haut de page) ---------- */
function BrandBar({ theme }) {
  return (
    <div style={{ background:"#fff", borderBottom:"1px solid #e6e7ea", padding:"13px 22px", display:"flex", alignItems:"center", gap:11 }}>
      <div style={{ width:32, height:32, borderRadius:8, background:theme.accent, color:"#fff", display:"grid", placeItems:"center", fontWeight:700, fontSize:13, fontFamily:"var(--mono)" }}>{theme.chip}</div>
      <span style={{ fontWeight:600, fontSize:14.5, color:"#1c2330" }}>{theme.name}</span>
      {theme.external && <span style={{ marginLeft:"auto", fontSize:11.5, color:"#7a8290", display:"flex", alignItems:"center", gap:6 }}><Ic name="Globe" width={14} height={14}/> Prestataire certifié</span>}
    </div>
  );
}

/* ---------- fil d'étapes propre au prestataire externe ---------- */
function ProviderStepper({ phases, phaseIdx, accent, name }) {
  return (
    <div style={{ marginBottom:18 }}>
      <div style={{ display:"flex", alignItems:"center", gap:6, fontSize:11, color:"#9098a4", marginBottom:9 }}>
        <span style={{ fontWeight:700, color:accent, letterSpacing:".02em" }}>{name}</span>
        <span>· étape {phaseIdx+1} sur {phases.length}</span>
      </div>
      <div style={{ display:"flex", gap:5 }}>
        {phases.map((p,i)=>(
          <div key={p.id} style={{ flex:1, display:"flex", flexDirection:"column", gap:5 }}>
            <div style={{ height:4, borderRadius:3, background: i<=phaseIdx ? accent : "#dfe1e6", transition:"background .3s" }} />
            <span style={{ fontSize:9.5, fontWeight: i===phaseIdx?700:500, color: i===phaseIdx?accent : i<phaseIdx?"#7a8290":"#b5bac3", whiteSpace:"nowrap", overflow:"hidden", textOverflow:"ellipsis" }}>{p.label}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------- progress du parcours ---------- */
function SceneProgress({ idx, total, accent, external }) {
  const pct = Math.round((idx / (total - 1)) * 100);
  return (
    <div style={{ height:4, background:"#e6e7ea" }}>
      <div style={{ height:"100%", width:pct+"%", background:accent, transition:"width .4s ease" }} />
    </div>
  );
}

/* ---------- rendu d'une scène ---------- */
function SceneView({ scene, theme, idx, total, next, restart, tenant, journey, THEMES, external }) {
  const accent = theme.accent;
  const cta = (label, onClick, secondary) => (
    <button onClick={onClick||next} style={{ width:"100%", marginTop:18, padding:"13px", borderRadius:9, border: secondary?"1px solid #d4d7dd":"none",
      background: secondary?"#fff":accent, color: secondary?"#334":"#fff", fontSize:14.5, fontWeight:600, cursor:"pointer", fontFamily:"var(--sans)" }}>{label}</button>
  );
  const wrap = (inner, opts={}) => (
    <div style={{ minHeight:"100%", display:"flex", flexDirection:"column" }}>
      <SceneProgress idx={idx} total={total} accent={accent} external={external} />
      {!opts.bare && <BrandBar theme={theme} />}
      <div key={idx} style={{ flex:1, padding: opts.pad||"30px 26px", animation:"scenein .25s ease", display:"flex", flexDirection:"column", justifyContent: opts.center?"center":"flex-start", alignItems: opts.center?"center":"stretch" }}>
        <div style={{ width:"100%", maxWidth:opts.center?420:560, margin:"0 auto" }}>{inner}</div>
      </div>
    </div>
  );

  const D = window.DATA;

  switch (scene.t) {
    case "welcome":
      return wrap(<>
        <div style={{ fontSize:12, fontWeight:700, letterSpacing:".08em", textTransform:"uppercase", color:accent }}>Adhésion 100 % en ligne</div>
        <h1 style={{ fontSize:27, margin:"8px 0 10px", color:"#1c2330", letterSpacing:"-0.02em" }}>Rejoignez {tenant.name}</h1>
        <p style={{ fontSize:14, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Votre adhésion se réalise en quelques minutes : nous vérifions votre identité, recueillons vos informations et signons votre bulletin en toute sécurité.</p>
        <div style={{ display:"flex", flexDirection:"column", gap:10, marginTop:18 }}>
          {["Vérification d'identité","Vos informations d'adhérent","Signature de votre bulletin"].map((s,i)=>(
            <div key={i} style={{ display:"flex", alignItems:"center", gap:12, padding:"11px 13px", background:"#fff", border:"1px solid #e6e7ea", borderRadius:10 }}>
              <span style={{ width:26, height:26, borderRadius:"50%", background:`color-mix(in oklch, ${accent} 14%, white)`, color:accent, display:"grid", placeItems:"center", fontWeight:700, fontSize:13, fontFamily:"var(--mono)" }}>{i+1}</span>
              <span style={{ fontSize:13.5, color:"#2b3340", fontWeight:500 }}>{s}</span>
            </div>
          ))}
        </div>
        {cta("Commencer mon adhésion →")}
        <div style={{ textAlign:"center", marginTop:14, fontSize:11.5, color:"#9098a4", display:"flex", justifyContent:"center", gap:6, alignItems:"center" }}><Ic name="Lock" width={13} height={13}/> Données hébergées en France · HDS</div>
      </>, { center:true });

    case "redirect":
      return wrap(<div style={{ textAlign:"center" }}>
        <div style={{ display:"flex", justifyContent:"center", alignItems:"center", gap:14, marginBottom:24 }}>
          <div style={{ width:42, height:42, borderRadius:9, background:tenant.color, color:"#fff", display:"grid", placeItems:"center", fontWeight:700, fontFamily:"var(--mono)" }}>{tenant.initials}</div>
          <div style={{ display:"flex", gap:4, color:theme.accent }}>{[0,1,2].map(i=><Ic key={i} name="ChevRight" width={16} height={16}/>)}</div>
          <div style={{ width:42, height:42, borderRadius:9, background:theme.accent, color:"#fff", display:"grid", placeItems:"center", fontWeight:700, fontFamily:"var(--mono)" }}>{theme.chip}</div>
        </div>
        <div style={{ display:"flex", justifyContent:"center", marginBottom:18 }}><Spinner color={theme.accent} /></div>
        <h2 style={{ fontSize:19, margin:"0 0 8px", color:"#1c2330" }}>Redirection vers {theme.real}…</h2>
        <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, maxWidth:360, margin:"0 auto" }}>Vous quittez momentanément l'espace {tenant.name} pour {scene.step.serviceId==="pvid"?"vérifier votre identité":"signer votre document"} auprès de notre prestataire certifié <b>{theme.real}</b>.</p>
        <div style={{ marginTop:16, display:"inline-flex", gap:7, alignItems:"center", fontSize:11.5, color:"#9098a4", background:"#fff", border:"1px solid #e6e7ea", padding:"6px 11px", borderRadius:20 }}><Ic name="Info" width={13} height={13}/> Changement de domaine en cours</div>
      </div>, { center:true, bare:true });

    case "return":
      return wrap(<div style={{ textAlign:"center" }}>
        <div style={{ display:"flex", justifyContent:"center", marginBottom:18 }}>
          <div style={{ width:54, height:54, borderRadius:"50%", background:"var(--green-soft)", color:"var(--green)", display:"grid", placeItems:"center" }}><Ic name="Check" width={30} height={30}/></div>
        </div>
        <h2 style={{ fontSize:19, margin:"0 0 8px", color:"#1c2330" }}>{scene.step.serviceId==="pvid"?"Identité vérifiée":"Document signé"}</h2>
        <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, maxWidth:340, margin:"0 auto" }}>Opération réalisée chez <b>{THEMES[scene.from].real}</b>. Retour vers votre espace {tenant.name}…</p>
        <div style={{ display:"flex", justifyContent:"center", marginTop:18 }}><Spinner color={accent} size={26} /></div>
      </div>, { center:true });

    /* ===== NATIF DOXALLIA — brique interactive en marque blanche, un seul écran intégré ===== */
    case "step": {
      const nativeBadge = (
        <div style={{ display:"inline-flex", alignItems:"center", gap:6, fontSize:11, fontWeight:600, color:"oklch(0.4 0.09 156)", background:"var(--green-soft)", border:"1px solid color-mix(in oklch, var(--green) 25%, white)", padding:"4px 10px", borderRadius:20, marginBottom:12 }}>
          <Ic name="ShieldCheck" width={13} height={13}/> Composant Doxallia · intégré, sans redirection
        </div>
      );
      if (scene.step.serviceId === "pvid") return wrap(<>
        {nativeBadge}
        <h2 style={{ fontSize:21, margin:"0 0 6px", color:"#1c2330" }}>Vérifions votre identité</h2>
        <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Munissez-vous de votre pièce d'identité. Capture et reconnaissance faciale se font <b>directement sur cet écran</b>, sans quitter l'espace {tenant.name}.</p>
        <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:13, marginTop:16 }}>
          {[["Recto de la pièce","Doc"],["Selfie + détection du vivant","Face"]].map(([l,ic],i)=>(
            <div key={i} style={{ border:`1.5px dashed ${accent}`, borderRadius:12, padding:"22px 12px", textAlign:"center", background:`color-mix(in oklch, ${accent} 6%, white)` }}>
              <div style={{ color:accent, display:"flex", justifyContent:"center", marginBottom:8 }}><Ic name={ic} width={28} height={28}/></div>
              <div style={{ fontSize:12, color:"#5a6373", fontWeight:500 }}>{l}</div>
              <div style={{ fontSize:11, color:accent, fontWeight:600, marginTop:6 }}>Capturer</div>
            </div>
          ))}
        </div>
        {cta("J'ai capturé mes documents")}
        <div style={{ textAlign:"center", marginTop:13, fontSize:11.5, color:"#9098a4" }}>Brique sécurisée Doxallia · PVID certifié ANSSI en marque blanche</div>
      </>);

      // signature — natif
      return wrap(<>
        {nativeBadge}
        <h2 style={{ fontSize:21, margin:"0 0 6px", color:"#1c2330" }}>Signature de votre bulletin</h2>
        <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Lecture, consentement et code de signature sur <b>un même écran</b> — sans quitter votre espace.</p>
        <div style={{ border:"1px solid #e6e7ea", borderRadius:10, background:"#fff", padding:"16px 18px", marginTop:14 }}>
          <div style={{ display:"flex", alignItems:"center", gap:10, marginBottom:10 }}><Ic name="Doc" width={18} height={18} style={{color:accent}}/><span style={{ fontWeight:600, fontSize:13.5 }}>Bulletin d'adhésion — {tenant.name}.pdf</span></div>
          {[88,72,94,60].map((w,i)=><div key={i} style={{ height:7, width:w+"%", background:"#eceef1", borderRadius:4, marginBottom:7 }}/>)}
        </div>
        <label style={{ display:"flex", gap:10, alignItems:"flex-start", fontSize:12.5, color:"#3a4250", margin:"14px 0 2px", cursor:"pointer" }}><input type="checkbox" defaultChecked style={{ marginTop:2, accentColor:accent, width:16, height:16 }}/> J'ai lu le bulletin et j'accepte de le signer électroniquement.</label>
        <div style={{ marginTop:14 }}>
          <Field label="Code reçu par SMS" req><div style={{ display:"flex", gap:8 }}>{[0,1,2,3].map(i=><input key={i} maxLength={1} defaultValue={["3","9","4","1"][i]} style={{...inputStyle, textAlign:"center", fontFamily:"var(--mono)", fontSize:18, fontWeight:600 }}/>)}</div></Field>
        </div>
        {cta("Signer électroniquement")}
        <div style={{ textAlign:"center", marginTop:13, fontSize:11.5, color:"#9098a4" }}>Signature eIDAS avancée · Doxallia Trust en marque blanche</div>
      </>);
    }

    /* ===== PRESTATAIRE EXTERNE — séquence multi-écrans fidèle au parcours réel ===== */
    case "ext": {
      const stepper = <ProviderStepper phases={scene.phases} phaseIdx={scene.phaseIdx} accent={accent} name={theme.real} />;
      const foot = (t) => <div style={{ textAlign:"center", marginTop:13, fontSize:11.5, color:"#9098a4" }}>{t}</div>;

      switch (scene.phase) {
        /* ---- IDnow : identification à distance (AutoIdent) ---- */
        case "consent":
          return wrap(<>
            {stepper}
            <h2 style={{ fontSize:20, margin:"0 0 6px", color:"#1c2330" }}>Bienvenue sur {theme.real}</h2>
            <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Pour vérifier votre identité pour le compte de <b>{tenant.name}</b>, {theme.real} doit traiter votre pièce d'identité et vos <b>données biométriques</b>.</p>
            <div style={{ display:"flex", flexDirection:"column", gap:10, marginTop:16 }}>
              {[["Traitement de mes données biométriques (reconnaissance faciale)","req"],["Transmission du résultat à "+tenant.name,"req"],["Conservation des preuves pendant la durée légale","opt"]].map(([l,k],i)=>(
                <label key={i} style={{ display:"flex", gap:10, alignItems:"flex-start", fontSize:12.5, color:"#3a4250", cursor:"pointer", padding:"11px 13px", background:"#fff", border:"1px solid #e6e7ea", borderRadius:10 }}>
                  <input type="checkbox" defaultChecked style={{ marginTop:1, accentColor:accent, width:16, height:16, flex:"none" }}/>
                  <span>{l}{k==="req" && <span style={{color:"#c0392b"}}> *</span>}</span>
                </label>
              ))}
            </div>
            {cta("J'accepte et je continue")}
            {foot(`Responsable du traitement : ${theme.real} GmbH · RGPD`)}
          </>);

        case "docpick":
          return wrap(<>
            {stepper}
            <h2 style={{ fontSize:20, margin:"0 0 6px", color:"#1c2330" }}>Quelle pièce utilisez-vous ?</h2>
            <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Pays émetteur : <b>France</b>. Sélectionnez le type de document à présenter.</p>
            <div style={{ display:"flex", flexDirection:"column", gap:9, marginTop:16 }}>
              {[["Carte nationale d'identité","CNI biométrique — recto/verso",true],["Passeport","Page photo",false],["Titre de séjour","Recto/verso",false]].map(([l,s,on],i)=>(
                <div key={i} style={{ display:"flex", gap:11, alignItems:"center", padding:"13px 14px", background:"#fff", border:`1.5px solid ${on?accent:"#e6e7ea"}`, borderRadius:11, cursor:"pointer" }}>
                  <span style={{ width:18, height:18, borderRadius:"50%", border:`2px solid ${on?accent:"#c4c8cf"}`, display:"grid", placeItems:"center", flex:"none" }}>{on && <span style={{ width:8, height:8, borderRadius:"50%", background:accent }}/>}</span>
                  <div style={{ flex:1 }}><div style={{ fontSize:13.5, fontWeight:600, color:"#2b3340" }}>{l}</div><div style={{ fontSize:11.5, color:"#9098a4" }}>{s}</div></div>
                  <Ic name="Doc" width={18} height={18} style={{ color: on?accent:"#c4c8cf" }}/>
                </div>
              ))}
            </div>
            {cta("Continuer")}
            {foot(`Propulsé par ${theme.real}`)}
          </>);

        case "front":
        case "back": {
          const isFront = scene.phase === "front";
          return wrap(<>
            {stepper}
            <h2 style={{ fontSize:20, margin:"0 0 6px", color:"#1c2330" }}>Photographiez le {isFront?"recto":"verso"} de votre pièce</h2>
            <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Placez votre carte dans le cadre, à plat et bien éclairée. {theme.real} contrôle la netteté automatiquement.</p>
            <div style={{ marginTop:18, aspectRatio:"1.586", border:`2px dashed ${accent}`, borderRadius:14, background:`color-mix(in oklch, ${accent} 6%, #0b0e14)`, position:"relative", display:"grid", placeItems:"center", overflow:"hidden" }}>
              {[[12,12,"tl"],[12,12,"tr"],[12,12,"bl"],[12,12,"br"]].map(([,,pos],i)=>{
                const m=14, st={ position:"absolute", width:26, height:26, border:`3px solid ${accent}` };
                const corner = pos==="tl"?{top:m,left:m,borderRight:"none",borderBottom:"none",borderRadius:"8px 0 0 0"}:pos==="tr"?{top:m,right:m,borderLeft:"none",borderBottom:"none",borderRadius:"0 8px 0 0"}:pos==="bl"?{bottom:m,left:m,borderRight:"none",borderTop:"none",borderRadius:"0 0 0 8px"}:{bottom:m,right:m,borderLeft:"none",borderTop:"none",borderRadius:"0 0 8px 0"};
                return <span key={i} style={{...st,...corner}}/>;
              })}
              <div style={{ textAlign:"center", color:"#fff" }}>
                <div style={{ opacity:.85, display:"flex", justifyContent:"center", marginBottom:8 }}><Ic name="Eye" width={30} height={30}/></div>
                <div style={{ fontSize:12, opacity:.8, fontFamily:"var(--mono)" }}>{isFront?"RECTO":"VERSO"} · cadrage auto</div>
              </div>
            </div>
            {cta(isFront?"Capturer le recto":"Capturer le verso")}
            {foot(`Capture sécurisée ${theme.real}`)}
          </>);
        }

        case "liveness":
          return wrap(<>
            {stepper}
            <h2 style={{ fontSize:20, margin:"0 0 6px", color:"#1c2330" }}>Selfie & détection du vivant</h2>
            <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Centrez votre visage puis suivez les mouvements demandés. {theme.real} confirme que vous êtes une personne réelle et présente.</p>
            <div style={{ display:"flex", justifyContent:"center", marginTop:20 }}>
              <div style={{ width:170, height:170, borderRadius:"50%", border:`3px solid ${accent}`, background:`color-mix(in oklch, ${accent} 8%, #0b0e14)`, display:"grid", placeItems:"center", position:"relative" }}>
                <span className="spin" style={{ position:"absolute", inset:-3, borderRadius:"50%", border:"3px solid transparent", borderTopColor:accent }}/>
                <Ic name="Face" width={64} height={64} style={{ color:"#fff", opacity:.9 }}/>
              </div>
            </div>
            <div style={{ display:"flex", flexDirection:"column", gap:7, marginTop:18, maxWidth:300, marginInline:"auto" }}>
              {["Tournez lentement la tête vers la gauche","Rapprochez-vous de la caméra"].map((s,i)=>(
                <div key={i} style={{ display:"flex", alignItems:"center", gap:9, fontSize:12.5, color:"#3a4250" }}><span style={{ width:6, height:6, borderRadius:"50%", background:accent, flex:"none" }}/>{s}</div>
              ))}
            </div>
            {cta("Lancer la vérification")}
            {foot(`Détection du vivant ${theme.real} · PVID ANSSI`)}
          </>);

        /* ---- Yousign : signature électronique ---- */
        case "identity":
          return wrap(<>
            {stepper}
            <h2 style={{ fontSize:20, margin:"0 0 6px", color:"#1c2330" }}>Confirmez vos coordonnées</h2>
            <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>{theme.real} envoie un code de signature par SMS. Vérifiez le numéro associé à votre dossier {tenant.name}.</p>
            <div style={{ marginTop:16, border:"1px solid #e6e7ea", borderRadius:11, background:"#fff", overflow:"hidden" }}>
              {[["Signataire","Camille Durand"],["Mobile","+33 6 12 •• •• 78"],["Document","Bulletin d'adhésion — "+tenant.name+".pdf"]].map(([k,v],i)=>(
                <div key={i} style={{ display:"flex", justifyContent:"space-between", gap:12, padding:"12px 15px", borderTop:i?"1px solid #f0f1f3":"none", fontSize:13 }}>
                  <span style={{ color:"#9098a4" }}>{k}</span><span style={{ fontWeight:600, color:"#2b3340", textAlign:"right" }}>{v}</span>
                </div>
              ))}
            </div>
            {cta("C'est bien moi")}
            {foot(`Signature opérée par ${theme.real} · eIDAS`)}
          </>);

        case "read":
          return wrap(<>
            {stepper}
            <h2 style={{ fontSize:20, margin:"0 0 6px", color:"#1c2330" }}>Lisez le document avant de signer</h2>
            <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Vous devez parcourir l'intégralité du bulletin. La signature se débloque en fin de lecture.</p>
            <div style={{ marginTop:14, border:"1px solid #e6e7ea", borderRadius:10, background:"#fff", padding:"18px 20px", maxHeight:230, overflow:"hidden", position:"relative" }}>
              <div style={{ fontSize:13, fontWeight:700, color:"#1c2330", marginBottom:12 }}>Bulletin d'adhésion — {tenant.name}</div>
              {[100,96,88,99,72,94,90,60,97,84].map((w,i)=><div key={i} style={{ height:7, width:w+"%", background:"#eceef1", borderRadius:4, marginBottom:9 }}/>)}
              <div style={{ position:"absolute", left:0, right:0, bottom:0, height:70, background:"linear-gradient(to top, #fff, transparent)" }}/>
              <div style={{ position:"absolute", right:12, bottom:12, fontSize:10.5, color:"#9098a4", fontFamily:"var(--mono)", background:"#fff", padding:"2px 6px", borderRadius:5, border:"1px solid #eceef1" }}>page 1 / 3</div>
            </div>
            {cta("J'ai lu le document — signer")}
            {foot(`Lecture suivie par ${theme.real}`)}
          </>);

        case "adopt":
          return wrap(<>
            {stepper}
            <h2 style={{ fontSize:20, margin:"0 0 6px", color:"#1c2330" }}>Adoptez votre signature</h2>
            <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Choisissez le style apposé sur le document. Il sera scellé au dossier de preuve.</p>
            <div style={{ display:"flex", flexDirection:"column", gap:10, marginTop:16 }}>
              {[["Camille Durand","'Brush Script MT', cursive",true],["Camille Durand","Georgia, serif",false]].map(([txt,ff,on],i)=>(
                <div key={i} style={{ display:"flex", alignItems:"center", gap:13, padding:"14px 16px", background:"#fff", border:`1.5px solid ${on?accent:"#e6e7ea"}`, borderRadius:11, cursor:"pointer" }}>
                  <span style={{ width:18, height:18, borderRadius:"50%", border:`2px solid ${on?accent:"#c4c8cf"}`, display:"grid", placeItems:"center", flex:"none" }}>{on && <span style={{ width:8, height:8, borderRadius:"50%", background:accent }}/>}</span>
                  <span style={{ fontFamily:ff, fontSize:24, color:"#1c2330", flex:1 }}>{txt}</span>
                </div>
              ))}
            </div>
            {cta("Adopter et continuer")}
            {foot(`Signature électronique ${theme.real}`)}
          </>);

        case "otp":
          return wrap(<>
            {stepper}
            <h2 style={{ fontSize:20, margin:"0 0 6px", color:"#1c2330" }}>Saisissez votre code de signature</h2>
            <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>{theme.real} vient d'envoyer un code à <b>6 chiffres</b> au +33 6 •• •• •• 78. Sa saisie vaut signature électronique.</p>
            <div style={{ display:"flex", gap:8, marginTop:20, justifyContent:"center" }}>
              {["4","7","2","9","1","5"].map((d,i)=><input key={i} maxLength={1} defaultValue={d} style={{ width:46, height:56, textAlign:"center", border:"1.5px solid #d4d7dd", borderRadius:10, fontFamily:"var(--mono)", fontSize:22, fontWeight:700, color:"#1c2330", background:"#fff" }}/>)}
            </div>
            <div style={{ textAlign:"center", marginTop:12, fontSize:12, color:accent, fontWeight:600 }}>Renvoyer le code</div>
            {cta("Valider et signer")}
            {foot(`Signature qualifiée ${theme.real} · eIDAS QES`)}
          </>);

        default: return wrap(<div>—</div>);
      }
    }

    case "extproc": {
      const isPvid = scene.step.serviceId === "pvid";
      const items = isPvid
        ? ["Authenticité du titre d'identité","Concordance photo / selfie","Détection du vivant validée","Données extraites et contrôlées"]
        : ["Code de signature vérifié","Signature apposée au document","Scellement eIDAS du dossier de preuve","Horodatage qualifié"];
      return wrap(<div style={{ textAlign:"center" }}>
        <div style={{ display:"flex", justifyContent:"center", marginBottom:18 }}><Spinner color={accent} /></div>
        <h2 style={{ fontSize:19, margin:"0 0 6px", color:"#1c2330" }}>{isPvid?`${theme.real} vérifie votre identité`:`${theme.real} finalise votre signature`}</h2>
        <p style={{ fontSize:13, color:"#5a6373", marginTop:0 }}>Traitement chez le prestataire — quelques secondes.</p>
        <div style={{ textAlign:"left", maxWidth:330, margin:"16px auto 0", display:"flex", flexDirection:"column", gap:9 }}>
          {items.map((it,i)=>(
            <div key={i} style={{ display:"flex", alignItems:"center", gap:10, fontSize:12.5, color:"#3a4250" }}>
              <span style={{ width:18, height:18, borderRadius:"50%", background:accent, color:"#fff", display:"grid", placeItems:"center", flex:"none" }}><Ic name="Check" width={11} height={11}/></span>{it}
            </div>
          ))}
        </div>
        <div style={{ marginTop:18, fontSize:11.5, color:"#9098a4" }}>Opéré par {theme.real} — vous serez redirigé vers {tenant.name}</div>
      </div>, { center:true, bare:true });
    }

    case "processing": {
      const isKyc = scene.step.serviceId === "kyc";
      const items = isKyc ? ["Listes de sanctions & gel des avoirs","Personnes politiquement exposées (PPE)","Scoring de risque LCB-FT"] : ["Calcul de l'empreinte d'intégrité","Horodatage qualifié","Versement à l'archive probatoire"];
      const op = scene.external ? (isKyc ? "Sis ID" : "Arkhineo") : "Doxallia";
      return wrap(<div style={{ textAlign:"center" }}>
        <div style={{ display:"flex", justifyContent:"center", marginBottom:18 }}><Spinner color={accent} /></div>
        <h2 style={{ fontSize:19, margin:"0 0 6px", color:"#1c2330" }}>{isKyc?"Contrôles réglementaires en cours":"Archivage de votre dossier"}</h2>
        <p style={{ fontSize:13, color:"#5a6373", marginTop:0 }}>Traitement automatique, sans action de votre part.</p>
        <div style={{ textAlign:"left", maxWidth:330, margin:"16px auto 0", display:"flex", flexDirection:"column", gap:9 }}>
          {items.map((it,i)=>(
            <div key={i} style={{ display:"flex", alignItems:"center", gap:10, fontSize:12.5, color:"#3a4250" }}>
              <span style={{ width:18, height:18, borderRadius:"50%", background:"var(--green)", color:"#fff", display:"grid", placeItems:"center", flex:"none" }}><Ic name="Check" width={11} height={11}/></span>{it}
            </div>
          ))}
        </div>
        <div style={{ marginTop:18, fontSize:11.5, color:"#9098a4" }}>Opéré par {op} · connecteur {scene.external?"externe (API serveur à serveur)":"natif"} — aucune rupture côté adhérent</div>
      </div>, { center:true });
    }

    case "form": {
      const fields = (scene.step.fields && scene.step.fields.length) ? scene.step.fields : (window.DATA.JOURNEYS[0].steps.find(s=>s.kind==="form")||{}).fields || [];
      return wrap(<>
        <h2 style={{ fontSize:21, margin:"0 0 6px", color:"#1c2330" }}>Vos informations d'adhérent</h2>
        <p style={{ fontSize:13.5, color:"#5a6373", marginTop:0 }}>Formulaire conçu par {tenant.name} dans le constructeur de parcours.</p>
        <div style={{ marginTop:16 }}>
          {fields.map(f => {
            if (f.type==="checkbox") return <label key={f.id} style={{ display:"flex", gap:10, alignItems:"flex-start", fontSize:12.5, color:"#3a4250", margin:"4px 0 13px", cursor:"pointer" }}><input type="checkbox" defaultChecked style={{ marginTop:2, accentColor:accent, width:16, height:16 }}/> {f.label}</label>;
            return <Field key={f.id} label={f.label} req={f.required}>
              {f.type==="select"
                ? <select style={inputStyle} defaultValue={(f.options||[])[0]}>{(f.options||["—"]).map(o=><option key={o}>{o}</option>)}</select>
                : f.type==="iban"
                ? <input style={{...inputStyle, fontFamily:"var(--mono)"}} defaultValue="FR76 3000 4000 0312 3456 7890 143" />
                : f.type==="date"
                ? <input style={inputStyle} defaultValue="1987-04-12" type="date" />
                : f.type==="file"
                ? <div style={{...inputStyle, color:"#9098a4", display:"flex", gap:8, alignItems:"center", borderStyle:"dashed", cursor:"pointer"}}><Ic name="Download" width={15} height={15}/> Déposer un fichier</div>
                : <input style={inputStyle} defaultValue={{f2:"Durand",f3:"Camille",f5:"camille.durand@email.fr",f6:"06 12 34 56 78",f1:"Mme"}[f.id]||""} placeholder={f.ph||""} />}
            </Field>;
          })}
        </div>
        {cta("Valider et continuer")}
      </>);
    }

    case "notify":
      return wrap(<>
        <h2 style={{ fontSize:21, margin:"0 0 6px", color:"#1c2330" }}>Confirmation d'adhésion</h2>
        <p style={{ fontSize:13.5, color:"#5a6373", lineHeight:1.6, marginTop:0 }}>Votre adhésion est confirmée par <b>lettre recommandée électronique</b> à valeur juridique{scene.external?` (acheminée par AR24)`:""}.</p>
        <div style={{ border:"1px solid #e6e7ea", borderRadius:10, background:"#fff", padding:"15px 17px", marginTop:14, display:"flex", gap:12, alignItems:"center" }}>
          <span style={{ width:38, height:38, borderRadius:9, background:`color-mix(in oklch, ${accent} 12%, white)`, color:accent, display:"grid", placeItems:"center", flex:"none" }}><Ic name="Mail" width={19} height={19}/></span>
          <div><div style={{ fontWeight:600, fontSize:13.5 }}>LRE — Accusé de réception</div><div style={{ fontSize:12, color:"#7a8290" }}>Preuve de dépôt et de réception conservées</div></div>
          <span style={{ marginLeft:"auto", fontSize:11, fontWeight:600, color:"var(--green)" }}>Envoyée</span>
        </div>
        {cta("Terminer")}
      </>);

    case "done":
      return wrap(<div style={{ textAlign:"center" }}>
        <div style={{ display:"flex", justifyContent:"center", marginBottom:18 }}>
          <div style={{ width:64, height:64, borderRadius:"50%", background:accent, color:"#fff", display:"grid", placeItems:"center" }}><Ic name="Check" width={36} height={36}/></div>
        </div>
        <h1 style={{ fontSize:25, margin:"0 0 8px", color:"#1c2330", letterSpacing:"-0.02em" }}>Bienvenue chez {tenant.name} !</h1>
        <p style={{ fontSize:14, color:"#5a6373", lineHeight:1.6, maxWidth:380, margin:"0 auto" }}>Votre adhésion est finalisée. Vous recevrez vos identifiants d'accès à votre espace adhérent par e-mail.</p>
        <div style={{ display:"inline-flex", flexDirection:"column", gap:4, marginTop:18, padding:"13px 24px", background:"#fff", border:"1px solid #e6e7ea", borderRadius:12 }}>
          <span style={{ fontSize:11, color:"#9098a4", textTransform:"uppercase", letterSpacing:".05em", fontWeight:600 }}>Numéro d'adhérent</span>
          <span className="mono" style={{ fontSize:20, fontWeight:700, color:accent }}>MH-2026-04817</span>
        </div>
        <div>{cta("Rejouer la simulation", restart, true)}</div>
      </div>, { center:true });

    default: return wrap(<div>—</div>);
  }
}

Object.assign(window, { JourneySimulator });
