/* ============================================================
   PORTE III — TROUVER UN PRÉNOM (moteur de nommage)
   Saisie du champ familial (prénoms parents + aînés), intention
   (Équilibrer / Ancrer / Amplifier), genre → suggestions accordées.
   Scoring élémentaire 100 % déterministe (core.js : suggestNames),
   choix final = une poignée semi-aléatoire parmi les mieux accordés.
   ============================================================ */
const { useState: useStateN, useEffect: useEffectN } = React;
const NM = window;

const GENRE_LABEL = { f: "fille", m: "garçon", x: "mixte" };
const INTENTION_LIST = [
{ key: "equilibrer", nom: "Équilibrer", baseline: "compléter ce qui manque",
  desc: "Apporter l'élément le moins présent chez vous." },
{ key: "ancrer", nom: "Ancrer", baseline: "enraciner, apaiser",
  desc: "Un prénom de Terre et d'Eau, pour poser et rassurer." },
{ key: "amplifier", nom: "Amplifier", baseline: "prolonger votre nature",
  desc: "Renforcer l'élément qui vous porte déjà." },
{ key: "contraster", nom: "Contraster le nom", baseline: "alléger le patronyme",
  desc: "Répondre à l'élément du nom de famille par son contraire.", needsNom: true }];

const GENRE_LIST = [
{ key: "fille", nom: "Fille" },
{ key: "garcon", nom: "Garçon" },
{ key: "mixte", nom: "Mixte" },
{ key: "tous", nom: "Peu importe" }];

const ORIGIN_LIST = [
{ key: "peu_importe", nom: "Peu importe" },
{ key: "lignee", nom: "Notre culture" },
{ key: "ailleurs", nom: "Ouvrir ailleurs" }];


/* shortlist locale (la liste que les parents se constituent) */
function loadNoms() {
  try {return JSON.parse(localStorage.getItem("oracle_noms") || "[]");}
  catch (e) {return [];}
}
function saveNoms(l) {try {localStorage.setItem("oracle_noms", JSON.stringify(l));} catch (e) {}}

/* un élément : pastille colorée + nom */
function ElemDot({ el }) {
  return <span className={"elem-dot elem-" + el.toLowerCase()} title={el}></span>;
}
function ElemTag({ el, lead }) {
  const meta = NM.ELEM_META[el];
  return (
    <span className={"elem-tag elem-" + el.toLowerCase() + (lead ? " elem-lead" : "")}>
      <ElemDot el={el} />{meta ? meta.nom : el}
    </span>);

}

/* signature chiffrée — la PREUVE que tout est calculé depuis les lettres */
function Signature({ cand }) {
  if (cand.gematrie == null) return null;
  const poids = cand.poids <= 0.4 ? "légère" : cand.poids >= 0.6 ? "dense" : "posée";
  return (
    <div className="nm-sig" title="Calculé depuis les lettres — gématrie A=1…Z=26, réduite 1-9 ; matière sonore.">
      <span className="nm-sig-item">gématrie <b>{cand.gematrie}</b></span>
      <span className="nm-sig-sep">·</span>
      <span className="nm-sig-item">nombre <b>{cand.nombre}</b></span>
      <span className="nm-sig-sep">·</span>
      <span className="nm-sig-item">matière <b>{poids}</b></span>
    </div>);

}

/* le champ familial : barres d'équilibre élémentaire (composant de réserve, non monté) */
function FieldBars({ field }) {
  const max = Math.max(0.001, ...NM.ELEMENTS.map((e) => field.pct[e]));
  return (
    <div className="nm-field">
      <div className="nm-field-bars">
        {NM.ELEMENTS.map((el) => {
          const w = Math.round(field.pct[el] / max * 100);
          const isDom = field.has && el === field.dominant;
          const isWeak = field.has && el === field.weakest;
          return (
            <div className={"nm-bar-row" + (isDom ? " nm-bar-dom" : "")} key={el}>
              <span className="nm-bar-name"><ElemDot el={el} />{NM.ELEM_META[el].nom}</span>
              <span className="nm-bar-track"><span className={"nm-bar-fill elem-fill-" + el.toLowerCase()} style={{ width: Math.max(w, 4) + "%" }}></span></span>
              <span className="nm-bar-flag">{isDom ? "dominant" : isWeak ? "en retrait" : ""}</span>
            </div>);

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

}

/* données calculées d'une personne (parent/aîné) — depuis les lettres */
function personData(name) {
  const O = NM.Onomancie;
  const label = (name || "").trim().replace(/\s+/g, " ");
  const disp = label ? label[0].toUpperCase() + label.slice(1) : "";
  if (!O || !disp) return null;
  const sig = O.signature(disp, NM.nommageBaseline ? NM.nommageBaseline() : null);
  return {
    label: disp,
    elemParts: sig.elements,
    dom: sig.elements[0],
    gematrie: sig.gematrie,
    nombre: sig.nombre,
    matiere: sig.poids <= 0.4 ? "légère" : sig.poids >= 0.6 ? "dense" : "posée"
  };
}

/* une box « conjoint » — résumé bref des data (pas d'explication étendue) */
function PersonBox({ name }) {
  const d = personData(name);
  if (!d) return null;
  return (
    <div className="nm-person">
      <div className="nm-person-head">
        <span className={"nm-person-initial elem-" + (d.dom || "feu").toLowerCase()}>{d.label[0]}</span>
        <span className="nm-person-name">{d.label}</span>
      </div>
      <div className="nm-person-elems">{d.elemParts.map((e) => <ElemTag el={e} key={e} />)}</div>
      <div className="nm-person-sig">
        <span>gématrie <b>{d.gematrie}</b></span>
        <span>nombre <b>{d.nombre}</b></span>
        <span>matière <b>{d.matiere}</b></span>
      </div>
    </div>);

}

/* lettres d'un prénom → séquence avec leur sens (window.LETTRES) */
function nameLetters(label) {
  const s = (label || "").normalize("NFD").replace(/[\u0300-\u036f]/g, "").toUpperCase();
  const seq = [];
  for (const c of s) {
    if (c >= "A" && c <= "Z" && NM.LETTRES && NM.LETTRES[c]) seq.push(Object.assign({ lettre: c }, NM.LETTRES[c]));
  }
  return seq;
}

/* panneau dépliant « Données & lettres » — la donnée calculée + l'analyse lettre à lettre */
function CandidateData({ cand }) {
  const seq = nameLetters(cand.label);
  const matiere = cand.poids <= 0.4 ? "légère" : cand.poids >= 0.6 ? "dense" : "posée";
  const last = seq.length - 1;
  return (
    <div className="nm-data">
      {cand.expr && <p className="nm-data-tier">Le prénom seul <span className="nm-data-tier-sub">— son « nombre actif »</span></p>}
      <div className="nm-data-grid">
        <div className="nm-data-cell"><span className="nm-data-k">genre</span><span className="nm-data-v">{GENRE_LABEL[cand.genre]}</span></div>
        <div className="nm-data-cell"><span className="nm-data-k">éléments</span><span className="nm-data-v nm-data-elems">{cand.elemParts.map((e) => <ElemTag el={e} key={e} />)}</span></div>
        <div className="nm-data-cell"><span className="nm-data-k">gématrie</span><span className="nm-data-v">{cand.gematrie}</span></div>
        <div className="nm-data-cell"><span className="nm-data-k">nombre</span><span className="nm-data-v">{cand.nombre}</span></div>
        <div className="nm-data-cell"><span className="nm-data-k">matière</span><span className="nm-data-v nm-data-mat">{matiere}</span></div>
      </div>
      {cand.expr &&
      <div className="nm-expr">
        <p className="nm-data-tier">Le nom complet <span className="nm-data-tier-sub">— ce que l'enfant portera vraiment</span></p>
        <div className="nm-expr-name">{cand.expr.full}</div>
        <div className="nm-expr-sig-row">
          <span className="nm-expr-elems">{cand.expr.elemParts.map((e) => <ElemTag el={e} key={e} />)}</span>
          <span className="nm-expr-nums">gématrie&nbsp;<b>{cand.expr.gematrie}</b> · nombre&nbsp;<b>{cand.expr.nombre}</b></span>
        </div>
      </div>}
      {seq.length > 0 &&
      <div className="nm-data-letters">
        <div className="name-cat-label">Les lettres <span className="name-cat-help">— {cand.label.toLowerCase()}, lettre à lettre</span></div>
        <ol className="lettre-liste">
          {seq.map((l, i) => {
            const tag = i === 0 ? "ouverture" : i === last ? "clôture" : null;
            return (
              <li className={"lettre-row" + (tag ? " lettre-row--" + (i === 0 ? "open" : "close") : "")} key={i}>
                <div className="lettre-row-glyph">
                  <span className="lettre-row-letter">{l.lettre}</span>
                  {tag && <span className="lettre-row-tag">{tag}</span>}
                </div>
                <div className="lettre-row-body">
                  <p className="lettre-row-sens">{l.sens}</p>
                  <p className="lettre-row-piste">{l.piste}</p>
                </div>
              </li>);

          })}
        </ol>
      </div>}
      <p className="nm-data-note">Tout est calculé depuis les lettres — gématrie (A=1…Z=26) réduite à un nombre, éléments et matière sonore. Rien n'est décidé à la main.</p>
    </div>);

}

/* accord avec la fratrie — euphonie + complétude (psychogénéalogie) */
function FratrieAccord({ cand }) {
  const f = cand.fratrie;
  if (!f || !f.aines || !f.aines.length) return null;
  const clash = f.clashes && f.clashes.length;
  const accord = f.accords && f.accords.length;
  if (!clash && !accord) return null;
  return (
    <p className={"nm-fratrie" + (clash ? " nm-fratrie--clash" : " nm-fratrie--accord")}>
      <span className="nm-fratrie-k">avec {f.aines.join(", ")}</span>
      <span className="nm-fratrie-v">{clash ? f.clashes.join(" · ") : f.accords.slice(0, 2).join(" · ")}</span>
    </p>);

}

/* une suggestion — variante CARTE */
function SuggestCard({ cand, saved, onSave, onShare, onFiche }) {
  const Lettrine = NM.Lettrine;
  const Questions = NM.Questions;
  const [open, setOpen] = useStateN(false);
  return (
    <div className="nm-card">
      <div className="nm-card-head">
        <Lettrine mot={cand.label} size={104} />
        <div className="nm-card-id">
          <div className="nm-card-meta">
            <span className="nm-genre">{GENRE_LABEL[cand.genre]}</span>
            <span className="nm-elems-dots">{cand.elemParts.map((e) => <ElemDot el={e} key={e} />)}</span>
          </div>
          <div className="nm-card-name">{cand.label}</div>
          {cand.origine && cand.sens &&
          <div className="nm-card-etym"><span className="nm-orig">{cand.origine}</span> · {cand.sens}</div>}
        </div>
      </div>
      <p className="nm-why">{cand.why}</p>
      {cand.piste && <p className="nm-piste">{cand.piste}</p>}
      <FratrieAccord cand={cand} />

      <div className={"q-block nm-data-block" + (open ? " q-open" : "")}>
        <button className="q-toggle" onClick={() => setOpen(!open)} aria-expanded={open}>
          <span className="q-chevron">›</span><span className="nm-data-q-lbl">Données &amp; lettres</span>
        </button>
        {open && <CandidateData cand={cand} />}
      </div>

      <div className="nm-card-foot">
        <div className="nm-card-actions">
          <button className={"nm-keep" + (saved ? " nm-keep-on" : "")} onClick={() => onSave(cand)}>
            {saved ? "✦ dans ta liste" : "Garder ce prénom"}
          </button>
          {onFiche && <button className="nm-fiche-link" onClick={() => onFiche(cand.label, cand.expr ? cand.expr.patLabel : "")}>Fiche complète</button>}
          <button className="nm-share-link" onClick={() => onShare(cand)}>Voir la carte →</button>
        </div>
      </div>
    </div>);

}

/* une suggestion — variante LISTE (éditoriale, compacte) */
function SuggestRow({ cand, saved, onSave, onShare, onFiche }) {
  const [open, setOpen] = useStateN(false);
  return (
    <div className={"nm-row" + (open ? " nm-row-open" : "")}>
      <button className="nm-row-main" onClick={() => setOpen(!open)}>
        <span className="nm-row-elem">{cand.elemParts.map((e) => <ElemDot el={e} key={e} />)}</span>
        <span className="nm-row-name">{cand.label}</span>
        <span className="nm-row-genre">{GENRE_LABEL[cand.genre]}</span>
        <span className="nm-row-why">{cand.why}</span>
        <span className="nm-row-chev">{open ? "−" : "+"}</span>
      </button>
      {open &&
      <div className="nm-row-detail">
          {cand.origine && cand.sens && <p className="nm-card-etym"><span className="nm-orig">{cand.origine}</span> · {cand.sens}</p>}
          {cand.piste && <p className="nm-piste">{cand.piste}</p>}
          <FratrieAccord cand={cand} />
          <CandidateData cand={cand} />
          <div className="nm-card-actions">
            <button className={"nm-keep" + (saved ? " nm-keep-on" : "")} onClick={() => onSave(cand)}>
              {saved ? "✦ dans ta liste" : "Garder ce prénom"}
            </button>
            {onFiche && <button className="nm-fiche-link" onClick={() => onFiche(cand.label, cand.expr ? cand.expr.patLabel : "")}>Fiche complète</button>}
            <button className="nm-share-link" onClick={() => onShare(cand)}>Voir la carte →</button>
          </div>
        </div>}
    </div>);

}

/* lecture du nom de famille (axe Λ) — flouté en partie pour le mode gratuit */
function PatronymeBlock({ pat, pro, onUnlock }) {
  const meta = NM.ELEM_META[pat.dom];
  const oppMeta = NM.ELEM_META[pat.oppose];
  const dictSens = pat.dict && pat.dict.s ? pat.dict.s : null;
  return (
    <div className="nm-pat-block">
      <div className="name-cat-label">Le nom, « {pat.label} »
        <span className="name-cat-help">— le décor hérité (axe fixe)</span>
      </div>
      <div className="nm-pat-head">
        <span className="nm-pat-elem"><ElemDot el={pat.dom} /><b>{meta.nom}</b></span>
        <span className="nm-sig-item">gématrie <b>{pat.gematrie}</b></span>
        <span className="nm-sig-item">nombre <b>{pat.nombre}</b></span>
        <span className={"nm-pat-poids" + (pat.lourd ? " nm-pat-lourd" : "")}>{pat.lourd ? "matière dense" : "matière légère"}</span>
      </div>
      <p className="nm-pat-read">
        {dictSens && <span><span className="nm-orig">{(pat.dict.o || pat.dict.type || "")}</span> {dictSens}. </span>}
        Par ses lettres, « {pat.label} » porte <b>{meta.nom}</b> ({meta.trait}).{" "}
        {pat.lourd
          ? "Sa matière sonore est dense — un nom qui pèse, qui ancre."
          : "Sa matière sonore est légère — un nom qui ne pèse pas trop."}
        {pro
          ? " Son contraire, " + oppMeta.nom + " (" + oppMeta.court + "), est ce qu'un prénom peut lui offrir en réponse."
          : ""}
      </p>
      {!pro &&
      <div className="nm-pat-lock">
        <div className="nm-pat-lock-veil"></div>
        <p className="nm-pat-lock-text">La lecture complète du nom — son contraire, son mandat, ce qu'un prénom peut lui répondre — s'ouvre dans l'<b>Oracle augmenté</b>. <button className="nm-pat-lock-btn" onClick={onUnlock}>Déverrouiller →</button></p>
      </div>}
    </div>);

}

/* verrou aperçu → liste complète (PRO) */
function NommageLock({ hidden, onUnlock }) {
  return (
    <div className="prenom-lock nm-lock">
      <div className="prenom-lock-veil"></div>
      <div className="prenom-lock-card">
        <div className="eyebrow">La sélection complète</div>
        <p className="prenom-lock-text">
          Un premier prénom t'est offert. Les <b>{hidden} autres prénoms accordés</b> à votre foyer,
          leur lecture et la possibilité d'<b>en tirer d'autres</b> t'attendent dans l'<b>Oracle augmenté</b>.
        </p>
        <button className="upsell-btn" onClick={onUnlock}>Voir tous les prénoms →</button>
      </div>
    </div>);

}

/* ---------------- Espace Trouver un prénom ---------------- */
function NommageSpace({ onJournal, onOpenFiche }) {
  const [phase, setPhase] = useStateN("accueil"); // accueil | resultats
  const [parents, setParents] = useStateN("");
  const [aines, setAines] = useStateN("");
  const [patronyme, setPatronyme] = useStateN("");
  const [intention, setIntention] = useStateN("equilibrer");
  const [genre, setGenre] = useStateN("tous");
  const [origine, setOrigine] = useStateN("peu_importe");
  const [res, setRes] = useStateN(null);
  const [layout, setLayout] = useStateN("cartes"); // cartes | liste
  const [noms, setNoms] = useStateN(loadNoms());
  const [share, setShare] = useStateN(null);

  const { pro, openPaywall } = React.useContext(NM.OracleCtx);
  const ShareCard = NM.ShareCard;

  function splitNames(s) {return (s || "").split(/[,;\n]+/).map((x) => x.trim()).filter(Boolean);}

  function chercher() {
    const r = NM.suggestNames({
      parents: splitNames(parents),
      aines: splitNames(aines),
      patronyme: patronyme.trim() || null,
      intention: intention,
      genre: genre,
      origine: origine,
      n: pro ? 6 : 4
    });
    setRes(r);
    setPhase("resultats");
  }
  function relancer() {
    if (!res) return;
    const r = NM.suggestNames({
      parents: splitNames(parents),
      aines: splitNames(aines),
      patronyme: patronyme.trim() || null,
      intention: intention,
      genre: genre,
      origine: origine,
      n: pro ? 6 : 4,
      exclude: noms.map((x) => x.key) // ne repropose pas ce qui est déjà gardé
    });
    setRes(r);
  }

  function keep(cand) {
    if (noms.some((x) => x.key === cand.key)) {
      const next = noms.filter((x) => x.key !== cand.key);
      setNoms(next);saveNoms(next);return;
    }
    const next = [{ key: cand.key, label: cand.label, genre: cand.genre, elem: cand.elem, sens: cand.sens, intention: res.intention.key }].concat(noms);
    setNoms(next);saveNoms(next);
    // garde aussi une trace au journal (onglet Prénoms)
    if (onJournal) {
      onJournal({
        id: Date.now(), space: "prenom", fromNommage: true, nomKey: cand.key,
        prenom: cand.label, nom: "",
        relation: "proche", relLabel: "prénom envisagé · " + (GENRE_LABEL[cand.genre] || "enfant à venir"),
        found: !!(cand.origine && cand.sens),
        prenomsFull: cand.label, ombres: [],
        etym: cand.origine && cand.sens ? { origine: cand.origine, sens: cand.sens, piste: cand.piste || "" } : null,
        initiale: "", finale: "",
        synthese: cand.why || "", questions: [], intention: ""
      });
    }
  }
  function removeNom(key) {
    const next = noms.filter((x) => x.key !== key);
    setNoms(next);saveNoms(next);
  }
  const isSaved = (key) => noms.some((x) => x.key === key);

  /* ---------- accueil ---------- */
  if (phase === "accueil") {
    return (
      <div className="fade-screen">
        <div className="eyebrow">Trouver un prénom</div>
        <h1 className="lede">Quel prénom pour<br />l'enfant qui <em>vient ?</em></h1>
        <p className="sub">Pas de numérologie, pas de tendances. On lit l'élément de vos propres prénoms — Feu, Eau, Air, Terre — puis on tire, dans le sens que vous choisissez, des prénoms qui s'y accordent. Le hasard propose ; à vous d'écouter.</p>

        <div className="field">
          <div className="nm-fields">
            <div className="prenom-input-wrap">
              <label className="field-label" htmlFor="np">Vos prénoms <span className="opt">— les parents</span></label>
              <input id="np" className="prenom-input" type="text" autoComplete="off"
              placeholder="Marie, Thomas…" value={parents}
              onChange={(e) => setParents(e.target.value)}
              onKeyDown={(e) => {if (e.key === "Enter") chercher();}} />
            </div>
            <div className="prenom-input-wrap">
              <label className="field-label" htmlFor="na">Les aîné·es <span className="opt">— optionnel</span></label>
              <input id="na" className="prenom-input" type="text" autoComplete="off"
              placeholder="Léa, Gabriel…" value={aines}
              onChange={(e) => setAines(e.target.value)}
              onKeyDown={(e) => {if (e.key === "Enter") chercher();}} />
            </div>
          </div>
          <p className="prenom-hint">Séparez les prénoms par une virgule. Chacun apporte son <b>élément</b> au foyer ; on s'en sert pour viser juste — vous pouvez aussi laisser vide et vous fier à la seule intention.</p>

          <div className="nm-fields nm-fields-sec">
            <div className="prenom-input-wrap">
              <label className="field-label" htmlFor="nn">Le nom de famille <span className="opt">— optionnel, l'enfant le portera</span></label>
              <input id="nn" className="prenom-input" type="text" autoComplete="off"
              placeholder="Lefebvre…" value={patronyme}
              onChange={(e) => setPatronyme(e.target.value)}
              onKeyDown={(e) => {if (e.key === "Enter") chercher();}} />
            </div>
            <div className="prenom-input-wrap">
              <label className="field-label">Culture d'origine <span className="opt">— du prénom proposé</span></label>
              <div className="nm-genres nm-origines">
                {ORIGIN_LIST.map((o) =>
                <button className={"nm-genre-pick" + (origine === o.key ? " nm-genre-on" : "")} key={o.key} onClick={() => setOrigine(o.key)}>{o.nom}</button>
                )}
              </div>
            </div>
          </div>

          <div className="formule-group">Dans quel sens ?</div>
          <div className="nm-intentions">
            {INTENTION_LIST.filter((it) => !it.needsNom || patronyme.trim()).map((it) =>
            <button className="nm-intent" aria-pressed={intention === it.key} key={it.key} onClick={() => setIntention(it.key)}>
                <span className="nm-intent-nom">{it.nom}</span>
                <span className="nm-intent-base">{it.baseline}</span>
                <span className="nm-intent-desc">{it.desc}</span>
              </button>
            )}
          </div>

          <div className="formule-group">Pour</div>
          <div className="nm-genres">
            {GENRE_LIST.map((g) =>
            <button className={"nm-genre-pick" + (genre === g.key ? " nm-genre-on" : "")} key={g.key} onClick={() => setGenre(g.key)}>{g.nom}</button>
            )}
          </div>

          <div className="actions">
            <button className="btn-primary" onClick={chercher}>Trouver des prénoms</button>
            <span className="hint-inline">le hasard, accordé à votre foyer</span>
          </div>

          {noms.length > 0 &&
          <p className="nm-shortlist-hint">✦ {noms.length} prénom{noms.length > 1 ? "s" : ""} dans ta liste — ils réapparaîtront en bas des résultats.</p>}
        </div>
      </div>);

  }

  /* ---------- résultats ---------- */
  const field = res.field;
  const visible = pro ? res.suggestions : res.suggestions.slice(0, 1);
  const hidden = res.suggestions.length - visible.length;
  const parentList = splitNames(parents);
  const ainesList = splitNames(aines);
  const aimText =
  res.intention.key === "equilibrer" ? field.has ? "On cherche : " + NM.ELEM_META[field.weakest].nom : "Guidé par l'intention seule" :
  res.intention.key === "amplifier" ? field.has ? "On prolonge : " + NM.ELEM_META[field.dominant].nom : "Guidé par l'intention seule" :
  res.intention.key === "ancrer" ? "On vise : Terre & Eau" :
  res.intention.key === "contraster" ? "On vise : le contraire du nom" : "";

  return (
    <div className="fade-screen">
      <div className="nm-result-head">
        <div className="eyebrow">{res.intention.nom} · {GENRE_LIST.find((g) => g.key === res.genre).nom.toLowerCase()}{res.origine !== "peu_importe" ? " · " + ORIGIN_LIST.find((o) => o.key === res.origine).nom.toLowerCase() : ""}</div>
        <h1 className="lede nm-result-lede">Des prénoms qui<br /><em>vous ressemblent.</em></h1>
      </div>

      {/* le foyer — une box par conjoint */}
      <div className="nm-field-block">
        <div className="nm-foyer-top">
          <div className="name-cat-label">Votre foyer
            <span className="name-cat-help">— {parentList.length ? "lu sur les prénoms, lettre à lettre" : "aucun prénom — guidé par la seule intention"}</span>
          </div>
          {aimText && <span className="nm-foyer-aim">{aimText}</span>}
        </div>
        {parentList.length > 0 &&
        <div className="nm-foyer-boxes">
            {parentList.map((p, i) => <PersonBox name={p} key={i} />)}
          </div>}
        {ainesList.length > 0 &&
        <div className="nm-foyer-aines">
            <span className="nm-foyer-aines-k">aussi compté·es</span>
            {ainesList.map((a, i) => {
              const d = personData(a);
              return d ? <span className="nm-aine-chip" key={i}><ElemDot el={d.dom} /><b>{d.label}</b></span> : null;
            })}
          </div>}
        {res.patronyme &&
        <PatronymeBlock pat={res.patronyme} pro={pro} onUnlock={openPaywall} />}
        {field.has && window.RadarChart &&
        <div className="nm-foyer-radar">
            <div className="nm-foyer-radar-k">Le composé du foyer <span className="name-cat-help">— l'équilibre des quatre éléments</span></div>
            {(() => {
              const Radar = window.RadarChart;
              const ELEM_COLOR = { Feu: "#b8502f", Eau: "#4f7a86", Air: "#bd9a40", Terre: "#7a5a39" };
              const max = Math.max(0.001, ...NM.ELEMENTS.map((e) => field.pct[e]));
              const axes = NM.ELEMENTS.map((el) => ({
                label: NM.ELEM_META[el].nom,
                value: field.pct[el] / max,
                color: ELEM_COLOR[el],
                sub: el === field.dominant ? "dominant" : el === field.weakest ? "en retrait" : null,
              }));
              return <div className="nm-radar"><Radar axes={axes} size={250} accent="#7a5a39" fill="rgba(122,90,57,.1)" /></div>;
            })()}
          </div>}
        {field.unresolved.length > 0 &&
        <p className="nm-foyer-note">{field.unresolved.join(", ")} : hors dictionnaire — leur élément reste calculé depuis les lettres.</p>}
      </div>

      {/* bascule d'affichage (2 variantes) */}
      <div className="nm-toolbar">
        <div className="nm-layout-toggle">
          <button className={"nm-seg" + (layout === "cartes" ? " nm-seg-on" : "")} onClick={() => setLayout("cartes")}>Cartes</button>
          <button className={"nm-seg" + (layout === "liste" ? " nm-seg-on" : "")} onClick={() => setLayout("liste")}>Liste</button>
        </div>
        <button className="nm-relancer" onClick={relancer}>↻ En tirer d'autres</button>
      </div>

      {/* suggestions */}
      <div className={"nm-suggests nm-" + layout}>
        {visible.map((cand) => layout === "cartes" ?
        <SuggestCard key={cand.key} cand={cand} saved={isSaved(cand.key)} onSave={keep} onShare={setShare} onFiche={onOpenFiche} /> :
        <SuggestRow key={cand.key} cand={cand} saved={isSaved(cand.key)} onSave={keep} onShare={setShare} onFiche={onOpenFiche} />)}
      </div>

      {!pro && hidden > 0 && <NommageLock hidden={hidden} onUnlock={openPaywall} />}

      {/* ma liste */}
      {noms.length > 0 &&
      <div className="nm-mylist">
          <div className="name-cat-label">Ta liste <span className="name-cat-help">— gardée sur cet appareil</span></div>
          <div className="nm-mylist-items">
            {noms.map((x) =>
          <span className="nm-chip" key={x.key}>
                <ElemDot el={x.elem.split(",")[0].trim()} />
                <b>{x.label}</b><span className="nm-chip-g">{GENRE_LABEL[x.genre]}</span>
                <button className="nm-chip-x" onClick={() => removeNom(x.key)} aria-label="retirer">×</button>
              </span>
          )}
          </div>
        </div>}

      <div className="mirror-note nm-mirror">
        <span>↳</span>
        <span><b>Le hasard propose, vous disposez.</b> Ces prénoms sont des pistes accordées, pas un verdict. Gardez ceux qui font lever quelque chose en vous ; le bon prénom, vous le reconnaîtrez en le disant à voix haute.</span>
      </div>

      <div className="reading-actions nm-bottom">
        <button className="btn-secondary" onClick={() => setPhase("accueil")}>← Changer les prénoms</button>
        <button className="ghost-btn" onClick={relancer}>En tirer d'autres →</button>
      </div>

      {share && window.FicheCard &&
      <window.FicheCard
        word={share.label}
        kindLabel={"Prénom · " + GENRE_LABEL[share.genre]}
        elemParts={share.elemParts}
        gematrie={share.gematrie}
        nombre={share.nombre}
        matiere={share.poids <= 0.4 ? "légère" : share.poids >= 0.6 ? "dense" : "posée"}
        sub={share.origine && share.sens ? share.origine + " · " + share.sens : null}
        line={share.piste || share.why}
        onClose={() => setShare(null)} />}
    </div>);

}

window.NommageSpace = NommageSpace;