// EDITOR — Wizard step-by-step contribution form

const DRAFT_KEY = "herbier:draft";
const DEFAULT_DRAFT = {
  nom: "", latin: "", famille: "", auteur: "", hauteur: "",
  contributeur: "",
  description: "", habitat: "",
  comestible: false, comestibleDetail: "",
  medicinal: false, medicinalDetail: "",
  bioindic: false, bioindicDetail: "",
  histoire: "", symbolique: "", precautions: "", notes: "",
  floraison: [],
  origine: [],   // multi-choix : "Sauvage" et/ou "Cultivée" (dimension pratique,
                 // distincte du `statut` scientifique Indigène/Naturalisée/etc.)
  jardins: [],
  photos: {},
  voirAussi: [], // tableau d'ids de fiches liées (cross-références "Voir aussi")
  voirAussiTitre: "", // sous-titre optionnel de la section Voir aussi (ex. "Pôle calmants & digestifs aromatiques")
};

function ficheToWizard(fiche) {
  if (!fiche) return DEFAULT_DRAFT;
  return {
    ...DEFAULT_DRAFT,
    nom: fiche.nom || "",
    latin: fiche.latin || "",
    famille: fiche.famille || "",
    auteur: fiche.auteur || "",
    hauteur: fiche.hauteur || "",
    contributeur: "",
    description: fiche.morphologie || "",
    habitat: fiche.habitat || "",
    histoire: fiche.histoire || "",
    symbolique: fiche.symbolique || "",
    precautions: fiche.precautions || "",
    notes: fiche.notes || "",
    floraison: Array.isArray(fiche.floraison) ? fiche.floraison : [],
    origine: Array.isArray(fiche.origine) ? fiche.origine : [],
    jardins: Array.isArray(fiche.jardins) ? fiche.jardins.map(j => typeof j === "string" ? j : j.nom).filter(Boolean) : [],
    photos: fiche.photos && typeof fiche.photos === "object" ? fiche.photos : {},
    photoDefault: fiche.photoDefault || null,
    voirAussi: Array.isArray(fiche.voirAussi) ? fiche.voirAussi.filter(x => typeof x === "string") : [],
    voirAussiTitre: typeof fiche.voirAussiTitre === "string" ? fiche.voirAussiTitre : "",
    comestible: !!fiche.comestibilite,
    comestibleDetail: (fiche.comestibilite && fiche.comestibilite.detail) || "",
    medicinal: !!fiche.medicinal,
    medicinalDetail: (fiche.medicinal && fiche.medicinal.detail) || "",
    bioindic: !!fiche.bioindication,
    bioindicDetail: typeof fiche.bioindication === "string" ? fiche.bioindication : "",
  };
}

function Editor({ setRoute, setPlantId, editId }) {
  const auth = window.useAuth ? window.useAuth() : { user: null, loading: false };
  const [step, setStep] = React.useState(0);
  const isMobile = useMobile();
  const [data, setData] = React.useState(() => {
    if (editId) return DEFAULT_DRAFT;
    try {
      const raw = localStorage.getItem(DRAFT_KEY);
      if (raw) {
        const parsed = JSON.parse(raw);
        return { ...DEFAULT_DRAFT, ...parsed };
      }
    } catch {}
    return DEFAULT_DRAFT;
  });
  const [loading, setLoading] = React.useState(!!editId);
  const [submitting, setSubmitting] = React.useState(false);
  const [submitError, setSubmitError] = React.useState(null);
  // Phase 2 : si la soumission part en pending (contributeur), on stocke
  // ici les infos pour afficher un écran de confirmation au lieu de
  // rediriger vers la fiche (qui n'a pas été modifiée).
  const [submittedAs, setSubmittedAs] = React.useState(null);
  const [originalFiche, setOriginalFiche] = React.useState(null);

  const set = (k, v) => setData(d => ({ ...d, [k]: v }));

  React.useEffect(() => {
    if (!editId) return;
    setLoading(true);
    // On charge en parallèle la fiche (texte) ET les photos (base64) — séparées
    // côté API pour ne pas alourdir les listes. Sans ce double fetch, les slots
    // photos seraient vides à l'ouverture de l'éditeur, et le submit écraserait
    // les photos existantes par les seules nouvelles uploadées.
    Promise.all([
      fetch(`api/get?id=${encodeURIComponent(editId)}`, { cache: "no-store" })
        .then(r => r.ok ? r.json() : null),
      fetch(`api/photos?id=${encodeURIComponent(editId)}`, { cache: "no-store" })
        .then(r => r.ok ? r.json() : {})
        .catch(() => ({})),
    ])
      .then(([fiche, photos]) => {
        if (fiche && !fiche.error) {
          const photoMap = (photos && !photos.error && typeof photos === "object") ? photos : {};
          const ficheWithPhotos = { ...fiche, photos: photoMap };
          setOriginalFiche(ficheWithPhotos);
          setData({ ...ficheToWizard(ficheWithPhotos), id: editId });
        }
      })
      .catch(() => {})
      .finally(() => setLoading(false));
  }, [editId]);

  React.useEffect(() => {
    if (editId) return;
    const t = setTimeout(() => {
      try { localStorage.setItem(DRAFT_KEY, JSON.stringify(data)); } catch {}
    }, 400);
    return () => clearTimeout(t);
  }, [data, editId]);

  const submit = async () => {
    setSubmitError(null);
    setSubmitting(true);
    try {
      // Les cases ne gèrent que ces trois usages. On reconstruit ceux-ci, mais
      // on PRÉSERVE les autres valeurs curatées de la fiche d'origine
      // (Mellifère, Aromatique, Tinctoriale, Symbolique, Arbre…) que l'éditeur
      // n'expose pas — sinon une simple ré-sauvegarde les effacerait.
      const MANAGED_USAGES = ["Comestible", "Médicinal", "Bio-indicatrice"];
      const usage = [];
      if (data.comestible) usage.push("Comestible");
      if (data.medicinal) usage.push("Médicinal");
      if (data.bioindic) usage.push("Bio-indicatrice");
      const preservedUsages = (Array.isArray(originalFiche?.usage) ? originalFiche.usage : [])
        .filter(u => !MANAGED_USAGES.includes(u) && !usage.includes(u));
      usage.push(...preservedUsages);

      const labels = {
        p1: "Planche principale", p2: "Fleur / capitule", p3: "Feuille — détail",
        p4: "Tige / port", p5: "Habitat", p6: "Vue complémentaire",
      };
      const galerie = Object.keys(data.photos || {}).map(slotId =>
        ({ id: slotId, label: labels[slotId] || "Photographie" })
      );

      const wizardFields = {
        nom: data.nom, latin: data.latin, auteur: data.auteur,
        famille: data.famille, hauteur: data.hauteur,
        // contributeur volontairement absent : le serveur prend l'identité
        // depuis le JWT de l'utilisateur connecté (cf. api/save.js).
        morphologie: data.description, habitat: data.habitat,
        floraison: data.floraison, origine: data.origine || [],
        histoire: data.histoire, symbolique: data.symbolique,
        precautions: data.precautions, notes: data.notes, photos: data.photos || {},
        usage, galerie,
        voirAussi: Array.isArray(data.voirAussi) ? data.voirAussi : [],
        voirAussiTitre: (data.voirAussiTitre || "").trim(),
      };
      if (data.comestible) wizardFields.comestibilite = { niveau: "Comestible", detail: data.comestibleDetail };
      if (data.medicinal) {
        const composes = (originalFiche && originalFiche.medicinal && originalFiche.medicinal.composes) || [];
        wizardFields.medicinal = { niveau: "Médicinale", detail: data.medicinalDetail, composes };
      }
      if (data.bioindic) wizardFields.bioindication = data.bioindicDetail;
      if (data.jardins && data.jardins.length) {
        const origByNom = new Map(
          (originalFiche && Array.isArray(originalFiche.jardins) ? originalFiche.jardins : [])
            .map(j => [j.nom, j])
        );
        wizardFields.jardins = data.jardins.map(nom => {
          const o = origByNom.get(nom);
          return o ? { ...o, nom } : { nom, lieu: "", parcelles: 1 };
        });
      }

      const payload = {
        ...(originalFiche || {}),
        ...wizardFields,
        ...(editId ? { id: editId } : {}),
      };

      const doFetch = window.authedFetch || fetch;
      const res = await doFetch("api/save", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      const json = await res.json();

      // ── Phase 2 : interpréter la réponse selon le rôle ──
      if (res.status === 409) {
        // Une autre révision pending existe déjà sur cette fiche
        const msg = (json.error || "Une proposition est déjà en cours de modération.") +
          (json.pendingAuthor ? `\nProposée par ${json.pendingAuthor}.` : "");
        setSubmitError(msg);
        setSubmittedAs(null);
        return;
      }
      if (!res.ok || !json.ok) throw new Error(json.error || "Erreur inconnue");

      try { localStorage.removeItem(DRAFT_KEY); } catch {}

      if (json.status === "pending") {
        // Contributeur : proposition envoyée à la modération
        setSubmittedAs({ status: "pending", revisionId: json.revisionId, plantId: json.plantId });
        // On NE redirige PAS sur la fiche (qui n'a pas été modifiée). On affiche
        // un écran de confirmation. L'utilisateur cliquera sur un CTA pour
        // aller voir sa proposition dans /moderation ou retourner à l'accueil.
        return;
      }

      // status === "applied" (moderator+) : comportement historique
      if (window.__reloadPlants) window.__reloadPlants();
      if (setPlantId) setPlantId(json.id);
      setRoute("fiche");
    } catch (err) {
      setSubmitError(err.message || String(err));
    } finally {
      setSubmitting(false);
    }
  };

  const steps = [
    { id: "ident",    label: "Identification",  icon: "I" },
    { id: "morpho",   label: "Morphologie",      icon: "II" },
    { id: "habitat",  label: "Habitat",          icon: "III" },
    { id: "usages",   label: "Usages",           icon: "IV" },
    { id: "histoire", label: "Histoire",         icon: "V" },
    { id: "photos",   label: "Photos",           icon: "VI" },
    { id: "review",   label: "Relecture",        icon: "VII" },
  ];

  const pad = isMobile ? "0 20px" : "0 40px";

  // Guard d'authentification : l'éditeur est interdit aux non-connectés.
  // (Le serveur refuserait de toute façon, mais affichage utilisateur clair.)
  if (!auth.loading && !auth.user) {
    return (
      <main className="page-enter">
        <section style={{ padding: "120px 0", textAlign: "center" }}>
          <div style={{ maxWidth: 560, margin: "0 auto", padding: pad }}>
            <div className="kicker" style={{ marginBottom: 18, color: "var(--moss-deep)" }}>Accès restreint</div>
            <h1 className="h-display" style={{ fontSize: "clamp(40px, 7vw, 64px)", lineHeight: 1, margin: "0 0 24px" }}>
              Connectez-vous pour contribuer.
            </h1>
            <p style={{ fontFamily: "var(--serif)", fontSize: 18, lineHeight: 1.55, color: "var(--ink-soft)", margin: "0 0 32px" }}>
              L'édition et la création de fiches sont réservées aux contributeurs invités du recueil. Cliquez sur « Se connecter » en haut de la page pour recevoir un lien de connexion par email.
            </p>
            <button className="btn" onClick={() => setRoute("home")} style={{ justifyContent: "center" }}>
              Retour à l'accueil
            </button>
          </div>
        </section>
      </main>
    );
  }

  // ── Écran de confirmation après soumission en pending ───────────────
  // Affiché quand un contributeur vient de soumettre une proposition.
  // La fiche live n'a pas été modifiée — pas de redirection automatique
  // vers /fiche. L'utilisateur choisit où aller ensuite.
  if (submittedAs && submittedAs.status === "pending") {
    return (
      <main className="page-enter">
        <section style={{ padding: "100px 0", textAlign: "center" }}>
          <div style={{ maxWidth: 620, margin: "0 auto", padding: pad }}>
            <div className="kicker" style={{ marginBottom: 18, color: "var(--moss-deep)" }}>Proposition envoyée</div>
            <h1 className="h-display" style={{ fontSize: "clamp(38px, 7vw, 60px)", lineHeight: 1, margin: "0 0 24px" }}>
              <span className="h-italic">Merci</span> pour votre contribution.
            </h1>
            <p style={{ fontFamily: "var(--serif)", fontSize: 18, lineHeight: 1.6, color: "var(--ink-soft)", margin: "0 0 22px" }}>
              Votre proposition a été soumise au comité de modération. Elle sera examinée
              dans les prochains jours par un modérateur. Vous serez informé du résultat
              dans votre page <em>Modération</em>.
            </p>
            <p style={{ fontFamily: "var(--serif)", fontSize: 15, fontStyle: "italic", color: "var(--ink-mute)", marginBottom: 36 }}>
              En attendant, la fiche publique reste inchangée. Si vous souhaitez retirer
              ou modifier votre proposition, c'est encore possible depuis votre page
              Modération.
            </p>
            <div style={{ display: "flex", gap: 12, justifyContent: "center", flexWrap: "wrap" }}>
              <button className="btn" onClick={() => setRoute("home")}>Retour à l'accueil</button>
              <button className="btn btn-solid" onClick={() => setRoute("moderation")}>
                Voir mes propositions →
              </button>
            </div>
          </div>
        </section>
      </main>
    );
  }

  return (
    <main className="page-enter">
      {/* Bandeau d'information pour les contributeurs (mode pending) */}
      {auth.user?.role === "contributor" && (
        <div style={{
          background: "rgba(220, 104, 3, 0.08)",
          borderBottom: "1px solid rgba(220, 104, 3, 0.25)",
          padding: isMobile ? "10px 20px" : "12px 40px",
          textAlign: "center",
          fontFamily: "var(--mono)",
          fontSize: 11,
          letterSpacing: ".10em",
          color: "var(--ink-soft)",
        }}>
          MODE CONTRIBUTEUR · vos modifications seront soumises au comité de modération avant publication.
        </div>
      )}

      {/* Header */}
      <section style={{ padding: isMobile ? "32px 0 24px" : "70px 0 50px" }}>
        <div style={{ maxWidth: 1400, margin: "0 auto", padding: pad }}>
          <div className="kicker" style={{ marginBottom: isMobile ? 14 : 22 }}>
            {editId
              ? <>Enrichir une fiche · {data.nom || (loading ? "Chargement…" : editId)}</>
              : <>Nouvelle fiche · Brouillon</>}
          </div>
          <h1 className="h-display" style={{ fontSize: isMobile ? "clamp(38px, 10vw, 60px)" : "clamp(56px, 7.5vw, 92px)", lineHeight: 0.95, margin: isMobile ? "0 0 14px" : "0 0 24px", letterSpacing: "-0.02em" }}>
            {editId
              ? <><span className="h-italic">Enrichir</span> {data.nom || "cette fiche"}.</>
              : <><span className="h-italic">Consigner</span> une plante.</>}
          </h1>
          {!isMobile && (
            <p style={{ fontFamily: "var(--serif)", fontSize: 21, lineHeight: 1.5, color: "var(--ink-soft)", maxWidth: 720, margin: 0 }}>
              {editId
                ? <>Vos ajouts (texte, photos) viennent compléter la fiche existante. Vous serez crédité·e parmi les contributeurs.</>
                : <>Sept étapes guidées pour ouvrir une fiche au recueil. À chaque étape, votre brouillon est sauvegardé.</>}
            </p>
          )}
        </div>
      </section>

      {/* Stepper */}
      <section style={{ borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)", padding: isMobile ? "0" : "30px 0", background: "var(--tint)" }}>
        <div style={{ maxWidth: 1400, margin: "0 auto", padding: isMobile ? "0" : pad }}>
          {isMobile ? (
            /* Stepper mobile : barre de progression + étape courante */
            <div>
              <div style={{ height: 3, background: "var(--line)" }}>
                <div style={{ height: "100%", background: "var(--moss-deep)", width: `${((step + 1) / steps.length) * 100}%`, transition: "width 300ms var(--ease)" }} />
              </div>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 20px" }}>
                <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                  <span className="h-italic" style={{ fontSize: 18, color: "var(--moss-deep)" }}>{steps[step].icon}</span>
                  <span style={{ fontFamily: "var(--serif)", fontSize: 17 }}>{steps[step].label}</span>
                </div>
                <span style={{ fontFamily: "var(--mono)", fontSize: 10, letterSpacing: ".16em", color: "var(--ink-mute)" }}>
                  {step + 1} / {steps.length}
                </span>
              </div>
              {/* Miniature des étapes cliquables */}
              <div style={{ display: "flex", borderTop: "1px solid var(--line-soft)" }}>
                {steps.map((s, i) => (
                  <button key={s.id} onClick={() => setStep(i)} style={{
                    flex: 1, padding: "10px 0", textAlign: "center",
                    background: i === step ? "var(--moss-deep)" : i < step ? "rgba(45,67,41,0.06)" : "transparent",
                    borderRight: i < steps.length - 1 ? "1px solid var(--line-soft)" : "none",
                    fontFamily: "var(--italic, var(--display))", fontStyle: "italic", fontSize: 13,
                    color: i === step ? "var(--paper)" : i < step ? "var(--moss-deep)" : "var(--ink-mute)",
                    transition: "all 220ms var(--ease)"
                  }}>{s.icon}</button>
                ))}
              </div>
            </div>
          ) : (
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }}>
              {steps.map((s, i) => (
                <button key={s.id} onClick={() => setStep(i)} style={{
                  ...eStyles.stepBtn,
                  color: i === step ? "var(--ink)" : i < step ? "var(--moss-deep)" : "var(--ink-mute)",
                }}>
                  <span style={{
                    ...eStyles.stepNum,
                    background: i === step ? "var(--moss-deep)" : i < step ? "var(--cream)" : "transparent",
                    color: i === step ? "var(--paper)" : i < step ? "var(--moss-deep)" : "var(--ink-mute)",
                    borderColor: i <= step ? "var(--moss-deep)" : "var(--line)",
                  }} className="h-italic">{s.icon}</span>
                  <span style={{ fontFamily: "var(--serif)", fontSize: 16 }}>{s.label}</span>
                  {i < steps.length - 1 && <span style={{ ...eStyles.stepLine, background: i < step ? "var(--moss-deep)" : "var(--line)" }} />}
                </button>
              ))}
            </div>
          )}
        </div>
      </section>

      {/* Body */}
      <section style={{ maxWidth: 1400, margin: isMobile ? "32px auto 0" : "60px auto 0", padding: pad }}>
        <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 360px", gap: isMobile ? 0 : 80, alignItems: "start" }}>
          <div style={{ minHeight: isMobile ? "auto" : 520 }}>
            {loading ? (
              <div style={{ fontFamily: "var(--serif)", fontSize: 18, fontStyle: "italic", color: "var(--ink-mute)", padding: "40px 0" }}>Chargement de la fiche…</div>
            ) : (
              <>
                {step === 0 && <StepIdent data={data} set={set} isMobile={isMobile} authUser={auth.user} />}
                {step === 1 && <StepMorpho data={data} set={set} />}
                {step === 2 && <StepHabitat data={data} set={set} isMobile={isMobile} />}
                {step === 3 && <StepUsages data={data} set={set} />}
                {step === 4 && <StepHistoire data={data} set={set} />}
                {step === 5 && <StepPhotos data={data} set={set} isMobile={isMobile} />}
                {step === 6 && <StepReview data={data} set={set} setRoute={setRoute} authUser={auth.user} />}
              </>
            )}
          </div>

          {/* Aperçu — masqué sur mobile */}
          {!isMobile && (
            <aside style={eStyles.preview}>
              <div className="kicker" style={{ marginBottom: 22 }}>Aperçu en cours</div>
              <Plate
                label="PLANCHE PRINCIPALE"
                aspect="4/5"
                src={
                  // 1. Photo explicitement marquée comme principale (sauf si =="wiki")
                  (data.photoDefault && data.photoDefault !== "wiki" && data.photos && data.photos[data.photoDefault])
                  // 2. Première photo uploadee dans le wizard
                  || (data.photos && data.photos.p1)
                  // 3. Fallback Wikipedia (utile en mode edition d'une fiche existante
                  //    qui n'a pas encore de photo locale uploadee)
                  || (originalFiche && originalFiche.wikipedia && originalFiche.wikipedia.thumb)
                  || null
                }
              />
              <div style={{ padding: "18px 0" }}>
                <h3 className="h-display" style={{ fontSize: 26, lineHeight: 1, margin: "0 0 4px" }}>
                  {data.nom || <span style={{ color: "var(--ink-mute)", fontStyle: "italic" }}>Nom commun…</span>}
                </h3>
                <div className="h-italic" style={{ fontSize: 16, color: "var(--moss-deep)" }}>
                  {data.latin || <span style={{ color: "var(--ink-mute)" }}>Nom latin…</span>}
                </div>
                <div style={{ height: 1, background: "var(--line)", margin: "16px 0" }} />
                <div style={{ display: "flex", flexDirection: "column", gap: 10, fontSize: 13 }}>
                  <PreviewRow k="Famille" v={data.famille} />
                  <PreviewRow k="Hauteur" v={data.hauteur} />
                  <PreviewRow k="Floraison" v={data.floraison.length ? `${data.floraison.length} mois` : ""} />
                  <PreviewRow k="Comestible" v={data.comestible ? "Oui" : ""} />
                  <PreviewRow k="Médicinale" v={data.medicinal ? "Oui" : ""} />
                  <PreviewRow k="Bio-indic." v={data.bioindic ? "Oui" : ""} />
                  <PreviewRow k="Photos" v={Object.keys(data.photos || {}).length ? `${Object.keys(data.photos).length}` : ""} />
                </div>
              </div>
            </aside>
          )}
        </div>

        {/* Navigation — label à gauche en absolu, boutons d'action centrés visuellement */}
        <div style={{ ...eStyles.nav, marginTop: isMobile ? 40 : 60, padding: isMobile ? "24px 0" : "30px 0", position: "relative", justifyContent: "center" }}>
          {!isMobile && (
            <span style={{
              position: "absolute", left: 0, top: "50%", transform: "translateY(-50%)",
              fontFamily: "var(--mono)", fontSize: 11, letterSpacing: ".18em",
              color: "var(--ink-mute)", textTransform: "uppercase",
            }}>
              Étape {step + 1} sur {steps.length}
            </span>
          )}
          <div style={{ display: "flex", gap: isMobile ? 8 : 10, alignItems: "center" }}>
            <button className="btn" onClick={() => setStep(Math.max(0, step - 1))} disabled={step === 0} style={{ opacity: step === 0 ? 0.3 : 1 }}>
              <IconArrow size={13} rot={180} /> {!isMobile && "Précédent"}
            </button>
            {/* Mode édition : bouton "Enregistrer" disponible à toutes les étapes
                sauf la dernière (où "Mettre à jour" fait déjà l'enregistrement).
                En mode création (pas d'editId), on conserve le parcours guidé
                du wizard jusqu'à la Relecture pour éviter les fiches incomplètes. */}
            {editId && step < steps.length - 1 && (
              <button
                className="btn"
                onClick={submit}
                disabled={submitting}
                style={{ opacity: submitting ? 0.6 : 1 }}
                title="Enregistrer la fiche maintenant"
                aria-label="Enregistrer"
              >
                {isMobile ? (
                  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M20 6L9 17l-5-5"/>
                  </svg>
                ) : (
                  <>{submitting ? "Envoi…" : "Enregistrer"}</>
                )}
              </button>
            )}
            {step < steps.length - 1 ? (
              <button className="btn btn-solid" onClick={() => setStep(Math.min(steps.length - 1, step + 1))}>
                {!isMobile && "Suivant"} <IconArrow size={13} />
              </button>
            ) : (
              <button className="btn btn-solid" onClick={submit} disabled={submitting} style={{ opacity: submitting ? 0.6 : 1 }}>
                {submitting ? "Envoi…" : (editId ? "Mettre à jour" : "Soumettre")} <IconArrow size={13} />
              </button>
            )}
          </div>
        </div>

        {submitError && (
          <div style={{
            margin: "20px 0 0", padding: "16px 22px",
            background: "rgba(168,116,77,0.1)", borderLeft: "3px solid var(--rust)",
            fontFamily: "var(--serif)", fontSize: 16, color: "var(--ink-soft)"
          }}>
            <strong style={{ fontWeight: 500, color: "var(--rust)" }}>Échec — </strong>
            {submitError}
          </div>
        )}
      </section>
    </main>
  );
}

function PreviewRow({ k, v }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", gap: 10 }}>
      <span style={{ fontFamily: "var(--mono)", fontSize: 10, letterSpacing: ".14em", color: "var(--ink-mute)", textTransform: "uppercase" }}>{k}</span>
      <span style={{ fontFamily: "var(--serif)", fontSize: 13, color: v ? "var(--ink)" : "var(--ink-mute)", fontStyle: v ? "normal" : "italic" }}>{v || "—"}</span>
    </div>
  );
}

function StepShell({ num, title, intro, children }) {
  return (
    <Reveal>
      <div>
        <div style={{ display: "flex", alignItems: "baseline", gap: 14, marginBottom: 12 }}>
          <span className="h-italic" style={{ fontSize: 28, color: "var(--moss-deep)" }}>{num}</span>
          <h2 className="h-display" style={{ fontSize: "clamp(36px, 7vw, 56px)", lineHeight: 1, margin: 0 }}>{title}</h2>
        </div>
        {intro && <p style={{ fontFamily: "var(--serif)", fontSize: 17, lineHeight: 1.5, color: "var(--ink-soft)", maxWidth: 620, margin: "0 0 32px" }}>{intro}</p>}
        <div style={{ display: "flex", flexDirection: "column", gap: 24 }}>{children}</div>
      </div>
    </Reveal>
  );
}

function StepIdent({ data, set, isMobile, authUser }) {
  return (
    <StepShell num="I" title="Identification" intro="Le binôme latin et la famille suffisent à inscrire une plante au recueil.">
      <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: 24 }}>
        <Field label="Nom commun *" value={data.nom} onChange={(v) => set("nom", v)} placeholder="Ex. Achillée millefeuille" />
        <Field label="Nom latin *" value={data.latin} onChange={(v) => set("latin", v)} placeholder="Ex. Achillea millefolium" italic />
      </div>
      <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: 24 }}>
        <Field label="Famille botanique" value={data.famille} onChange={(v) => set("famille", v)} placeholder="Ex. Astéracées" />
        <Field label="Auteur taxonomique" value={data.auteur} onChange={(v) => set("auteur", v)} placeholder="Ex. L. (Linné)" hint="Optionnel" />
      </div>
      <div>
        <label style={{ display: "block", marginBottom: 6, fontFamily: "var(--mono)", fontSize: 11, letterSpacing: ".14em", textTransform: "uppercase", color: "var(--ink-mute)" }}>
          Contributeur (auto-rempli)
        </label>
        <div style={{
          padding: "11px 14px",
          fontFamily: "var(--serif)", fontSize: 16,
          color: "var(--ink-soft)",
          background: "var(--paper-2, var(--cream))",
          border: "1px solid var(--line-soft)",
          display: "flex", alignItems: "center", gap: 10,
        }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{ color: "var(--moss-deep)" }}>
            <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
            <circle cx="12" cy="7" r="4"/>
          </svg>
          <span>{authUser?.displayName || authUser?.email || "Non connecté"}</span>
        </div>
        <p style={{ fontFamily: "var(--serif)", fontSize: 13, fontStyle: "italic", color: "var(--ink-mute)", margin: "8px 0 0", lineHeight: 1.5 }}>
          Cette identité est attribuée automatiquement à partir de votre compte. Elle apparaîtra dans la liste des contributeurs de la fiche publiée.
        </p>
      </div>
    </StepShell>
  );
}

function StepMorpho({ data, set }) {
  return (
    <StepShell num="II" title="Morphologie" intro="Décrivez la plante comme un botaniste de terrain : port, tige, feuilles, fleurs.">
      <Field label="Hauteur adulte" value={data.hauteur} onChange={(v) => set("hauteur", v)} placeholder="Ex. 30–80 cm" />
      <FieldArea label="Description morphologique *" value={data.description} onChange={(v) => set("description", v)}
        placeholder="Vivace dressée à tige cannelée. Feuilles très divisées, plumeuses…"
        hint="Décrivez de bas en haut — racine, tige, feuilles, inflorescence." />
    </StepShell>
  );
}

function StepHabitat({ data, set, isMobile }) {
  const months = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
  const fullMonths = ["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"];
  const toggle = (m) => set("floraison", data.floraison.includes(m) ? data.floraison.filter(x => x !== m) : [...data.floraison, m]);
  const toggleOrigine = (o) => {
    const current = data.origine || [];
    set("origine", current.includes(o) ? current.filter(x => x !== o) : [...current, o]);
  };
  return (
    <StepShell num="III" title="Habitat & calendrier" intro="Où trouve-t-on cette plante, et quand fleurit-elle ?">
      <FieldArea label="Habitat" value={data.habitat} onChange={(v) => set("habitat", v)} placeholder="Prairies sèches, bords de chemins, friches…" />

      <div className="field">
        <label>Où trouve-t-on la plante ? — cochez l'un, l'autre, ou les deux</label>
        <div style={{ display: "flex", gap: 10, marginTop: 10, flexWrap: "wrap" }}>
          {[
            { id: "Sauvage",  emoji: "🌾", hint: "Prairies, sentiers, friches" },
            { id: "Cultivée", emoji: "🪴", hint: "Jardins, potagers, vergers" },
          ].map(o => {
            const active = (data.origine || []).includes(o.id);
            return (
              <button
                key={o.id}
                onClick={() => toggleOrigine(o.id)}
                style={{
                  flex: "1 1 220px",
                  display: "flex", alignItems: "center", gap: 12,
                  padding: "14px 18px",
                  background: active ? "var(--cream)" : "transparent",
                  border: "1px solid " + (active ? "var(--moss-deep)" : "var(--line)"),
                  borderLeft: "3px solid " + (active ? "var(--moss-deep)" : "var(--line)"),
                  cursor: "pointer", transition: "all 220ms var(--ease)",
                  textAlign: "left",
                }}
              >
                <span style={{
                  width: 22, height: 22, borderRadius: 4,
                  border: "1.5px solid var(--moss-deep)",
                  background: active ? "var(--moss-deep)" : "transparent",
                  display: "grid", placeItems: "center",
                  color: "var(--paper)", fontFamily: "var(--mono)", fontSize: 12,
                  flexShrink: 0,
                }}>{active ? "✓" : ""}</span>
                <span style={{ fontSize: 22 }}>{o.emoji}</span>
                <span style={{ display: "flex", flexDirection: "column", gap: 2 }}>
                  <span className="h-display" style={{ fontSize: 18, color: active ? "var(--ink)" : "var(--ink-soft)" }}>{o.id}</span>
                  <span style={{ fontFamily: "var(--serif)", fontSize: 13, fontStyle: "italic", color: "var(--ink-mute)" }}>{o.hint}</span>
                </span>
              </button>
            );
          })}
        </div>
        <div className="hint">Une plante peut être les deux à la fois (ex : la lavande, sauvage en garrigue ET cultivée).</div>
      </div>

      <div className="field">
        <label>Mois de floraison — cliquez pour sélectionner</label>
        <div style={{ display: "flex", gap: isMobile ? 4 : 6, marginTop: 10 }}>
          {months.map((m, i) => {
            const active = data.floraison.includes(fullMonths[i]);
            return (
              <button key={i} onClick={() => toggle(fullMonths[i])} style={{
                flex: 1, padding: isMobile ? "14px 0" : "18px 0",
                background: active ? "var(--moss-deep)" : "var(--cream)",
                color: active ? "var(--paper)" : "var(--ink-mute)",
                border: "1px solid " + (active ? "var(--moss-deep)" : "var(--line)"),
                fontFamily: "var(--mono)", fontSize: isMobile ? 12 : 14, fontWeight: 600,
                letterSpacing: ".1em", cursor: "pointer", transition: "all 220ms var(--ease)"
              }}>{m}</button>
            );
          })}
        </div>
        <div className="hint">{data.floraison.length || 0} mois sélectionnés</div>
      </div>

      <div className="field">
        <label>Jardins partagés où la plante est cultivée</label>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 10, marginTop: 10 }}>
          {[
            "Jardin Aimé", "Jardin Médicinal", "Syracuse", "Knossos", "Palmyre", "Carré des Aromatiques", "Potager de l'École",
          ].map(j => {
            const active = data.jardins.includes(j);
            return (
              <button key={j} onClick={() => set("jardins", active ? data.jardins.filter(x => x !== j) : [...data.jardins, j])}
                className={`tag ${active ? "tag-active" : ""}`} style={{ cursor: "pointer" }}>
                {active ? "✓ " : "+ "}{j}
              </button>
            );
          })}
        </div>
      </div>
    </StepShell>
  );
}

function StepUsages({ data, set }) {
  return (
    <StepShell num="IV" title="Usages" intro="Trois facettes : la table, le soin, la lecture du sol.">
      <UsageEditor
        title="Comestibilité"
        active={data.comestible} setActive={(v) => set("comestible", v)}
        detail={data.comestibleDetail} setDetail={(v) => set("comestibleDetail", v)}
        placeholder="Jeunes feuilles en salade, fleurs en infusion…"
        accent="var(--olive)"
      />
      <UsageEditor
        title="Vertus médicinales"
        active={data.medicinal} setActive={(v) => set("medicinal", v)}
        detail={data.medicinalDetail} setDetail={(v) => set("medicinalDetail", v)}
        placeholder="Hémostatique, cicatrisante, antispasmodique…"
        accent="var(--moss-deep)"
      />
      <UsageEditor
        title="Bio-indication"
        active={data.bioindic} setActive={(v) => set("bioindic", v)}
        detail={data.bioindicDetail} setDetail={(v) => set("bioindicDetail", v)}
        placeholder="Indique un sol équilibré, calcaire, drainé…"
        accent="var(--terra)"
      />
      <FieldArea label="Précautions / toxicité" value={data.precautions || ""} onChange={(v) => set("precautions", v)}
        placeholder="Allergies possibles, contre-indications, toxicité partielle…" />
      <FieldArea label="Notes" value={data.notes || ""} onChange={(v) => set("notes", v)}
        placeholder="Infos diverses : observations de terrain, anecdotes, sources, remarques de culture…" />
      <VoirAussiPicker
        value={data.voirAussi || []}
        onChange={(v) => set("voirAussi", v)}
        titre={data.voirAussiTitre || ""}
        onTitreChange={(v) => set("voirAussiTitre", v)}
        currentId={data.id || data.latin || ""}
      />
    </StepShell>
  );
}

function VoirAussiPicker({ value = [], onChange, titre = "", onTitreChange, currentId }) {
  const [input, setInput] = React.useState("");
  // Liste de toutes les fiches publiées (sauf la fiche en cours d'édition),
  // récupérée depuis window.PLANTS (chargée au démarrage par Herbier.html).
  const allPlants = React.useMemo(() => {
    const list = Array.isArray(window.PLANTS) ? window.PLANTS : [];
    // Filtre la fiche courante par id ET par latin (cas où l'id n'est pas
    // encore généré côté backend pour une nouvelle fiche).
    return list.filter(pp => pp.id !== currentId && pp.latin !== currentId);
  }, [currentId]);

  const byId = React.useMemo(() => {
    const m = new Map();
    for (const pp of allPlants) m.set(pp.id, pp);
    return m;
  }, [allPlants]);

  const selectedItems = value.map(id => byId.get(id)).filter(Boolean);
  const datalistId = "voir-aussi-options";

  const tryAddFromInput = (raw) => {
    const v = (raw || "").trim();
    if (!v) return false;
    // Match exact sur "Nom · Latin" (format de l'option datalist) OU sur le
    // nom commun seul OU sur le latin seul — souplesse pour l'utilisateur.
    const match = allPlants.find(pp =>
      `${pp.nom} · ${pp.latin}` === v ||
      pp.nom === v ||
      pp.latin === v
    );
    if (match && !value.includes(match.id)) {
      onChange([...value, match.id]);
      setInput("");
      return true;
    }
    return false;
  };

  const handleInput = (e) => {
    const v = e.target.value;
    setInput(v);
    // Tentative auto-add quand l'utilisateur sélectionne dans le datalist
    // (déclenche un onChange avec la valeur exacte de l'option).
    tryAddFromInput(v);
  };

  const handleKeyDown = (e) => {
    if (e.key === "Enter") {
      e.preventDefault();
      tryAddFromInput(input);
    }
  };

  const remove = (id) => onChange(value.filter(x => x !== id));

  return (
    <div style={{ marginTop: 10 }}>
      <label style={{ display: "block", marginBottom: 8, fontFamily: "var(--mono)", fontSize: 11, letterSpacing: ".14em", textTransform: "uppercase", color: "var(--ink-mute)" }}>
        Voir aussi · plantes liées
      </label>
      <p style={{ fontFamily: "var(--serif)", fontSize: 14, fontStyle: "italic", color: "var(--ink-mute)", margin: "0 0 12px", lineHeight: 1.5 }}>
        Lie cette fiche à d'autres plantes du recueil (famille thérapeutique,
        affinités, alternatives…). Affichage en bas de fiche.
      </p>
      <input
        type="text"
        value={titre}
        onChange={(e) => onTitreChange && onTitreChange(e.target.value)}
        placeholder="Titre du regroupement — ex. « Pôle calmants & digestifs aromatiques »"
        style={{
          width: "100%", padding: "8px 12px", fontFamily: "var(--serif)",
          fontStyle: "italic", fontSize: 14, color: "var(--ink-soft)",
          border: "1px solid var(--line-soft)", background: "var(--paper)",
          outline: "none", boxSizing: "border-box", marginBottom: 12,
        }}
      />
      {selectedItems.length > 0 && (
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 10 }}>
          {selectedItems.map(item => (
            <span key={item.id} style={{
              display: "inline-flex", alignItems: "center", gap: 8,
              padding: "5px 8px 5px 12px",
              background: "var(--moss-deep)", color: "var(--paper)",
              fontFamily: "var(--mono)", fontSize: 11, letterSpacing: ".08em",
            }}>
              {item.nom}
              <button
                type="button"
                onClick={() => remove(item.id)}
                aria-label={`Retirer ${item.nom}`}
                style={{
                  background: "rgba(255,255,255,0.18)", color: "var(--paper)",
                  border: 0, width: 18, height: 18, borderRadius: "50%",
                  cursor: "pointer", display: "grid", placeItems: "center",
                  fontSize: 13, lineHeight: 1, padding: 0,
                }}
              >×</button>
            </span>
          ))}
        </div>
      )}
      <input
        list={datalistId}
        value={input}
        onChange={handleInput}
        onKeyDown={handleKeyDown}
        placeholder="Tapez un nom ou nom latin…"
        style={{
          width: "100%", padding: "10px 14px", fontFamily: "var(--serif)",
          fontSize: 15, border: "1px solid var(--line)", background: "var(--paper)",
          outline: "none", boxSizing: "border-box",
        }}
      />
      <datalist id={datalistId}>
        {allPlants
          .filter(pp => !value.includes(pp.id))
          .map(pp => (
            <option key={pp.id} value={`${pp.nom} · ${pp.latin}`} />
          ))}
      </datalist>
    </div>
  );
}

function UsageEditor({ title, active, setActive, detail, setDetail, placeholder, accent }) {
  return (
    <div style={{ padding: 22, background: active ? "var(--cream)" : "transparent", border: "1px solid " + (active ? accent : "var(--line)"), borderLeft: "3px solid " + (active ? accent : "var(--line)"), transition: "all 320ms var(--ease)" }}>
      <label style={{ display: "flex", alignItems: "center", gap: 14, cursor: "pointer", marginBottom: active ? 16 : 0 }}>
        <span style={{
          width: 22, height: 22, borderRadius: 4, border: "1.5px solid " + accent,
          background: active ? accent : "transparent", display: "grid", placeItems: "center",
          color: "var(--paper)", fontFamily: "var(--mono)", fontSize: 12, transition: "all 220ms var(--ease)", flexShrink: 0
        }}>{active ? "✓" : ""}</span>
        <span className="h-display" style={{ fontSize: 24, color: active ? "var(--ink)" : "var(--ink-soft)" }}>{title}</span>
        <input type="checkbox" checked={active} onChange={(e) => setActive(e.target.checked)} style={{ display: "none" }} />
      </label>
      {active && (
        <textarea value={detail} onChange={(e) => setDetail(e.target.value)} placeholder={placeholder}
          style={{ width: "100%", minHeight: 80, fontFamily: "var(--serif)", fontSize: 16, color: "var(--ink)",
            border: "1px solid var(--line-soft)", padding: 14, background: "var(--paper)",
            outline: "none", resize: "vertical", lineHeight: 1.55, boxSizing: "border-box" }} />
      )}
    </div>
  );
}

function StepHistoire({ data, set }) {
  return (
    <StepShell num="V" title="Histoire & symbolique" intro="Mythes, étymologie, usages anciens, anecdotes glanées.">
      <FieldArea label="Histoire" value={data.histoire} onChange={(v) => set("histoire", v)}
        placeholder="Plante des champs de bataille, l'achillée porte le nom du héros…"
        hint="N'hésitez pas à citer vos sources entre crochets — Pline, Dioscoride, herbiers locaux." minHeight={180} />
      <Field label="Symbolique" value={data.symbolique} onChange={(v) => set("symbolique", v)}
        placeholder="Ex. Guérison, courage, divination, protection."
        hint="Mots-clés ou courte phrase résumant la dimension symbolique de la plante." />
    </StepShell>
  );
}

// Délègue à shared.jsx :: compressImage (factorisé pour être réutilisé
// par le QuickPhotoModal de Fiche.jsx). maxDim passé de 1200 à 1500 pour
// un meilleur compromis qualité (utile sur écran retina), quality 0.82.
const fileToDataUrl = (file) => window.compressImage(file, { maxDim: 1500, quality: 0.82 });

function PhotoSlot({ slotId, label, required, currentSrc, onUpload, onClear }) {
  const [over, setOver] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const inputRef = React.useRef(null);

  const handleFile = async (file) => {
    setErr(null);
    if (!file) return;
    if (!/^image\/(png|jpeg|webp|avif)$/i.test(file.type)) {
      setErr("Format accepté : PNG, JPEG, WebP, AVIF.");
      return;
    }
    setBusy(true);
    try {
      const url = await fileToDataUrl(file);
      onUpload(url);
    } catch (e) {
      setErr("Impossible de lire l'image.");
    } finally {
      setBusy(false);
    }
  };

  return (
    <div
      style={{ position: "relative" }}
      onDragEnter={(e) => { e.preventDefault(); e.stopPropagation(); setOver(true); }}
      onDragOver={(e) => { e.preventDefault(); e.stopPropagation(); }}
      onDragLeave={(e) => { e.preventDefault(); e.stopPropagation(); setOver(false); }}
      onDrop={(e) => {
        e.preventDefault(); e.stopPropagation(); setOver(false);
        const f = e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files[0];
        if (f) handleFile(f);
      }}
    >
      <input ref={inputRef} type="file" accept="image/png,image/jpeg,image/webp,image/avif"
        style={{ display: "none" }}
        onChange={(e) => { const f = e.target.files && e.target.files[0]; if (f) handleFile(f); e.target.value = ""; }}
      />
      <div
        onClick={() => inputRef.current && inputRef.current.click()}
        style={{
          aspectRatio: "4/5", cursor: "pointer", position: "relative",
          background: currentSrc ? "transparent" : "var(--cream)",
          border: "1px solid " + (over ? "var(--moss-deep)" : "var(--line)"),
          outline: over ? "2px solid var(--moss-deep)" : "none",
          outlineOffset: "-2px", overflow: "hidden",
          backgroundImage: currentSrc ? "none" :
            "repeating-linear-gradient(45deg, transparent 0 9px, rgba(45,67,41,0.05) 9px 10px)",
          transition: "all 220ms var(--ease)",
        }}
      >
        {currentSrc ? (
          <img src={currentSrc} alt={label}
            style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
        ) : (
          <div style={{
            position: "absolute", inset: 0, display: "flex", flexDirection: "column",
            alignItems: "center", justifyContent: "center", gap: 8, padding: 12, textAlign: "center",
            color: "var(--ink-mute)"
          }}>
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round">
              <rect x="3" y="3" width="18" height="18" rx="2" />
              <circle cx="8.5" cy="8.5" r="1.5" />
              <path d="m21 15-5-5L5 21" />
            </svg>
            <div style={{ fontFamily: "var(--mono)", fontSize: 9, letterSpacing: ".14em", textTransform: "uppercase" }}>
              {busy ? "Traitement…" : label}
            </div>
          </div>
        )}
        {currentSrc && (
          <button type="button" onClick={(e) => { e.stopPropagation(); onClear(); }} title="Retirer"
            style={{
              position: "absolute", top: 6, right: 6, width: 26, height: 26,
              background: "rgba(28,36,27,0.7)", color: "#f1ead9",
              border: 0, borderRadius: "50%", cursor: "pointer",
              display: "grid", placeItems: "center", fontSize: 14
            }}>×</button>
        )}
      </div>
      {required && (
        <span style={{
          position: "absolute", top: 8, left: 8, padding: "3px 8px",
          background: "var(--rust)", color: "var(--paper)", fontFamily: "var(--mono)",
          fontSize: 8, letterSpacing: ".16em", textTransform: "uppercase"
        }}>Requis</span>
      )}
      {err && (
        <div style={{
          position: "absolute", left: 6, bottom: 6, right: 6,
          background: "rgba(255,255,255,0.92)", color: "var(--rust)",
          padding: "4px 8px", fontSize: 11, fontFamily: "var(--mono)"
        }}>{err}</div>
      )}
    </div>
  );
}

function StepPhotos({ data, set, isMobile }) {
  const slots = [
    { id: "p1", label: "PLANCHE PRINCIPALE", req: true },
    { id: "p2", label: "FLEUR / CAPITULE" },
    { id: "p3", label: "FEUILLE — DÉTAIL" },
    { id: "p4", label: "TIGE / PORT" },
    { id: "p5", label: "HABITAT" },
    { id: "p6", label: "EXTRA" },
  ];
  const setPhoto = (slotId, url) => {
    const next = { ...(data.photos || {}) };
    if (url) next[slotId] = url;
    else delete next[slotId];
    set("photos", next);
  };
  return (
    <StepShell num="VI" title="Photographies" intro="Versez vos clichés : planches d'herbier, fleurs, feuilles, habitat.">
      <div style={{ display: "grid", gridTemplateColumns: isMobile ? "repeat(2, 1fr)" : "repeat(3, 1fr)", gap: isMobile ? 10 : 14 }}>
        {slots.map(slot => (
          <PhotoSlot
            key={slot.id}
            slotId={slot.id}
            label={slot.label}
            required={slot.req}
            currentSrc={data.photos && data.photos[slot.id]}
            onUpload={(url) => setPhoto(slot.id, url)}
            onClear={() => setPhoto(slot.id, null)}
          />
        ))}
      </div>
    </StepShell>
  );
}

function StepReview({ data, set, setRoute, authUser }) {
  return (
    <Reveal>
      <div>
        <div style={{ display: "flex", alignItems: "baseline", gap: 14, marginBottom: 12 }}>
          <span className="h-italic" style={{ fontSize: 28, color: "var(--moss-deep)" }}>VII</span>
          <h2 className="h-display" style={{ fontSize: "clamp(36px, 7vw, 56px)", lineHeight: 1, margin: 0 }}>Relecture</h2>
        </div>
        <p style={{ fontFamily: "var(--serif)", fontSize: 17, lineHeight: 1.5, color: "var(--ink-soft)", maxWidth: 620, margin: "0 0 32px" }}>
          Voici un aperçu de la fiche telle qu'elle paraîtra dans le recueil.
        </p>

        <div style={{ padding: "32px 28px", background: "var(--cream)", border: "1px solid var(--line)" }}>
          <div className="kicker" style={{ marginBottom: 14, color: "var(--moss-deep)" }}>Aperçu — Folio en attente</div>
          <h3 className="h-display" style={{ fontSize: "clamp(40px, 8vw, 64px)", lineHeight: 0.95, margin: "0 0 10px" }}>
            {data.nom || "Nom de la plante"}
          </h3>
          <div className="h-italic" style={{ fontSize: 20, color: "var(--moss-deep)", marginBottom: 24 }}>{data.latin || "Genre espèce"} {data.auteur}</div>

          <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 0, border: "1px solid var(--line)", marginBottom: 24 }}>
            {[
              { k: "Famille", v: data.famille || "—" },
              { k: "Hauteur", v: data.hauteur || "—" },
              { k: "Floraison", v: data.floraison.length ? `${data.floraison.length} mois` : "—" },
              { k: "Jardins", v: data.jardins.length || "—" },
            ].map((r, i) => (
              <div key={i} style={{ padding: 14, borderRight: i % 2 === 0 ? "1px solid var(--line)" : "none", borderBottom: i < 2 ? "1px solid var(--line)" : "none" }}>
                <div className="kicker" style={{ marginBottom: 5 }}>{r.k}</div>
                <div style={{ fontFamily: "var(--serif)", fontSize: 16 }}>{r.v}</div>
              </div>
            ))}
          </div>

          <p style={{ fontFamily: "var(--serif)", fontSize: 16, lineHeight: 1.6, color: "var(--ink-soft)" }}>
            {data.description || <em style={{ color: "var(--ink-mute)" }}>Description morphologique non renseignée.</em>}
          </p>
          <p style={{ fontFamily: "var(--serif)", fontSize: 16, lineHeight: 1.6, color: "var(--ink-soft)" }}>
            <strong style={{ fontWeight: 500 }}>Habitat — </strong>
            {data.habitat || <em style={{ color: "var(--ink-mute)" }}>—</em>}
          </p>
          {data.histoire ? (
            <p style={{ fontFamily: "var(--serif)", fontSize: 16, lineHeight: 1.6, color: "var(--ink-soft)", marginTop: 12 }}>
              <strong style={{ fontWeight: 500 }}>Histoire — </strong>{data.histoire}
            </p>
          ) : null}

          <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginTop: 20 }}>
            {data.comestible && <span className="tag tag-active">Comestible</span>}
            {data.medicinal && <span className="tag tag-active">Médicinale</span>}
            {data.bioindic && <span className="tag tag-active">Bio-indicatrice</span>}
          </div>
        </div>

        <div style={{ marginTop: 28 }}>
          <label style={{ display: "block", marginBottom: 6, fontFamily: "var(--mono)", fontSize: 11, letterSpacing: ".14em", textTransform: "uppercase", color: "var(--ink-mute)" }}>
            Contributeur (auto-rempli)
          </label>
          <div style={{
            padding: "11px 14px",
            fontFamily: "var(--serif)", fontSize: 16,
            color: "var(--ink-soft)",
            background: "var(--cream)",
            border: "1px solid var(--line-soft)",
            display: "flex", alignItems: "center", gap: 10,
          }}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{ color: "var(--moss-deep)" }}>
              <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
              <circle cx="12" cy="7" r="4"/>
            </svg>
            <span>{authUser?.displayName || authUser?.email || "Non connecté"}</span>
          </div>
        </div>

        <div style={{ marginTop: 22, padding: 24, background: "rgba(45,67,41,0.06)", borderLeft: "3px solid var(--moss-deep)" }}>
          <div className="kicker" style={{ marginBottom: 10 }}>Engagement de contribution</div>
          <p style={{ fontFamily: "var(--serif)", fontSize: 15, lineHeight: 1.5, color: "var(--ink-soft)", margin: 0 }}>
            En soumettant, je certifie l'exactitude de mes observations.
          </p>
        </div>
      </div>
    </Reveal>
  );
}

function Field({ label, value, onChange, placeholder, hint, italic }) {
  return (
    <div className="field">
      <label>{label}</label>
      <input type="text" value={value} onChange={(e) => onChange(e.target.value)} placeholder={placeholder}
        style={{ fontStyle: italic ? "italic" : "normal" }} />
      {hint && <div className="hint">{hint}</div>}
    </div>
  );
}
function FieldArea({ label, value, onChange, placeholder, hint, minHeight = 110 }) {
  return (
    <div className="field">
      <label>{label}</label>
      <textarea value={value} onChange={(e) => onChange(e.target.value)} placeholder={placeholder} style={{ minHeight }} />
      {hint && <div className="hint">{hint}</div>}
    </div>
  );
}

const eStyles = {
  stepBtn: { display: "flex", alignItems: "center", gap: 12, padding: "8px 0", flex: 1, position: "relative", justifyContent: "flex-start" },
  stepNum: { width: 38, height: 38, borderRadius: "50%", border: "1px solid", display: "grid", placeItems: "center", flex: "none", transition: "all 320ms var(--ease)", fontSize: 16 },
  stepLine: { position: "absolute", right: -8, top: 19, width: 16, height: 1 },
  preview: { position: "sticky", top: 110, padding: 22, background: "var(--cream)", border: "1px solid var(--line)" },
  nav: { borderTop: "1px solid var(--line)", display: "flex", justifyContent: "space-between", alignItems: "center" },
};

Object.assign(window, { Editor });
