/* ============================================================
   ensō rse — Quizz onboarding · Parcours RECRUE
   ============================================================ */

function RoleCard({ rkey, role, selected, onClick }) {
  return (
    <Card onClick={onClick} hover pad={18}
    style={{ borderColor: selected ? "var(--accent-500)" : "var(--border-default)",
      background: selected ? "var(--accent-100)" : "var(--bg-surface)",
      boxShadow: selected ? "var(--shadow-md)" : "var(--shadow-xs)" }}>
      <div style={{ display: "flex", gap: 14, alignItems: "flex-start" }}>
        <div style={{ width: 44, height: 44, borderRadius: 12, flex: "none", display: "grid", placeItems: "center",
          background: selected ? "var(--accent-500)" : "var(--color-neutral-50)", color: selected ? "#fff" : "var(--accent-700)" }}>
          <Icon name={role.icon} size={22} />
        </div>
        <div>
          <div style={{ fontWeight: 700, fontSize: "var(--fs-md)" }}>{role.label}</div>
          <div className="muted" style={{ fontSize: "var(--fs-sm)", marginTop: 3, lineHeight: 1.4 }}>{role.desc}</div>
        </div>
      </div>
    </Card>);

}

function ProfileStep({ initial, onStart }) {
  const ROLES = window.QD.ROLES,STATUTS = window.QD.STATUTS;
  const [name, setName] = useState(initial?.name || "");
  const [role, setRole] = useState(initial?.role || "");
  const [statut, setStatut] = useState(initial?.statut || "");
  const ready = name.trim() && role && statut;
  const attemptNo = (initial?.attempts?.length || 0) + 1;
  const phase = attemptNo >= 2 ? "j15" : "j0";
  const isJ15 = phase === "j15";
  const preview = useMemo(() => {
    if (!role || !statut) return null;
    return window.QD.buildQuiz(role, statut, { attempt: attemptNo, phase });
  }, [role, statut]);

  return (
    <div className="fade-up" style={{ maxWidth: 760, margin: "0 auto", padding: "8px 0 40px" }}>
      <Eyebrow>{isJ15 ? "On remet ça · J+15" : "Bienvenue chez ensō rse · J0"}</Eyebrow>
      <h1 style={{ fontSize: "var(--fs-3xl)", marginTop: 10, marginBottom: 8 }}>
        {isJ15 ? "Quizz J+15 — voyons ce qui a infusé" : "On fait connaissance ?"}
      </h1>
      <p className="muted" style={{ fontSize: "var(--fs-md)", maxWidth: 600, marginBottom: 28 }}>
        {isJ15 ?
        <>Même terrain, niveau d'exigence en hausse. On <strong style={{ color: "var(--fg-default)" }}>rejoue les questions ratées à J0</strong> et on ajoute des questions plus pointues pour mesurer ta progression.</> :
        <>Pas de piège, pas de note. Ce quizz sert juste à <strong style={{ color: "var(--fg-default)" }}>caler ton onboarding sur ce que tu sais déjà</strong>. Réponds franchement, tu es là pour apprendre.</>}
      </p>

      <Card pad={26} style={{ marginBottom: 20 }}>
        <label style={{ fontWeight: 600, fontSize: "var(--fs-sm)", display: "block", marginBottom: 8 }}>Ton prénom & nom</label>
        <input value={name} onChange={(e) => setName(e.target.value)} placeholder="ex. Marion Lefèvre" disabled={!!initial?.name}
        style={{ width: "100%", padding: "13px 16px", borderRadius: "var(--r-md)", border: "1px solid var(--border-strong)",
          fontFamily: "var(--font-body)", fontSize: "var(--fs-base)", background: initial?.name ? "var(--color-neutral-50)" : "#fff", color: "var(--fg-default)" }} />
      </Card>

      <div style={{ fontWeight: 600, fontSize: "var(--fs-sm)", marginBottom: 12 }}>Quel est ton poste&nbsp;?</div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 24 }}>
        {Object.entries(ROLES).map(([k, r]) =>
        <RoleCard key={k} rkey={k} role={r} selected={role === k} onClick={() => !initial?.role && setRole(k)} />
        )}
      </div>

      <div style={{ fontWeight: 600, fontSize: "var(--fs-sm)", marginBottom: 12 }}>Ton type de contrat&nbsp;?</div>
      <div style={{ display: "flex", gap: 10, flexWrap: "wrap", marginBottom: 26 }}>
        {Object.entries(STATUTS).map(([k, s]) => {
          const on = statut === k;
          return (
            <button key={k} onClick={() => !initial?.statut && setStatut(k)}
            style={{ padding: "11px 20px", borderRadius: "var(--r-pill)", fontFamily: "var(--font-body)", fontWeight: 600, fontSize: "var(--fs-base)",
              border: on ? "1px solid var(--accent-500)" : "1px solid var(--border-strong)", background: on ? "var(--accent-100)" : "#fff",
              color: on ? "var(--accent-700)" : "var(--fg-muted)", transition: "all .14s var(--ease-out)" }}>
              {s.label}
              <span style={{ fontWeight: 400, fontSize: "var(--fs-xs)", marginLeft: 8, opacity: .75 }}>{s.note}</span>
            </button>);

        })}
      </div>

      {preview &&
      <div className="fade-up" style={{ background: "var(--color-env-100)", border: "1px solid var(--color-env-200)", borderRadius: "var(--r-lg)", padding: "16px 20px", marginBottom: 26, display: "flex", gap: 12, alignItems: "center" }}>
          <Icon name="sparkles" size={20} color="var(--color-env-600)" />
          <div style={{ fontSize: "var(--fs-sm)" }}>
            Ton quizz a été <strong>adapté à ton profil</strong> : <strong>{preview.filter((q) => q.type !== "selfrate").length} questions</strong> + quelques auto-évaluations, pondérées sur ce qui compte le plus pour ton poste.
          </div>
        </div>
      }

      <Btn size="lg" disabled={!ready} iconRight="arrow-right"
      onClick={() => onStart({ name: name.trim(), role, statut, preview })}>
        {isJ15 ? "Démarrer le quizz J+15" : "Démarrer le quizz J0"}
      </Btn>
    </div>);

}

/* ---------- une question ---------- */
function QuestionView({ q, idx, total, answer, onAnswer }) {
  const dom = window.QD.DOMAINS.find((d) => d.id === q.domain);
  const tone = dom.pillar;
  const setChoice = (choice, correct) => onAnswer({ ...answer, choice, correct, certainty: answer?.certainty || "mid" });

  return (
    <div className="fade-up" key={q.id} style={{ maxWidth: 720, margin: "0 auto" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 18 }}>
        <Pill tone={tone}>{dom.short}</Pill>
        {q.type === "selfrate" && <Pill tone="neutral">Auto-évaluation</Pill>}
        {q.type === "vf" && <Pill tone="neutral">Vrai / Faux</Pill>}
        {q.type === "free" && <Pill tone="neutral">Réponse libre</Pill>}
      </div>

      <h2 style={{ fontSize: "var(--fs-2xl)", lineHeight: 1.2, marginBottom: 26, textWrap: "pretty" }}>{q.text}</h2>

      {q.type === "qcm" &&
      <div style={{ display: "grid", gap: 10 }}>
          {q.options.map((o, i) => {
          const on = answer?.choice === i;
          return (
            <button key={i} onClick={() => setChoice(i, !!o.ok)}
            style={{ textAlign: "left", display: "flex", gap: 13, alignItems: "center", padding: "15px 18px",
              borderRadius: "var(--r-md)", border: on ? "1.5px solid var(--accent-500)" : "1px solid var(--border-strong)",
              background: on ? "var(--accent-100)" : "#fff", fontFamily: "var(--font-body)", fontSize: "var(--fs-base)",
              color: "var(--fg-default)", transition: "all .14s var(--ease-out)", cursor: "pointer" }}>
                <span style={{ width: 26, height: 26, flex: "none", borderRadius: "50%", display: "grid", placeItems: "center",
                border: on ? "1.5px solid var(--accent-500)" : "1.5px solid var(--border-strong)", background: on ? "var(--accent-500)" : "transparent", color: "#fff" }}>
                  {on && <Icon name="check" size={15} stroke={2.6} />}
                </span>
                <span style={{ fontWeight: on ? 600 : 400 }}>{o.t}</span>
              </button>);

        })}
        </div>
      }

      {q.type === "vf" &&
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          {[{ v: true, l: "Vrai" }, { v: false, l: "Faux" }].map((o) => {
          const on = answer?.choice === o.v;
          return (
            <button key={o.l} onClick={() => setChoice(o.v, o.v === q.answer)}
            style={{ padding: "22px", borderRadius: "var(--r-lg)", border: on ? "1.5px solid var(--accent-500)" : "1px solid var(--border-strong)",
              background: on ? "var(--accent-100)" : "#fff", fontFamily: "var(--font-display)", fontWeight: 700, fontSize: "var(--fs-xl)",
              color: on ? "var(--accent-700)" : "var(--fg-default)", transition: "all .14s var(--ease-out)" }}>
                {o.l}
              </button>);

        })}
        </div>
      }

      {q.type === "selfrate" &&
      <div style={{ display: "grid", gap: 10 }}>
          {[{ k: "maitrise", l: "Oui, je saurais l'expliquer", ic: "check-circle" },
        { k: "idee", l: "J'en ai une idée, mais flou", ic: "eye" },
        { k: "nouveau", l: "Non, c'est nouveau pour moi", ic: "sparkles" }].map((o) => {
          const on = answer?.rate === o.k;
          return (
            <button key={o.k} onClick={() => onAnswer({ rate: o.k })}
            style={{ textAlign: "left", display: "flex", gap: 13, alignItems: "center", padding: "15px 18px",
              borderRadius: "var(--r-md)", border: on ? "1.5px solid var(--accent-500)" : "1px solid var(--border-strong)",
              background: on ? "var(--accent-100)" : "#fff", fontFamily: "var(--font-body)", fontSize: "var(--fs-base)",
              color: "var(--fg-default)", transition: "all .14s var(--ease-out)" }}>
                <Icon name={o.ic} size={20} color={on ? "var(--accent-600)" : "var(--fg-subtle)"} />
                <span style={{ fontWeight: on ? 600 : 400 }}>{o.l}</span>
              </button>);

        })}
        </div>
      }

      {q.type === "free" &&
      <div style={{ display: "grid", gap: 14 }}>
          <textarea value={answer?.text || ""} onChange={(e) => onAnswer({ text: e.target.value })}
          placeholder="Écris ta réponse avec tes mots — il n'y a pas de mauvaise façon de répondre." rows={4}
          style={{ width: "100%", padding: "15px 18px", borderRadius: "var(--r-md)", border: "1px solid var(--border-strong)",
            fontFamily: "var(--font-body)", fontSize: "var(--fs-base)", lineHeight: 1.5, color: "var(--fg-default)", resize: "vertical" }} />
          {q.model && answer?.text && answer.text.trim() &&
          <div className="fade-up" style={{ background: "var(--color-env-100)", border: "1px solid var(--color-env-200)", borderRadius: "var(--r-lg)", padding: "16px 18px" }}>
              <div style={{ display: "flex", gap: 9, alignItems: "center", marginBottom: 7 }}>
                <Icon name="compass" size={18} color="var(--color-env-700)" />
                <strong style={{ fontSize: "var(--fs-sm)", color: "var(--color-env-700)" }}>Un repère de réponse</strong>
              </div>
              <p style={{ fontSize: "var(--fs-sm)", lineHeight: 1.55 }}>{q.model}</p>
            </div>
          }
        </div>
      }

      {(q.type === "qcm" || q.type === "vf") && answer?.choice !== undefined &&
      <div className="fade-up" style={{ marginTop: 26, paddingTop: 22, borderTop: "1px dashed var(--border-strong)" }}>
          <div className="muted" style={{ fontSize: "var(--fs-sm)", fontWeight: 600, marginBottom: 10 }}>À quel point es-tu sûr·e de ta réponse&nbsp;?</div>
          <CertaintySelector value={answer.certainty} onChange={(c) => onAnswer({ ...answer, certainty: c })} />
        </div>
      }
    </div>);

}

function QuizStep({ profile, attemptNo, phase, quiz, onDone, onQuit }) {
  const [i, setI] = useState(0);
  const [answers, setAnswers] = useState({});
  const total = quiz.length;
  const q = quiz[i];
  const cur = answers[q.id];
  const answered = q.type === "selfrate" ? !!cur?.rate
    : q.type === "free" ? !!(cur?.text && cur.text.trim())
    : cur?.choice !== undefined;
  const pct = Math.round(i / total * 100);

  // séquence des thèmes (questions groupées par domaine)
  const domSeq = useMemo(() => { const s = []; quiz.forEach((x) => { if (!s.includes(x.domain)) s.push(x.domain); }); return s; }, [quiz]);
  const domObj = window.QD.DOMAINS.find((d) => d.id === q.domain);
  const curDomIdx = domSeq.indexOf(q.domain);

  const setAns = (a) => setAnswers((s) => ({ ...s, [q.id]: a }));
  const next = () => {if (i < total - 1) setI(i + 1);else onDone(answers);};

  return (
    <div style={{ minHeight: "100%", display: "flex", flexDirection: "column" }}>
      {/* progress header */}
      <div style={{ position: "sticky", top: 0, zIndex: 5, background: "rgba(250,251,250,.85)", backdropFilter: "blur(10px)", borderBottom: "1px solid var(--border-default)", padding: "14px 0" }}>
        <div style={{ maxWidth: 720, margin: "0 auto", padding: "0 24px", display: "flex", alignItems: "center", gap: 16 }}>
          <button onClick={onQuit} title="Quitter" style={{ background: "none", border: "none", color: "var(--fg-muted)", display: "grid", placeItems: "center", padding: 4 }}>
            <Icon name="x" size={20} />
          </button>
          <span style={{ fontWeight: 700, fontSize: "var(--fs-xs)", letterSpacing: ".04em", color: "var(--accent-700)", background: "var(--accent-100)", border: "1px solid var(--accent-200)", padding: "3px 10px", borderRadius: "var(--r-pill)", whiteSpace: "nowrap" }}>
            {window.QD.PHASES[phase || "j0"].label}
          </span>
          <div style={{ flex: 1, height: 8, borderRadius: 999, background: "var(--color-neutral-100)", overflow: "hidden" }}>
            <div style={{ height: "100%", width: pct + "%", background: "var(--accent-500)", borderRadius: 999, transition: "width .3s var(--ease-out)" }} />
          </div>
          <span style={{ fontWeight: 700, fontSize: "var(--fs-sm)", color: "var(--fg-muted)", minWidth: 54, textAlign: "right" }}>{i + 1} / {total}</span>
        </div>
      </div>

      <div style={{ flex: 1, padding: "30px 24px 24px" }}>
        {/* en-tête de thème (questions groupées par sujet) */}
        <div style={{ maxWidth: 720, margin: "0 auto 22px", display: "flex", alignItems: "center", gap: 12 }}>
          <span className="eyebrow" style={{ color: window.PILLAR_700[domObj.pillar], whiteSpace: "nowrap" }}>Thème {curDomIdx + 1}/{domSeq.length}</span>
          <span style={{ height: 1, flex: 1, background: "var(--border-default)" }} />
          <span style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: "var(--fs-sm)", color: window.PILLAR_700[domObj.pillar], whiteSpace: "nowrap" }}>{domObj.label}</span>
        </div>
        <QuestionView q={q} idx={i} total={total} answer={cur} onAnswer={setAns} />
      </div>

      {/* footer nav */}
      <div style={{ position: "sticky", bottom: 0, background: "rgba(250,251,250,.85)", backdropFilter: "blur(10px)", borderTop: "1px solid var(--border-default)", padding: "14px 0" }}>
        <div style={{ maxWidth: 720, margin: "0 auto", padding: "0 24px", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <Btn variant="ghost" icon="arrow-left" disabled={i === 0} onClick={() => setI(Math.max(0, i - 1))}>Précédent</Btn>
          <Btn variant="primary" iconRight={i === total - 1 ? "check" : "arrow-right"} disabled={!answered} onClick={next}>
            {i === total - 1 ? "Voir mon résultat" : "Suivant"}
          </Btn>
        </div>
      </div>
    </div>);

}

/* ---------- recap réponses (pour apprendre) ---------- */
function AnswerRecap({ quiz, answers }) {
  return (
    <div style={{ display: "grid", gap: 12 }}>
      {quiz.filter((q) => q.type === "qcm" || q.type === "vf").map((q, n) => {
        const a = answers[q.id];const ok = a?.correct;
        const dom = window.QD.DOMAINS.find((d) => d.id === q.domain);
        const okIdx = q.type === "qcm" ? q.options.findIndex((o) => o.ok) : null;
        const chosen = q.type === "qcm" ? (a?.choice != null ? q.options[a.choice].t : "—") : (a?.choice === true ? "Vrai" : a?.choice === false ? "Faux" : "—");
        const right = q.type === "qcm" ? q.options[okIdx].t : (q.answer ? "Vrai" : "Faux");
        return (
          <Card key={q.id} pad={18} style={{ borderColor: ok ? "var(--color-env-200)" : "#f6c8c4" }}>
            <div style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
              <Icon name={ok ? "check-circle" : "x-circle"} size={22} color={ok ? "var(--color-env-600)" : "var(--danger-500)"} />
              <div style={{ flex: 1 }}>
                <div style={{ display: "flex", gap: 8, marginBottom: 6, alignItems: "center", flexWrap: "wrap" }}>
                  <Pill tone={dom.pillar} style={{ padding: "3px 9px" }}>{dom.short}</Pill>
                  {a?.certainty === "sure" && !ok && <Pill tone="danger" style={{ padding: "3px 9px" }}>Idée fausse à corriger</Pill>}
                  {a?.certainty !== "sure" && ok && <Pill tone="neutral" style={{ padding: "3px 9px" }}>Juste, mais à confirmer</Pill>}
                </div>
                <div style={{ fontWeight: 600, marginBottom: 8 }}>{q.text}</div>
                <div style={{ fontSize: "var(--fs-sm)", display: "grid", gap: 3, marginBottom: 8 }}>
                  <div>Ta réponse&nbsp;: <strong style={{ color: ok ? "var(--color-env-700)" : "var(--danger-fg)" }}>{chosen}</strong>{ok ? "" : " ✗"}</div>
                  {!ok && <div className="muted">Bonne réponse&nbsp;: <strong style={{ color: "var(--color-env-700)" }}>{right}</strong></div>}
                </div>
                <div className="muted" style={{ fontSize: "var(--fs-sm)", lineHeight: 1.5, paddingTop: 8, borderTop: "1px dashed var(--border-strong)" }}>{q.explain}</div>
              </div>
            </div>
          </Card>);

      })}
    </div>);

}

/* ---------- bloc « Et maintenant ? » (distinct J0 / J+15) ---------- */
function EtMaintenant({ isJ15, name }) {
  if (!isJ15) {
    return (
      <Card pad={22} style={{ background: "var(--bg-inverse)", border: "none", color: "#fff" }}>
        <div style={{ display: "flex", gap: 14, alignItems: "flex-start" }}>
          <Icon name="compass" size={22} color="var(--color-env-300)" />
          <div>
            <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: "var(--fs-lg)", marginBottom: 6 }}>Et maintenant&nbsp;?</div>
            <p style={{ color: "rgba(255,255,255,.82)", fontSize: "var(--fs-sm)", lineHeight: 1.55 }}>
              Ton manager reçoit ces résultats pour <strong style={{ color: "#fff" }}>adapter ton onboarding</strong> — il insistera là où c'est utile et ira vite là où tu es déjà à l'aise. Dans 15 jours, tu repasseras un quizz (J+15) — plus exigeant — pour voir ce qui a infusé.
            </p>
          </div>
        </div>
      </Card>);

  }
  const steps = [
  { ic: "check-circle", t: "Tes acquis sont validés", d: "Les notions revues à J+15 sont consolidées. Ton bilan de progression J0 → J+15 est disponible côté manager." },
  { ic: "message-circle", t: "Place à la mise en situation", d: "Pitchs, démos, premiers dossiers : tu passes de la théorie au terrain, accompagné·e de ton manager." },
  { ic: "target", t: "Cap sur l'autonomie", d: "Continue à driller les thèmes encore fragiles — c'est le dernier trait du cercle ensō rse." }];

  return (
    <Card pad={26} style={{ background: "var(--color-env-100)", border: "1px solid var(--color-env-200)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 18 }}>
        <div style={{ width: 42, height: 42, borderRadius: 12, background: "var(--color-env-500)", display: "grid", placeItems: "center", flex: "none" }}>
          <Icon name="flag" size={21} color="#fff" />
        </div>
        <div>
          <div style={{ fontFamily: "var(--font-display)", fontWeight: 800, fontSize: "var(--fs-xl)", color: "var(--color-env-700)" }}>Et après le J+15&nbsp;?</div>
          <div className="muted" style={{ fontSize: "var(--fs-sm)" }}>La suite de ton parcours chez ensō rse</div>
        </div>
      </div>
      <div style={{ display: "grid", gap: 12 }}>
        {steps.map((s, i) =>
        <div key={i} style={{ display: "flex", gap: 13, alignItems: "flex-start", background: "var(--bg-surface)", borderRadius: "var(--r-md)", padding: "14px 16px", border: "1px solid var(--color-env-200)" }}>
            <Icon name={s.ic} size={20} color="var(--color-env-600)" style={{ marginTop: 2, flex: "none" }} />
            <div>
              <div style={{ fontWeight: 700, fontSize: "var(--fs-base)", marginBottom: 2 }}>{s.t}</div>
              <div className="muted" style={{ fontSize: "var(--fs-sm)", lineHeight: 1.5 }}>{s.d}</div>
            </div>
          </div>
        )}
      </div>
    </Card>);

}

/* ---------- programme de formation à venir (réf. deck Onboarding) ---------- */
const TRAINING_BLOCKS = [
  { n: "01", d: "J1", title: "Profession comptable & synergie RSE", who: "Stéphane", tone: "env" },
  { n: "02", d: "J2", title: "Marché RSE réglementaire", who: "Stéphane", tone: "env" },
  { n: "03", d: "J3", title: "Clients, offre, pricing & pitch", who: "Océane + ton manager", tone: "soc" },
  { n: "04", d: "J4", title: "Outils marketing & démo plateforme", who: "Océane + ton manager", tone: "soc" },
  { n: "05", d: "J5", title: "Environnement logiciel & IA", who: "Ton manager + Stéphane", tone: "gov" }];

function TrainingProgram() {
  return (
    <div>
      <div style={{ background: "var(--color-env-500)", borderRadius: "var(--r-lg) var(--r-lg) 0 0", padding: "22px 26px", color: "#fff" }}>
        <div style={{ fontFamily: "var(--font-display)", fontWeight: 800, fontSize: "var(--fs-xl)" }}>Ton programme de formation</div>
        <div style={{ fontSize: "var(--fs-sm)", color: "rgba(255,255,255,.88)", marginTop: 4 }}>5 blocs · 3 animateurs · Semaine du 1ᵉʳ juin 2026</div>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(178px,1fr))", gap: 14, padding: 18, background: "var(--color-neutral-25)", borderRadius: "0 0 var(--r-lg) var(--r-lg)", border: "1px solid var(--border-default)", borderTop: "none" }}>
        {TRAINING_BLOCKS.map((b) => {
          const col = window.PILLAR_COLOR[b.tone],col7 = window.PILLAR_700[b.tone];
          return (
            <div key={b.n} style={{ background: "var(--bg-surface)", borderRadius: "var(--r-md)", border: "1px solid var(--border-default)", overflow: "hidden", boxShadow: "var(--shadow-xs)" }}>
              <div style={{ background: col, color: "#fff", padding: "11px 14px", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <span style={{ fontFamily: "var(--font-display)", fontWeight: 800, fontSize: "var(--fs-lg)" }}>{b.n}</span>
                <span style={{ fontWeight: 700, fontSize: "var(--fs-sm)" }}>{b.d}</span>
              </div>
              <div style={{ padding: 14 }}>
                <div style={{ fontWeight: 700, fontSize: "var(--fs-base)", lineHeight: 1.25, minHeight: 46, textWrap: "pretty" }}>{b.title}</div>
                <div className="muted" style={{ fontSize: "var(--fs-xs)", margin: "14px 0 6px" }}>Animé par</div>
                <div style={{ textAlign: "center", fontWeight: 700, fontSize: "var(--fs-sm)", color: col7, background: `color-mix(in srgb, ${col} 11%, white)`, borderRadius: "var(--r-sm)", padding: "8px 6px" }}>{b.who}</div>
              </div>
            </div>);

        })}
      </div>
    </div>);

}

/* ---------- espace personnel recrue ---------- */
function RecrueSpace({ recruit, onStartJ15, onHome }) {
  const QD = window.QD;
  const r = recruit;
  const [showRecap, setShowRecap] = useState(false);
  const last = r.attempts[r.attempts.length - 1];
  const prev = r.attempts.length > 1 ? r.attempts[r.attempts.length - 2] : null;
  const first = r.name.split(" ")[0];
  const hasJ15 = r.attempts.some((a) => QD.phaseOf(a) === "j15");
  const lastIsJ15 = last && QD.phaseOf(last) === "j15";
  const lvl = last ? QD.levelFor(last.global) : null;
  const quiz = last ? last.quizIds.map((id) => window.Store.qById[id]).filter(Boolean) : [];
  const delta = prev ? last.global - prev.global : null;

  const series = last ? [{ values: last.scores, color: "var(--color-env-500)", fill: "rgba(0,175,143,.16)" }] : [];
  if (prev) series.unshift({ values: prev.scores, color: "var(--color-neutral-300)", fill: "rgba(0,0,0,.04)", dots: false });

  return (
    <div className="fade-up" style={{ maxWidth: 960, margin: "0 auto", padding: "8px 0 60px" }}>
      <button onClick={onHome} style={{ display: "inline-flex", gap: 7, alignItems: "center", background: "none", border: "none", color: "var(--fg-muted)", fontWeight: 600, fontSize: "var(--fs-sm)", marginBottom: 16, padding: 0 }}>
        <Icon name="arrow-left" size={17} /> Accueil
      </button>

      {/* en-tête */}
      <div style={{ display: "flex", gap: 18, alignItems: "center", flexWrap: "wrap", marginBottom: 28 }}>
        <div style={{ width: 58, height: 58, borderRadius: "50%", background: "var(--color-env-100)", display: "grid", placeItems: "center", color: "var(--accent-700)", flex: "none" }}>
          <Icon name={window.QD.ROLES[r.role].icon} size={27} />
        </div>
        <div style={{ flex: 1, minWidth: 200 }}>
          <Eyebrow>Mon espace</Eyebrow>
          <h1 style={{ fontSize: "var(--fs-2xl)", marginTop: 6 }}>Bonjour {first}</h1>
          <div className="muted" style={{ marginTop: 3 }}>{QD.ROLES[r.role].label} · {QD.STATUTS[r.statut].label}</div>
        </div>
        {last &&
        <div style={{ textAlign: "right" }}>
            <div style={{ fontFamily: "var(--font-display)", fontWeight: 800, fontSize: "var(--fs-3xl)", color: lvl.color, lineHeight: 1 }}>{last.global}%</div>
            <div style={{ fontWeight: 700, color: lvl.color }}>{lvl.label}</div>
            <div className="subtle" style={{ fontSize: "var(--fs-xs)", marginTop: 2 }}>au quizz {QD.PHASES[QD.phaseOf(last)].label}</div>
          </div>
        }
      </div>

      {!last ?
      <Card pad={36} style={{ textAlign: "center", marginBottom: 26 }}>
          <Icon name="clock" size={32} color="var(--fg-subtle)" style={{ margin: "0 auto 12px" }} />
          <h3 style={{ fontSize: "var(--fs-lg)", marginBottom: 8 }}>Tu n'as pas encore passé ton quizz d'arrivée.</h3>
          <p className="muted" style={{ maxWidth: 420, margin: "0 auto 18px" }}>Lance ton quizz J0 pour découvrir ton point de départ.</p>
          <Btn variant="primary" iconRight="arrow-right" onClick={() => onStartJ15(r)}>Démarrer mon quizz J0</Btn>
        </Card> :

      <>
          {/* niveau + profil de connaissances */}
          <div style={{ display: "grid", gridTemplateColumns: "minmax(0,1fr) minmax(0,1.1fr)", gap: 24, alignItems: "center", marginBottom: 24 }}>
            <Card pad={28} style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 16 }}>
              <LevelBadge score={last.global} size={158} />
              {prev &&
            <Pill tone={delta >= 0 ? "env" : "gov"}>
                  <Icon name="trending-up" size={15} />{delta >= 0 ? "+" : ""}{delta} pts depuis J0
                </Pill>
            }
              <div className="muted" style={{ fontSize: "var(--fs-sm)", textAlign: "center" }}>{last.correct} bonnes réponses sur {last.asked} questions</div>
            </Card>
            <Card pad={20}>
              <div style={{ fontWeight: 700, marginBottom: 4, textAlign: "center" }}>Ton profil de connaissances</div>
              {prev && <div className="muted" style={{ fontSize: "var(--fs-xs)", textAlign: "center", marginBottom: 4 }}>
                <span style={{ color: "var(--color-neutral-400)" }}>● J0</span> &nbsp; <span style={{ color: "var(--color-env-600)" }}>● J+15</span>
              </div>}
              {(window.__viz || "both") === "bars" ?
            <div style={{ marginTop: 14 }}><DomainBars scores={last.scores} compare={prev ? prev.scores : null} /></div> :
            <div style={{ display: "grid", placeItems: "center" }}><Radar size={356} series={series} /></div>}
            </Card>
          </div>

          {/* CTA J+15 autonome OU note de réalisation */}
          {!hasJ15 ?
        <Card pad={0} style={{ overflow: "hidden", marginBottom: 24, background: "var(--bg-inverse)", border: "none", color: "#fff" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 18, padding: "22px 26px", flexWrap: "wrap" }}>
                <div style={{ width: 50, height: 50, borderRadius: 14, background: "rgba(255,255,255,.12)", display: "grid", placeItems: "center", flex: "none" }}>
                  <Icon name="refresh" size={24} color="var(--color-env-300)" />
                </div>
                <div style={{ flex: 1, minWidth: 220 }}>
                  <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: "var(--fs-lg)" }}>Prêt·e pour ton quizz J+15&nbsp;?</div>
                  <div style={{ color: "rgba(255,255,255,.8)", fontSize: "var(--fs-sm)", marginTop: 3 }}>
                    Tu peux le déclencher toi-même quand tu te sens prêt·e. On rejoue ce qui avait coincé à J0 et on ajoute des questions plus pointues.
                  </div>
                </div>
                <Btn variant="primary" iconRight="arrow-right" onClick={() => onStartJ15(r)}>Démarrer mon quizz J+15</Btn>
              </div>
            </Card> :

        <Card pad={18} style={{ marginBottom: 24, display: "flex", alignItems: "center", gap: 12 }}>
              <Icon name="check-circle" size={22} color="var(--color-env-600)" />
              <span style={{ fontSize: "var(--fs-sm)" }}>Tu as bouclé ton quizz <strong>J+15</strong>. Retrouve ci-dessous le détail de tes réponses et ton programme de formation.</span>
            </Card>
        }

          {/* détail des réponses */}
          <div style={{ display: "flex", justifyContent: "center", marginBottom: showRecap ? 18 : 30 }}>
            <Btn variant="secondary" icon={showRecap ? "chevron-down" : "list-checks"} onClick={() => setShowRecap((s) => !s)}>
              {showRecap ? "Masquer mes réponses" : "Revoir mes réponses (bonnes & mauvaises)"}
            </Btn>
          </div>
          {showRecap && <div className="fade-up" style={{ marginBottom: 30 }}><AnswerRecap quiz={quiz} answers={last.answers} /></div>}
        </>
      }

      {/* programme de formation */}
      <div style={{ marginBottom: 30 }}><TrainingProgram /></div>

      {/* et maintenant ? */}
      <EtMaintenant isJ15={lastIsJ15} name={r.name} />
    </div>);

}

/* ---------- accès espace recrue (prénom + nom, sans mot de passe) ---------- */
function RecrueGate({ onNew, onLogin }) {
  return (
    <div className="fade-up" style={{ maxWidth: 760, margin: "0 auto", padding: "8px 0 40px" }}>
      <Eyebrow>Espace recrue</Eyebrow>
      <h1 style={{ fontSize: "var(--fs-3xl)", marginTop: 10, marginBottom: 8 }}>Bienvenue chez ensō rse</h1>
      <p className="muted" style={{ fontSize: "var(--fs-md)", maxWidth: 560, marginBottom: 28 }}>
        Première fois ou retour&nbsp;? Choisis ton entrée — ton espace personnel garde tes résultats, ta progression et ton programme.
      </p>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 18 }}>
        <Card hover onClick={onNew} pad={28} style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div style={{ width: 52, height: 52, borderRadius: 14, background: "var(--color-env-100)", display: "grid", placeItems: "center", color: "var(--color-env-600)" }}>
            <Icon name="sparkles" size={26} />
          </div>
          <div>
            <h2 style={{ fontSize: "var(--fs-lg)", marginBottom: 6 }}>C'est ma première fois</h2>
            <p className="muted" style={{ fontSize: "var(--fs-sm)", lineHeight: 1.5 }}>Je passe mon quizz d'arrivée (J0) et je crée mon espace.</p>
          </div>
          <div style={{ display: "inline-flex", alignItems: "center", gap: 8, fontWeight: 600, color: "var(--color-env-600)", marginTop: "auto" }}>Commencer <Icon name="arrow-right" size={18} /></div>
        </Card>
        <Card hover onClick={onLogin} pad={28} style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div style={{ width: 52, height: 52, borderRadius: 14, background: "var(--color-soc-100)", display: "grid", placeItems: "center", color: "var(--color-soc-600)" }}>
            <Icon name="user" size={26} />
          </div>
          <div>
            <h2 style={{ fontSize: "var(--fs-lg)", marginBottom: 6 }}>J'ai déjà mon espace</h2>
            <p className="muted" style={{ fontSize: "var(--fs-sm)", lineHeight: 1.5 }}>J'accède à mes résultats et je déclenche mon quizz J+15.</p>
          </div>
          <div style={{ display: "inline-flex", alignItems: "center", gap: 8, fontWeight: 600, color: "var(--color-soc-600)", marginTop: "auto" }}>Me connecter <Icon name="arrow-right" size={18} /></div>
        </Card>
      </div>
    </div>);

}

function RecrueLogin({ onFound, onBack }) {
  const [name, setName] = useState("");
  const [err, setErr] = useState("");
  const submit = () => {
    const q = name.trim().toLowerCase();
    if (!q) return;
    const found = window.Store.all().find((r) => r.name.trim().toLowerCase() === q);
    if (found) onFound(found);else
    setErr("Aucun espace trouvé à ce nom. Vérifie l'orthographe (prénom + nom), ou passe d'abord ton quizz d'arrivée.");
  };
  return (
    <div className="fade-up" style={{ maxWidth: 560, margin: "0 auto", padding: "8px 0 40px" }}>
      <button onClick={onBack} style={{ display: "inline-flex", gap: 7, alignItems: "center", background: "none", border: "none", color: "var(--fg-muted)", fontWeight: 600, fontSize: "var(--fs-sm)", marginBottom: 16, padding: 0 }}>
        <Icon name="arrow-left" size={17} /> Retour
      </button>
      <Eyebrow>Espace recrue</Eyebrow>
      <h1 style={{ fontSize: "var(--fs-2xl)", marginTop: 8, marginBottom: 8 }}>Accède à ton espace</h1>
      <p className="muted" style={{ fontSize: "var(--fs-md)", marginBottom: 24 }}>Pas de mot de passe — saisis simplement ton prénom et ton nom, comme à ton arrivée.</p>
      <Card pad={26} style={{ marginBottom: 18 }}>
        <label style={{ fontWeight: 600, fontSize: "var(--fs-sm)", display: "block", marginBottom: 8 }}>Prénom & nom</label>
        <input value={name} autoFocus onChange={(e) => {setName(e.target.value);setErr("");}} onKeyDown={(e) => e.key === "Enter" && submit()} placeholder="ex. Marion Lefèvre"
        style={{ width: "100%", padding: "13px 16px", borderRadius: "var(--r-md)", border: `1px solid ${err ? "var(--danger-500)" : "var(--border-strong)"}`, fontFamily: "var(--font-body)", fontSize: "var(--fs-base)", background: "#fff", color: "var(--fg-default)" }} />
        {err && <div style={{ color: "var(--danger-fg)", fontSize: "var(--fs-sm)", marginTop: 10, lineHeight: 1.4 }}>{err}</div>}
      </Card>
      <Btn size="lg" iconRight="arrow-right" disabled={!name.trim()} onClick={submit}>Accéder à mon espace</Btn>
    </div>);

}

/* ---------- résultat ---------- */
function ResultStep({ profile, attemptNo, phase, prev, quiz, answers, onHome }) {
  const QD = window.QD;
  const isJ15 = (phase || (attemptNo >= 2 ? "j15" : "j0")) === "j15";
  const res = useMemo(() => window.Store.computeResult(answers), [answers]);
  const lvl = QD.levelFor(res.global);
  const [showRecap, setShowRecap] = useState(false);

  // strengths / gaps
  const sorted = QD.DOMAINS.map((d) => ({ d, v: res.scores[d.id] })).filter((x) => x.v != null).sort((a, b) => b.v - a.v);
  const strong = sorted.filter((x) => x.v >= 70).slice(0, 3);
  const weak = sorted.filter((x) => x.v < 55).slice(-3).reverse();

  const series = [{ values: res.scores, color: "var(--color-env-500)", fill: "rgba(0,175,143,.16)" }];
  if (prev) series.unshift({ values: prev.scores, color: "var(--color-neutral-300)", fill: "rgba(0,0,0,.04)", dots: false });

  return (
    <div className="fade-up" style={{ maxWidth: 960, margin: "0 auto", padding: "8px 0 60px" }}>
      <div style={{ textAlign: "center", marginBottom: 8 }}>
        <Eyebrow>{isJ15 ? "Quizz J+15 · progression" : "Ton niveau d'entrée · J0"}</Eyebrow>
      </div>
      <h1 style={{ textAlign: "center", fontSize: "var(--fs-3xl)", margin: "10px 0 6px" }}>
        {profile.name.split(" ")[0]}, {isJ15 ? "regarde le chemin parcouru." : "voici où tu en es."}
      </h1>
      <p className="muted" style={{ textAlign: "center", maxWidth: 560, margin: "0 auto 36px", fontSize: "var(--fs-md)" }}>{lvl.blurb}</p>

      <div style={{ display: "grid", gridTemplateColumns: "minmax(0,1fr) minmax(0,1.1fr)", gap: 28, alignItems: "center", marginBottom: 34 }}>
        <Card pad={30} style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 18 }}>
          <LevelBadge score={res.global} size={168} />
          {prev &&
          <Pill tone={res.global >= prev.global ? "env" : "gov"}>
              <Icon name="trending-up" size={15} />
              {res.global >= prev.global ? "+" : ""}{res.global - prev.global} pts depuis J0
            </Pill>
          }
          <div className="muted" style={{ fontSize: "var(--fs-sm)", textAlign: "center" }}>
            {res.correct} bonnes réponses sur {res.asked} questions
          </div>
        </Card>
        <Card pad={20}>
          <div style={{ fontWeight: 700, marginBottom: 4, textAlign: "center" }}>Ton profil de connaissances</div>
          {prev && <div className="muted" style={{ fontSize: "var(--fs-xs)", textAlign: "center", marginBottom: 4 }}>
            <span style={{ color: "var(--color-neutral-400)" }}>● quizz précédent</span> &nbsp; <span style={{ color: "var(--color-env-600)" }}>● aujourd'hui</span>
          </div>}
          {(window.__viz || "both") === "bars" ?
          <div style={{ marginTop: 14 }}><DomainBars scores={res.scores} compare={prev ? prev.scores : null} /></div> :
          <div style={{ display: "grid", placeItems: "center" }}><Radar size={360} series={series} /></div>}
        </Card>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20, marginBottom: 30 }}>
        <Card pad={22}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 14 }}>
            <Icon name="award" size={20} color="var(--color-env-600)" />
            <h3 style={{ fontSize: "var(--fs-lg)" }}>Tes points forts</h3>
          </div>
          {strong.length ? strong.map((x) =>
          <div key={x.d.id} style={{ display: "flex", justifyContent: "space-between", padding: "9px 0", borderBottom: "1px solid var(--border-default)" }}>
              <span style={{ fontWeight: 500 }}>{x.d.label}</span><span style={{ fontWeight: 700, color: "var(--color-env-600)" }}>{x.v}%</span>
            </div>
          ) : <p className="muted" style={{ fontSize: "var(--fs-sm)" }}>On va construire ça ensemble pendant l'onboarding — c'est exactement le but.</p>}
        </Card>
        <Card pad={22}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 14 }}>
            <Icon name="target" size={20} color="var(--color-gov-600)" />
            <h3 style={{ fontSize: "var(--fs-lg)" }}>À explorer en priorité</h3>
          </div>
          {weak.length ? weak.map((x) =>
          <div key={x.d.id} style={{ display: "flex", justifyContent: "space-between", padding: "9px 0", borderBottom: "1px solid var(--border-default)" }}>
              <span style={{ fontWeight: 500 }}>{x.d.label}</span><span style={{ fontWeight: 700, color: "var(--color-gov-600)" }}>{x.v}%</span>
            </div>
          ) : <p className="muted" style={{ fontSize: "var(--fs-sm)" }}>Solide partout — joli&nbsp;! Ton manager calibrera un onboarding qui va te challenger.</p>}
        </Card>
      </div>

      <div style={{ marginBottom: 30 }}><EtMaintenant isJ15={isJ15} name={profile.name} /></div>

      <div style={{ display: "flex", gap: 12, justifyContent: "center", flexWrap: "wrap" }}>
        <Btn variant="secondary" icon={showRecap ? "chevron-down" : "list-checks"} onClick={() => setShowRecap((s) => !s)}>
          {showRecap ? "Masquer le détail" : "Revoir mes réponses & explications"}
        </Btn>
        <Btn variant="primary" icon="home" onClick={onHome}>Retour à l'accueil</Btn>
      </div>

      {showRecap && <div className="fade-up" style={{ marginTop: 26 }}><AnswerRecap quiz={quiz} answers={answers} /></div>}
    </div>);

}

/* ---------- orchestrateur recrue ---------- */
function RecrueFlow({ initialRecruit, onHome }) {
  const selfServe = !initialRecruit;
  const [step, setStep] = useState(initialRecruit ? "profile" : "gate");
  const [profile, setProfile] = useState(null);
  const [quiz, setQuiz] = useState(null);
  const [answers, setAnswers] = useState(null);
  const [recruit, setRecruit] = useState(initialRecruit || null);
  const [attemptNo, setAttemptNo] = useState(1); // frozen at quiz start
  const [phase, setPhase] = useState("j0");
  const [prevAttempt, setPrevAttempt] = useState(null);

  const buildAndStart = (p, base) => {
    const n = (base?.attempts?.length || 0) + 1;
    const ph = n >= 2 ? "j15" : "j0";
    const prior = base && base.attempts.length ? base.attempts[base.attempts.length - 1] : null;
    let weak = null, retakeIds = [], exclude = [];
    if (prior) {
      weak = window.QD.DOMAINS.filter((d) => (prior.scores[d.id] ?? 100) < 60).map((d) => d.id);
      Object.keys(prior.answers).forEach((qid) => {
        const q = window.Store.qById[qid], a = prior.answers[qid];
        if (!q || q.type === "selfrate") return;
        if (a.correct) exclude.push(qid); else retakeIds.push(qid);
      });
    }
    const qz = window.QD.buildQuiz(p.role, p.statut, { attempt: n, phase: ph, weakDomains: weak, retakeIds, exclude });
    setAttemptNo(n); setPhase(ph); setPrevAttempt(prior);
    setProfile(p); setQuiz(qz); setStep("quiz");
  };

  // depuis ProfileStep (saisie manuelle / manager)
  const start = (p) => buildAndStart(p, recruit || initialRecruit);
  // depuis l'espace perso : déclenche directement le quizz (J0 ou J+15) sans re-saisie
  const startFromSpace = (r) => { setRecruit(r); buildAndStart({ name: r.name, role: r.role, statut: r.statut }, r); };

  const finish = (ans) => {
    setAnswers(ans);
    let rec = recruit;
    if (!rec) {
      rec = { id: window.Store.newId(), name: profile.name, role: profile.role, statut: profile.statut,
        createdAt: new Date().toISOString(), attempts: [] };
    }
    const res = window.Store.computeResult(ans);
    const attempt = { attempt: attemptNo, phase, date: new Date().toISOString(), answers: ans, quizIds: quiz.map((q) => q.id), ...res };
    rec = { ...rec, attempts: [...rec.attempts, attempt] };
    window.Store.upsertRecruit(rec);
    setRecruit(rec);
    setStep("result");
  };

  const afterResult = () => { if (selfServe) setStep("space"); else onHome(); };

  if (step === "gate")
  return <div style={{ padding: "32px 24px" }}><RecrueGate onNew={() => setStep("profile")} onLogin={() => setStep("login")} /></div>;
  if (step === "login")
  return <div style={{ padding: "32px 24px" }}><RecrueLogin onBack={() => setStep("gate")} onFound={(r) => {setRecruit(r);setStep("space");}} /></div>;
  if (step === "space")
  return <div style={{ padding: "32px 24px" }}><RecrueSpace recruit={recruit} onStartJ15={startFromSpace} onHome={onHome} /></div>;
  if (step === "quiz")
  return <QuizStep profile={profile} attemptNo={attemptNo} phase={phase} quiz={quiz} onDone={finish} onQuit={() => setStep(selfServe ? recruit && recruit.attempts.length ? "space" : "gate" : "profile")} />;
  if (step === "result")
  return <div style={{ padding: "32px 24px" }}><ResultStep profile={profile} attemptNo={attemptNo} phase={phase} prev={prevAttempt} quiz={quiz} answers={answers} onHome={afterResult} /></div>;
  return <div style={{ padding: "32px 24px" }}><ProfileStep initial={initialRecruit} onStart={start} /></div>;
}

Object.assign(window, { RecrueFlow });