// PARCOURS D'IDENTIFICATION — variante IMMERSIVE (Folio clair / Veillée nocturne)
// Portée de la maquette « Clé immersive », rebranchée sur les VRAIES données :
//   - window.PLANTS (86 fiches, couleur brute, floraison en mois, feuille en tableaux)
//   - vraies photos via <Plate>, clic → vraie fiche (setRoute)
// Une question à la fois (8 étapes). Folio par défaut ; Veillée quand le thème
// nocturne est actif (les accents dorés C3 sont adossés à body.theme-nocturne).
(function () {
  const { useState, useMemo } = React;

  // — Normalisation couleur (même table que Identifier.jsx) —
  function norm(s) {
    return (s == null ? "" : String(s)).normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().trim();
  }
  const PALETTE = [
    { key: "jaune", label: "Jaune", sw: "#e0bd3a" },
    { key: "orange", label: "Orange", sw: "#dd8a3c" },
    { key: "rouge", label: "Rouge", sw: "#b5402f" },
    { key: "rose", label: "Rose", sw: "#d98aab" },
    { key: "violet", label: "Violet / mauve", sw: "#8a6bb0" },
    { key: "bleu", label: "Bleu", sw: "#5b7fb0" },
    { key: "vert", label: "Vert", sw: "#7a9750" },
    { key: "blanc", label: "Blanc", sw: "#f4f0e4" },
    { key: "brun", label: "Brun", sw: "#8a6a4a" },
  ];
  const COULEUR_BASE = { "mauve": "violet", "blanc rose": "blanc", "jaune-vert": "jaune", "vert-bleute": "vert", "jaune pale": "jaune", "vert argente": "vert" };
  function baseColor(raw) {
    const n = norm(raw);
    if (!n) return null;
    if (COULEUR_BASE[n]) return COULEUR_BASE[n];
    for (const c of PALETTE) if (n.includes(c.key)) return c.key;
    return null;
  }

  const MOIS_FR = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"];
  const MOIS_AB = ["jan", "fév", "mar", "avr", "mai", "juin", "juil", "août", "sep", "oct", "nov", "déc"];
  function enFleurAuMois(plant, moisNom) {
    const f = plant.floraison;
    if (Array.isArray(f)) return f.includes(moisNom);
    return typeof f === "string" && f.includes(moisNom);
  }

  const TRANCHES = [
    { key: "basse", label: "Basse", hint: "moins de 30 cm", test: (cm) => cm < 30 },
    { key: "moyenne", label: "Moyenne", hint: "30 cm à 1 m", test: (cm) => cm >= 30 && cm <= 100 },
    { key: "haute", label: "Haute", hint: "1 à 3 m", test: (cm) => cm > 100 && cm <= 300 },
    { key: "arbre", label: "Arbre", hint: "plus de 3 m", test: (cm) => cm > 300 },
  ];

  // — Silhouettes de feuilles (chemins « se dessinant », pathLength=100) —
  const FORMES = [
    { key: "lineaire", label: "Linéaire", d: ["M12 2 C13.6 9 13.6 20 12 26 C10.4 20 10.4 9 12 2 Z", "M12 26 L12 30"] },
    { key: "lanceolee", label: "Lancéolée", d: ["M12 2 C16.5 8 16.5 17 12 26 C7.5 17 7.5 8 12 2 Z", "M12 26 L12 30"] },
    { key: "ovale", label: "Ovale", d: ["M12 3 C18 6 18.5 14 12 26 C5.5 14 6 6 12 3 Z", "M12 26 L12 30"] },
    { key: "elliptique", label: "Elliptique", d: ["M12 3 C17 7 17 21 12 26 C7 21 7 7 12 3 Z", "M12 26 L12 30"] },
    { key: "spatulee", label: "Spatulée", d: ["M12 26 C10.8 21 7.5 16 7.5 9.5 C7.5 5.5 9.5 3 12 3 C14.5 3 16.5 5.5 16.5 9.5 C16.5 16 13.2 21 12 26 Z", "M12 26 L12 30"] },
    { key: "cordiforme", label: "Cordiforme", d: ["M12 3 C17.5 6.5 19.5 12 18.5 16.5 C17.5 21 14.8 24 13.2 24 C12.6 24 12.2 23.2 12 22.4 C11.8 23.2 11.4 24 10.8 24 C9.2 24 6.5 21 5.5 16.5 C4.5 12 6.5 6.5 12 3 Z", "M12 23.5 L12 30"] },
    { key: "reniforme", label: "Réniforme", d: ["M13 22 C18 21.5 21 17.5 21 13.5 C21 9 17.5 6.5 12 6.5 C6.5 6.5 3 9 3 13.5 C3 17.5 6 21.5 11 22 L12 20.5 L13 22 Z", "M12 21 L12 30"] },
    { key: "decoupee", label: "Découpée", d: ["M12 4 L12 30", "M12 8 C9 7 7 5.5 6 4 M12 8 C15 7 17 5.5 18 4 M12 13 C9 12 6.5 10.5 5 9.5 M12 13 C15 12 17.5 10.5 19 9.5 M12 18 C9.5 17.5 7 16 5.5 15 M12 18 C14.5 17.5 17 16 18.5 15 M12 23 C10 22.5 8 21.5 7 20.5 M12 23 C14 22.5 16 21.5 17 20.5"], noFill: true },
    { key: "composee", label: "Composée", d: ["M12 5 L12 30", "M12 5 C10 3.5 9 3.5 7.5 4.5 C9 6 10.5 6 12 5 M8 10 C6 9 5 9.5 4.5 11 C6.5 11.8 7.5 11.2 8 10 M16 10 C18 9 19 9.5 19.5 11 C17.5 11.8 16.5 11.2 16 10 M8 16 C6 15 5 15.5 4.5 17 C6.5 17.8 7.5 17.2 8 16 M16 16 C18 15 19 15.5 19.5 17 C17.5 17.8 16.5 17.2 16 16 M8 22 C6 21 5 21.5 4.5 23 C6.5 23.8 7.5 23.2 8 22 M16 22 C18 21 19 21.5 19.5 23 C17.5 23.8 16.5 23.2 16 22"], noFill: true },
    { key: "ecaille-aiguille", label: "Aiguille", d: ["M12 30 L12 5 M12 30 L6.5 9 M12 30 L17.5 9 M12 30 L9 6.5 M12 30 L15 6.5"], noFill: true },
  ];
  const MARGES = [
    { key: "entiere", label: "Entière", d: ["M12 3 C18 6 18.5 14 12 26 C5.5 14 6 6 12 3 Z", "M12 26 L12 30"] },
    { key: "dentee", label: "Dentée", d: ["M12 3 L15 5.5 L14 8 L17 10 L15.5 12.5 L17.5 15 L15.5 17 L16 20 L13.5 22 L12 26 L10.5 22 L8 20 L8.5 17 L6.5 15 L8.5 12.5 L7 10 L10 8 L9 5.5 Z", "M12 26 L12 30"] },
    { key: "crenelee", label: "Crénelée", d: ["M12 3 Q16 4 16.5 7 Q18.5 8.5 17.5 11 Q19 13 17 15.5 Q18 18 15.5 19.5 Q16 22.5 13.5 23 Q13 25.5 12 26 Q11 25.5 10.5 23 Q8 22.5 8.5 19.5 Q6 18 7 15.5 Q5 13 6.5 11 Q5.5 8.5 7.5 7 Q8 4 12 3 Z", "M12 26 L12 30"] },
    { key: "lobee", label: "Lobée", d: ["M12 3 C14 4 15 5.5 14 7 C17 7.5 18 10 16 11.5 C19 12.5 19 16 16.5 16.5 C18 18.5 16.5 21 14 20.5 C14.5 23 13 25 12 26 C11 25 9.5 23 10 20.5 C7.5 21 6 18.5 7.5 16.5 C5 16 5 12.5 8 11.5 C6 10 7 7.5 10 7 C9 5.5 10 4 12 3 Z", "M12 26 L12 30"] },
    { key: "epineuse", label: "Épineuse", d: ["M12 3 L14.5 5.5 L17.5 4.5 L16.2 8 L19.5 9 L16.8 11.2 L19.5 13.5 L16.5 14.5 L18 18 L15 17.8 L15.5 21.5 L13 20.5 L12 26 L11 20.5 L8.5 21.5 L9 17.8 L6 18 L7.5 14.5 L4.5 13.5 L7.2 11.2 L4.5 9 L7.8 8 L6.5 4.5 L9.5 5.5 Z", "M12 26 L12 30"] },
  ];
  const NERVS = [
    { key: "pennee", label: "Pennée", d: ["M12 3 C18 6 18.5 14 12 26 C5.5 14 6 6 12 3 Z", "M12 4.5 L12 24 M12 9 L8.2 12.5 M12 9 L15.8 12.5 M12 14 L8.6 17.5 M12 14 L15.4 17.5 M12 19 L9.5 21.8 M12 19 L14.5 21.8"] },
    { key: "palmee", label: "Palmée", d: ["M12 3 C19 6 19.5 15 12 26 C4.5 15 5 6 12 3 Z", "M12 24 L12 4.5 M12 24 L6.8 9.5 M12 24 L17.2 9.5 M12 24 L8.2 16 M12 24 L15.8 16"] },
    { key: "parallele", label: "Parallèle", d: ["M10 2 C14 9 15 19 12.5 30 C9 21 7.5 10 10 2 Z", "M10.8 4 C13 11 13.8 19 12.6 26 M9.7 5 C11.5 12 12.2 19 11.4 25"] },
  ];
  const lf = (x, y, dir) => `M${x} ${y} c${dir * 2.6} -2 ${dir * 4.6} -1.4 ${dir * 5} 0.8 c${dir * -2.2} 1.8 ${dir * -4.2} 1 ${dir * -5} -0.8 Z`;
  const DISPOS = [
    { key: "alterne", label: "Alterne", d: ["M12 2 L12 30", [lf(12, 8, -1), lf(12, 13, 1), lf(12, 18, -1), lf(12, 23, 1)].join(" ")] },
    { key: "opposee", label: "Opposée", d: ["M12 2 L12 30", [lf(12, 9, -1), lf(12, 9, 1), lf(12, 18, -1), lf(12, 18, 1)].join(" ")] },
    { key: "verticillee", label: "Verticillée", d: ["M12 2 L12 30", [lf(12, 9, -1), lf(12, 9, 1), lf(12, 7, -1), lf(12, 7, 1), lf(12, 20, -1), lf(12, 20, 1), lf(12, 18, -1), lf(12, 18, 1)].join(" ")] },
    { key: "rosette", label: "Rosette", d: ["M12 28 L12 22", [lf(12, 26, -1), lf(12, 26, 1), lf(12, 23.5, -1), lf(12, 23.5, 1), "M12 22 C10.5 18.5 11 16 12 14.5 C13 16 13.5 18.5 12 22 Z"].join(" ")] },
  ];
  const LEAF_DEFS = { forme: FORMES, marge: MARGES, nervation: NERVS, disposition: DISPOS };

  // — Filtrage réel : chaque critère est une valeur unique ; les champs feuille
  //   des fiches sont des tableaux → on teste l'appartenance. —
  const MATCH = {
    couleur: (p, v) => baseColor(p.couleur) === v,
    mois: (p, v) => enFleurAuMois(p, MOIS_FR[v]),
    taille: (p, v) => { const t = TRANCHES.find((x) => x.key === v); return t && typeof p.hMax === "number" ? t.test(p.hMax) : false; },
    forme: (p, v) => !!(p.feuille && Array.isArray(p.feuille.forme) && p.feuille.forme.includes(v)),
    marge: (p, v) => !!(p.feuille && Array.isArray(p.feuille.marge) && p.feuille.marge.includes(v)),
    nervation: (p, v) => !!(p.feuille && Array.isArray(p.feuille.nervation) && p.feuille.nervation.includes(v)),
    disposition: (p, v) => !!(p.feuille && Array.isArray(p.feuille.disposition) && p.feuille.disposition.includes(v)),
  };
  function useIdentify() {
    const plants = window.PLANTS || [];
    const empty = { couleur: null, mois: null, taille: null, forme: null, marge: null, nervation: null, disposition: null };
    const [sel, setSel] = useState(empty);
    const pick = (k, v) => setSel((s) => ({ ...s, [k]: v }));
    const reset = () => setSel(empty);
    const filtered = useMemo(() => plants.filter((p) =>
      Object.entries(sel).every(([k, v]) => v == null || MATCH[k](p, v))
    ).sort((a, b) => a.nom.localeCompare(b.nom, "fr")), [sel, plants.length]);
    const nbActifs = Object.values(sel).filter((v) => v != null).length;
    return { sel, pick, reset, filtered, nbActifs };
  }

  function selLabel(k, v) {
    if (v == null) return null;
    if (k === "couleur") return (PALETTE.find((c) => c.key === v) || {}).label;
    if (k === "mois") return MOIS_FR[v];
    if (k === "taille") return (TRANCHES.find((t) => t.key === v) || {}).label;
    const defs = LEAF_DEFS[k];
    return defs ? (defs.find((f) => f.key === v) || {}).label : null;
  }

  // ---------- Contrôles ----------
  function PetalPicker({ value, onPick, size = 250 }) {
    const [hov, setHov] = useState(null);
    const n = PALETTE.length;
    const shown = hov != null ? PALETTE[hov] : PALETTE.find((c) => c.key === value);
    return (
      <div className="petal-wrap" style={{ width: size }}>
        <svg viewBox="-110 -110 220 220" width={size} height={size} style={{ display: "block", overflow: "visible", maxWidth: "100%" }}>
          {PALETTE.map((c, i) => {
            const active = value === c.key, dim = value != null && !active;
            return (
              <g key={c.key} transform={`rotate(${i * (360 / n)})`} className={`petal ${active ? "petal-on" : ""} ${dim ? "petal-dim" : ""}`}
                onClick={() => onPick(c.key)} onMouseEnter={() => setHov(i)} onMouseLeave={() => setHov(null)}>
                <path d="M 0,-32 C 16,-46 24,-68 0,-100 C -24,-68 -16,-46 0,-32 Z" fill={c.sw}
                  stroke={active ? "var(--moss-deep)" : "rgba(28,36,27,0.35)"} strokeWidth={active ? 2 : 1} />
              </g>
            );
          })}
          <circle cx="0" cy="0" r="27" className="petal-core" onClick={() => onPick(null)}
            fill={value == null ? "var(--moss-deep)" : "var(--cream)"} stroke="var(--moss-deep)" strokeWidth="1" />
          <text x="0" y="1" textAnchor="middle" dominantBaseline="middle"
            style={{ fontFamily: "var(--mono)", fontSize: 7.5, letterSpacing: ".12em", textTransform: "uppercase", pointerEvents: "none", fill: value == null ? "var(--paper)" : "var(--ink-mute)" }}>
            {value == null ? "PEU" : "×"}
          </text>
          {value == null && <text x="0" y="10" textAnchor="middle" style={{ fontFamily: "var(--mono)", fontSize: 7.5, letterSpacing: ".12em", fill: "var(--paper)", pointerEvents: "none" }}>IMPORTE</text>}
        </svg>
        <div className="petal-label">
          {shown ? <><span className="petal-dot" style={{ background: shown.sw }} />{shown.label}</> : <span style={{ opacity: .55 }}>cliquez un pétale</span>}
        </div>
      </div>
    );
  }

  const SAISON_TINT = ["#dfe3e2", "#dfe3e2", "#dce4c6", "#d6e2bc", "#d2e0b2", "#ecdfae", "#eed9a0", "#ecd29a", "#e6cfae", "#e2c9a8", "#dccdb8", "#dfe3e2"];
  function arcPath(a0, a1, r0, r1) {
    const p = (a, r) => [Math.sin(a) * r, -Math.cos(a) * r];
    const [x0, y0] = p(a0, r1), [x1, y1] = p(a1, r1), [x2, y2] = p(a1, r0), [x3, y3] = p(a0, r0);
    const large = a1 - a0 > Math.PI ? 1 : 0;
    return `M ${x0} ${y0} A ${r1} ${r1} 0 ${large} 1 ${x1} ${y1} L ${x2} ${y2} A ${r0} ${r0} 0 ${large} 0 ${x3} ${y3} Z`;
  }
  function SeasonWheel({ value, onPick, count, size = 280 }) {
    const seg = (Math.PI * 2) / 12, gap = 0.016;
    return (
      <div className="wheel-wrap" style={{ width: size }}>
        <svg viewBox="-120 -120 240 240" width={size} height={size} style={{ display: "block", overflow: "visible", maxWidth: "100%" }}>
          {MOIS_FR.map((m, i) => {
            const a0 = i * seg + gap, a1 = (i + 1) * seg - gap, active = value === i, mid = (a0 + a1) / 2;
            const [lx, ly] = [Math.sin(mid) * 93, -Math.cos(mid) * 93];
            let deg = mid * 180 / Math.PI;
            if (deg > 95 && deg < 265) deg += 180;
            return (
              <g key={m} className={`wseg ${active ? "wseg-on" : ""}`} onClick={() => onPick(active ? null : i)}>
                <path d={arcPath(a0, a1, 64, 114)} fill={active ? "var(--moss-deep)" : SAISON_TINT[i]}
                  stroke={active ? "var(--moss-deep)" : "rgba(28,36,27,0.22)"} strokeWidth="0.8" />
                <text x={lx} y={ly} textAnchor="middle" dominantBaseline="middle" transform={`rotate(${deg} ${lx} ${ly})`}
                  style={{ fontFamily: "var(--serif)", fontSize: 10.5, fill: active ? "var(--paper)" : "var(--ink-soft)", pointerEvents: "none" }}>{MOIS_AB[i]}</text>
              </g>
            );
          })}
          <circle r="52" fill="var(--cream)" stroke="var(--line)" strokeWidth="1" onClick={() => onPick(null)} style={{ cursor: "pointer" }} />
          <text y="-8" textAnchor="middle" style={{ fontFamily: "var(--display)", fontSize: 24, fill: "var(--ink)", pointerEvents: "none" }}>{count}</text>
          <text y="10" textAnchor="middle" style={{ fontFamily: "var(--mono)", fontSize: 6.8, letterSpacing: ".16em", fill: "var(--ink-mute)", pointerEvents: "none" }}>
            {value != null ? MOIS_FR[value].toUpperCase() : "TOUTE L'ANNÉE"}
          </text>
          {value != null && <text y="24" textAnchor="middle" onClick={() => onPick(null)} style={{ fontFamily: "var(--mono)", fontSize: 7, letterSpacing: ".1em", fill: "var(--rust)", cursor: "pointer" }}>× EFFACER</text>}
        </svg>
      </div>
    );
  }

  function HeightRuler({ value, onPick, height = 300 }) {
    const zones = [...TRANCHES].reverse();
    const silhouettes = {
      basse: <path d="M4 20 C5 16 5 13 4.5 11 M7 20 C7.5 15 8 13 9 11 M10 20 C10 16 9.5 13 10.5 10 M13 20 C13.5 16 14 14 13 11" />,
      moyenne: <path d="M9 20 L9 8 M9 12 C6.5 11 5 9 4.5 7 M9 12 C11.5 11 13 9 13.5 7 M9 8 C7.5 6.5 7.5 5 9 3.5 C10.5 5 10.5 6.5 9 8" />,
      haute: <path d="M9 20 L9 6 M9 16 C6 15 4.5 13 4 11 M9 16 C12 15 13.5 13 14 11 M9 11 C7 10 6 8.5 5.5 6.5 M9 11 C11 10 12 8.5 12.5 6.5 M9 6 C8 4.5 8 3.5 9 2.5 C10 3.5 10 4.5 9 6" />,
      arbre: <path d="M9 20 L9 12 M9 12 C4.5 12 3 8.5 5 6 C5.5 3 8 2 9.5 3 C12 1.5 14.5 3.5 14 6 C16 8 14.5 12 9 12 Z" />,
    };
    return (
      <div className="ruler-wrap" style={{ height }}>
        <div className="ruler-ticks">{Array.from({ length: 21 }).map((_, i) => <span key={i} className={`tick ${i % 5 === 0 ? "tick-big" : ""}`} />)}</div>
        <div className="ruler-zones">
          {zones.map((t) => {
            const active = value === t.key;
            return (
              <button key={t.key} className={`rzone ${active ? "rzone-on" : ""}`} onClick={() => onPick(active ? null : t.key)}>
                <svg viewBox="0 0 18 22" width="26" height="32" fill="none" stroke="currentColor" strokeWidth="1.1" strokeLinecap="round" strokeLinejoin="round">{silhouettes[t.key]}</svg>
                <span className="rzone-txt"><span className="rzone-l">{t.label}</span><span className="rzone-h">{t.hint}</span></span>
              </button>
            );
          })}
        </div>
        <button className={`peu-importe ${value == null ? "pi-on" : ""}`} onClick={() => onPick(null)} style={{ marginTop: 10 }}>Peu importe</button>
      </div>
    );
  }

  function LeafGrid({ value, onPick, defs, available }) {
    return (
      <div className="leaf-grid">
        {defs.filter((f) => !available || available.has(f.key)).map((f) => {
          const active = value === f.key;
          return (
            <button key={f.key} className={`leafbtn ${active ? "leafbtn-on" : ""}`} onClick={() => onPick(active ? null : f.key)}>
              <svg viewBox="0 0 24 32" width="30" height="40" fill="currentColor" fillOpacity={f.noFill ? 0 : 0.13} stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round">
                {f.d.map((d, i) => <path key={i} d={d} pathLength="100" className="draw" fill={i > 0 || f.noFill ? "none" : undefined} />)}
              </svg>
              <span>{f.label}</span>
            </button>
          );
        })}
        <button className={`peu-importe ${value == null ? "pi-on" : ""}`} onClick={() => onPick(null)}>Peu importe</button>
      </div>
    );
  }

  function StepControl({ k, sel, onPick, count, big }) {
    if (k === "couleur") return <PetalPicker value={sel.couleur} onPick={(v) => onPick("couleur", v === sel.couleur ? null : v)} size={big ? 280 : 230} />;
    if (k === "mois") return <SeasonWheel value={sel.mois} onPick={(v) => onPick("mois", v)} count={count} size={big ? 300 : 250} />;
    if (k === "taille") return <HeightRuler value={sel.taille} onPick={(v) => onPick("taille", v)} height={big ? 300 : 260} />;
    const defs = LEAF_DEFS[k];
    if (defs) return <LeafGrid value={sel[k]} onPick={(v) => onPick(k, v)} defs={defs} />;
    return null;
  }

  function Confetti() {
    // Délais/tailles fixes (pas de Math.random : indisponible ici) — variation par index.
    const leaves = Array.from({ length: 20 }).map((_, i) => ({
      left: (i * 53) % 100, delay: (i % 7) * 0.18, dur: 2.8 + (i % 5) * 0.4, rot: (i * 67) % 360,
      hue: ["#7a9750", "#b5402f", "#e0bd3a", "#2d4329", "#dd8a3c"][i % 5], s: 8 + (i % 4) * 2,
    }));
    return (
      <div className="confetti" aria-hidden="true">
        {leaves.map((l, i) => (
          <svg key={i} viewBox="0 0 10 14" width={l.s} height={l.s * 1.4}
            style={{ left: `${l.left}%`, animationDelay: `${l.delay}s`, animationDuration: `${l.dur}s`, transform: `rotate(${l.rot}deg)` }}>
            <path d="M5 1 C8 4 8.5 9 5 13 C1.5 9 2 4 5 1 Z" fill={l.hue} opacity="0.85" />
          </svg>
        ))}
      </div>
    );
  }

  // Planche réelle (vraie photo via <Plate>, clic → fiche).
  function PlateMini({ plant, ghost, big, tilt, onClick, delay = 0 }) {
    const fromWiki = !!plant.thumbFromWikipedia;
    const attribution = fromWiki && plant.latin ? `https://fr.wikipedia.org/wiki/${encodeURIComponent(plant.latin.replace(/ /g, "_"))}` : null;
    return (
      <figure className={`plate-mini ${ghost ? "plate-ghost" : ""} ${big ? "plate-big" : ""}`} style={{ "--tilt": `${tilt}deg`, transitionDelay: `${delay}ms` }} onClick={onClick}>
        <Plate src={plant.thumb || null} frame={false} attribution={attribution} label={(plant.nom || "").toUpperCase()} aspect={big ? "4/3" : "3/4"} />
        <figcaption>
          <span className="plate-fam">{plant.famille}</span>
          <span className="plate-nom">{plant.nom}</span>
          <span className="plate-lat">{plant.latin}</span>
        </figcaption>
      </figure>
    );
  }

  // Table d'herbier : les candidates D'ABORD (planches vivantes), puis les
  // écartées en fantômes dans une section dessous — pas de chasse au trésor.
  // Projecteur + confettis quand il ne reste que 1 à 3 candidates.
  function TableHerbier({ filtered, onOpen, compact }) {
    const plants = window.PLANTS || [];
    const okIds = new Set(filtered.map((p) => p.id));
    const excluded = plants.filter((p) => !okIds.has(p.id));
    const few = filtered.length <= 3 && filtered.length > 0 && excluded.length > 0;
    return (
      <div>
        {few ? (
          <div className="spotlight">
            {filtered.length === 1 && <Confetti />}
            <div className="spot-head">
              <span className="kicker" style={{ color: "var(--moss-deep)" }}>{filtered.length === 1 ? "— Une seule candidate —" : `— Plus que ${filtered.length} candidates —`}</span>
              <h3 className="h-display" style={{ fontSize: compact ? 26 : 36, margin: "8px 0 0" }}>
                {filtered.length === 1 ? <>C'est très probablement <span className="h-italic" style={{ color: "var(--moss-deep)" }}>elle.</span></> : <>Le cercle se <span className="h-italic" style={{ color: "var(--moss-deep)" }}>resserre.</span></>}
              </h3>
            </div>
            <div className={`spot-grid spot-${filtered.length}`}>
              {filtered.map((p, i) => <PlateMini key={p.id} plant={p} big tilt={(i - (filtered.length - 1) / 2) * 2.4} onClick={() => onOpen(p)} />)}
            </div>
          </div>
        ) : (
          <div className={`herbier-table ${compact ? "ht-compact" : ""}`}>
            {filtered.map((p, i) => (
              <PlateMini key={p.id} plant={p} tilt={((i * 37) % 5) - 2} onClick={() => onOpen(p)} delay={(i % 8) * 30} />
            ))}
          </div>
        )}
        {excluded.length > 0 && (
          <>
            <div className="ht-sep">
              <span className="kicker">Écartées par vos indices · {excluded.length}</span>
            </div>
            <div className={`herbier-table ${compact ? "ht-compact" : ""} ht-dimmed`}>
              {excluded.map((p, i) => (
                <PlateMini key={p.id} plant={p} ghost tilt={((i * 37) % 5) - 2} />
              ))}
            </div>
          </>
        )}
      </div>
    );
  }

  const IM_STEPS = [
    { key: "couleur", num: "i", q: <>De quelle <em>couleur</em> est la fleur ?</>, short: "Couleur" },
    { key: "mois", num: "ii", q: <>À quel <em>mois</em> l'avez-vous observée ?</>, short: "Mois" },
    { key: "taille", num: "iii", q: <>Quelle <em>taille</em> fait la plante ?</>, short: "Taille" },
    { key: "forme", num: "iv", q: <>Quelle <em>silhouette</em> de feuille ?</>, short: "Silhouette" },
    { key: "marge", num: "v", q: <>Quel <em>bord</em> de feuille ?</>, short: "Bord" },
    { key: "nervation", num: "vi", q: <>Quelles <em>nervures</em> ?</>, short: "Nervures" },
    { key: "disposition", num: "vii", q: <>Comment les feuilles <em>s'attachent</em>-elles ?</>, short: "Attache" },
    { key: "fin", num: "viii", q: <>Voici les <em>candidates.</em></>, short: "Résultat" },
  ];

  function Trail({ sel, pick, goto }) {
    const crumbs = IM_STEPS.slice(0, 7).map((s, i) => ({ k: s.key, l: selLabel(s.key, sel[s.key]), i })).filter((c) => c.l);
    if (!crumbs.length) return null;
    return (
      <div className="im-trail">
        <span className="kicker">Vos indices ·</span>
        {crumbs.map((c) => (
          <button key={c.k} className="im-crumb" onClick={() => { pick(c.k, null); goto && goto(c.i); }}>{c.l} <span style={{ opacity: .6 }}>×</span></button>
        ))}
      </div>
    );
  }

  // ---------- C1 · LE FOLIO ----------
  function Folio({ goFiche }) {
    const { sel, pick, reset, filtered, nbActifs } = useIdentify();
    const [step, setStep] = useState(0);
    const cur = IM_STEPS[step];
    const next = () => setStep((s) => Math.min(s + 1, IM_STEPS.length - 1));
    const prev = () => setStep((s) => Math.max(s - 1, 0));
    const pickAndGo = (k, v) => { pick(k, v); if (v != null) setTimeout(next, 550); };
    return (
      <div className="cle-immersive c1">
        <div className="c1-folio">
          <div className="c1-corner tl" /><div className="c1-corner br" />
          <div className="c1-pagenum">folio {cur.num} / viii</div>
          <div className="im-dots">
            {IM_STEPS.map((s, i) => (
              <button key={s.key} className={`im-dot ${i === step ? "on" : ""} ${i < step ? "done" : ""}`} onClick={() => setStep(i)} title={s.short}><span>{s.num}</span></button>
            ))}
          </div>
          <div className="c1-stage" key={step}>
            <div className="im-count"><span className="im-count-n">{filtered.length}</span><span className="im-count-l">plante{filtered.length > 1 ? "s" : ""} encore possibles</span></div>
            <h1 className="im-q">{cur.q}</h1>
            <div className="im-control">
              {cur.key === "fin"
                ? <div style={{ width: "100%" }}>
                    <TableHerbier filtered={filtered} onOpen={(p) => goFiche(p.id)} />
                    {nbActifs > 0 && <div style={{ textAlign: "center", marginTop: 24 }}><button className="peu-importe" onClick={() => { reset(); setStep(0); }}>Recommencer le parcours</button></div>}
                  </div>
                : <StepControl k={cur.key} sel={sel} onPick={pickAndGo} count={filtered.length} big />}
            </div>
            <div className="im-nav">
              <button className="im-navbtn" onClick={prev} disabled={step === 0}>← Précédent</button>
              {step < IM_STEPS.length - 1 && <button className="im-navbtn im-skip" onClick={next}>{sel[cur.key] != null ? "Continuer →" : "Je ne sais pas, passer →"}</button>}
            </div>
          </div>
        </div>
        <Trail sel={sel} pick={pick} goto={setStep} />
      </div>
    );
  }

  // ---------- C3 · LA VEILLÉE (thème nocturne) ----------
  function Veillee({ goFiche }) {
    const { sel, pick, reset, filtered, nbActifs } = useIdentify();
    const [step, setStep] = useState(0);
    const cur = IM_STEPS[step];
    const total = (window.PLANTS || []).length;
    const next = () => setStep((s) => Math.min(s + 1, IM_STEPS.length - 1));
    const prev = () => setStep((s) => Math.max(s - 1, 0));
    const pickAndGo = (k, v) => { pick(k, v); if (v != null) setTimeout(next, 550); };
    return (
      <div className="cle-immersive c3">
        <div className="c3-halo" aria-hidden="true" />
        <div className="c3-head">
          <span className="c3-chap">Chapitre {cur.num}</span>
          <div className="c3-bar"><span style={{ width: `${(step / (IM_STEPS.length - 1)) * 100}%` }} /></div>
          <span className="c3-chap">{filtered.length} / {total}</span>
        </div>
        <div className="c3-stage" key={step}>
          <h1 className="im-q c3-q">{cur.q}</h1>
          <div className="c3-lantern">
            {cur.key === "fin"
              ? <div style={{ width: "100%" }}>
                  <TableHerbier filtered={filtered} onOpen={(p) => goFiche(p.id)} />
                  {nbActifs > 0 && <div style={{ textAlign: "center", marginTop: 24 }}><button className="peu-importe" onClick={() => { reset(); setStep(0); }}>Recommencer la veillée</button></div>}
                </div>
              : <StepControl k={cur.key} sel={sel} onPick={pickAndGo} count={filtered.length} big />}
          </div>
          <div className="im-nav">
            <button className="im-navbtn c3-navbtn" onClick={prev} disabled={step === 0}>← Précédent</button>
            {step < IM_STEPS.length - 1 && <button className="im-navbtn c3-skip" onClick={next}>{sel[cur.key] != null ? "Continuer →" : "Je ne sais pas, passer →"}</button>}
          </div>
        </div>
        <Trail sel={sel} pick={pick} goto={setStep} />
      </div>
    );
  }

  // Variante choisie par le thème : nocturne → Veillée, sinon Folio.
  function IdentifierImmersive({ setRoute, setPlantId, theme }) {
    const goFiche = (id) => { setPlantId(id); setRoute("fiche"); };
    return theme === "nocturne" ? <Veillee goFiche={goFiche} /> : <Folio goFiche={goFiche} />;
  }

  window.IdentifierImmersive = IdentifierImmersive;
})();
