// landing_v2.jsx — premium motion-rich landing sections

const { useState: useS2, useEffect: useE2, useRef: useR2 } = React;

function ScrollProgress() {
  useE2(() => {
    const bar = document.querySelector(".scroll-progress");
    const onScroll = () => {
      const h = document.documentElement;
      const pct = (h.scrollTop / (h.scrollHeight - h.clientHeight)) * 100;
      if (bar) bar.style.width = `${pct}%`;
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return <div className="scroll-progress" />;
}

function RevealV2({ children, delay = 0, as: Tag = "div", className = "", ...rest }) {
  const ref = useR2(null);
  const [seen, setSeen] = useS2(false);
  useE2(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setSeen(true); io.unobserve(el); }
    }, { rootMargin: "0px 0px -60px 0px", threshold: 0.12 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return <Tag ref={ref} className={`reveal-v2 ${seen ? "in" : ""} ${className}`} style={{ transitionDelay: `${delay}ms` }} {...rest}>{children}</Tag>;
}

function SplitWords({ text, delayStart = 0, stagger = 60 }) {
  const words = text.split(" ");
  return (
    <React.Fragment>
      {words.map((w, i) => (
        <span key={i} className="word">
          <span style={{ animationDelay: `${delayStart + i * stagger}ms` }}
                dangerouslySetInnerHTML={{ __html: w + (i < words.length - 1 ? "&nbsp;" : "") }} />
        </span>
      ))}
    </React.Fragment>
  );
}

function HeroPills() {
  return (
    <div className="hv-pills">
      <div className="hv-pill"><span className="dot" /><span>500+ élèves accompagnés</span></div>
      <div className="hv-pill"><span className="dot" /><span>4.8/5 sur Google</span></div>
      <div className="hv-pill"><span className="dot" /><span>Agréé service à la personne</span></div>
    </div>
  );
}

function HeroFormCard({ openModal }) {
  const [v, setV] = useS2({ prenomParent: "", tel: "", niveau: "" });
  const submit = (e) => { e.preventDefault(); openModal(v); };

  return (
    <form className="hv-form" onSubmit={submit}>
      <div className="hv-form-head">
        <h4>Prenez rendez-vous</h4>
        <span className="badge">● Dispo</span>
      </div>
      <div className="row">
        <input placeholder="Votre prénom" value={v.prenomParent} onChange={(e) => setV({ ...v, prenomParent: e.target.value })} required />
        <input placeholder="Téléphone" type="tel" value={v.tel} onChange={(e) => setV({ ...v, tel: e.target.value })} required />
      </div>
      <select value={v.niveau} onChange={(e) => setV({ ...v, niveau: e.target.value })} required>
        <option value="">Niveau de l'enfant…</option>
        {NIVEAUX.map(n => <option key={n} value={n}>{n}</option>)}
      </select>
      <button type="submit" className="btn btn-accent">
        Prendre rendez-vous <ArrowIcon />
      </button>
      <p className="foot">Rappel sous 2h</p>
      <div className="phone-line">
        ou appelez-nous : <a href={`tel:${PHONE.replace(/\s/g,"")}`}>{PHONE}</a>
      </div>
    </form>
  );
}

function HeroV2({ openModal }) {
  return (
    <section className="hero-v2">
      <div className="hero-v2-bg" />
      <div className="hero-v2-glow" />

      <div className="wrap hero-v2-inner">
        <div>
          <HeroPills />
          <h1 className="hv-headline">
            Les meilleurs étudiants de <span className="accent">grande école</span> pour vos cours particuliers.
          </h1>

          <p className="hv-lead">
            Un matching sur-mesure entre votre enfant et un étudiant de grande école. À Paris, à domicile, sans engagement.
          </p>

          <div className="hv-meta">
            <div className="hv-meta-item">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4 10-10"/></svg>
              Prof trouvé en 24h
            </div>
            <div className="hv-meta-item">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4 10-10"/></svg>
              Sans engagement
            </div>
            <div className="hv-meta-item">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4 10-10"/></svg>
              -50% de crédit d'impôt
            </div>
          </div>
        </div>

        <HeroFormCard openModal={openModal} />
      </div>

    </section>
  );
}

function CtaHeroForm({ openModal, eyebrow, title, lead }) {
  return (
    <section className="section-sm">
      <div className="wrap">
        <div className="cta-hero-card">
          <div className="cta-hero-card-bg" />
          <div className="cta-hero-card-glow" />
          <div className="cta-hero-card-inner">
            <div>
              <HeroPills />
              {eyebrow && <Eyebrow>{eyebrow}</Eyebrow>}
              <h2 className="hv-headline hv-headline-compact" dangerouslySetInnerHTML={{ __html: title }} />
              {lead && <p className="hv-lead" dangerouslySetInnerHTML={{ __html: lead }} />}
            </div>
            <HeroFormCard openModal={openModal} />
          </div>
        </div>
      </div>
    </section>
  );
}

function MarqueeBand() {
  const items = [
    { name: "HEC Paris",        src: "assets/logos/hec.png" },
    { name: "École Polytechnique", src: "assets/logos/polytechnique.png" },
    { name: "CentraleSupélec",  src: "assets/logos/centralesupelec.png" },
    { name: "Sciences Po",      src: "assets/logos/sciencespo.png" },
    { name: "ENS-PSL",          src: "assets/logos/ens.svg" },
    { name: "ESSEC",            src: "assets/logos/essec.png" },
    { name: "ESCP",             src: "assets/logos/escp.png" },
  ];
  const double = [...items, ...items];
  return (
    <section className="marquee" aria-label="Grandes écoles">
      <div className="marquee-track">
        {double.map((it, i) => (
          <span key={i} className="marquee-item">
            <img src={it.src} alt={it.name} className="marquee-logo" />
          </span>
        ))}
      </div>
    </section>
  );
}

function PillarsV2() {
  const pillars = [
    {
      num: "01",
      title: "Des profs de <em>grande école</em>",
      body: "Nos étudiants sortent des meilleures grandes écoles françaises. Ils sont passés par les mêmes bancs il y a peu — du collège au supérieur — et savent exactement ce qui fonctionne.",
      stat: "100% d'étudiants de grande école",
      icon: (<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M12 14l9-5-9-5-9 5 9 5z"/><path d="M12 14l6.16-3.42a12 12 0 01.66 6.48A11.95 11.95 0 0012 20.06a11.95 11.95 0 00-6.82-3 12 12 0 01.66-6.48L12 14z"/></svg>),
    },
    {
      num: "02",
      title: "Un matching <em>sur-mesure</em>",
      body: "Pas d'assignation au hasard. Notre équipe choisit LE prof qui correspond au niveau, aux objectifs et à la personnalité de chacun — du collège à la prépa. Premier cours en 24h.",
      stat: "Premier cours en 24h",
      icon: (<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>),
    },
    {
      num: "03",
      title: "La <em>méthodologie</em> avant tout",
      body: "Apprendre ses leçons ne suffit pas : il faut apprendre à travailler. Nos profs transmettent les méthodes qui les ont menés là où ils sont — celles qui font la différence au brevet, au bac, en prépa, comme à la fac.",
      stat: "Du collège au supérieur",
      icon: (<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M7 9h10M7 13h10M7 17h6"/></svg>),
    },
  ];
  const onMove = (e) => {
    const r = e.currentTarget.getBoundingClientRect();
    e.currentTarget.style.setProperty("--mx", `${e.clientX - r.left}px`);
    e.currentTarget.style.setProperty("--my", `${e.clientY - r.top}px`);
  };
  return (
    <section className="section">
      <div className="wrap">
        <div className="sec-head-v2">
          <div className="left">
            <Eyebrow>Pourquoi Cours Edgar</Eyebrow>
            <h2>Trois piliers qui <em>font la différence</em>.</h2>
          </div>
          <p className="lead" dangerouslySetInnerHTML={{ __html: "Nous vous mettons en relation avec les meilleurs étudiants de grande école. Cours Edgar est la garantie de cours particuliers axés sur la méthodologie et la rigueur." }} />
        </div>
        <RevealV2>
          <div className="pillars-v2">
            {pillars.map((p) => (
              <div key={p.num} className="pillar-v2" onMouseMove={onMove}>
                <div className="pv-head">
                  <div className="pv-num">{p.num}</div>
                  <div className="pv-icon">{p.icon}</div>
                </div>
                <h3 dangerouslySetInnerHTML={{ __html: p.title }} />
                {p.stat && (
                  <div className="pv-stat">
                    <span className="pv-stat-dot" />
                    {p.stat}
                  </div>
                )}
                <p>{p.body}</p>
              </div>
            ))}
          </div>
        </RevealV2>
      </div>
    </section>
  );
}

function MatchingShowcase() {
  const kids = [
    { av: "HU", img: "assets/avatars/hugo.png",   name: "Hugo, 1ère",    sub: "Maths · Prépa concours" },
    { av: "LO", img: "assets/avatars/louise.png", name: "Louise, 4e",    sub: "Français · Méthode" },
    { av: "LE", img: "assets/avatars/leo.png",    name: "Léo, L1 Éco",   sub: "Micro · Stats" },
  ];
  const profs = [
    { av: "CR", img: "assets/avatars/claire.png",  name: "Claire R.",  sub: "Polytechnique" },
    { av: "TB", img: "assets/avatars/thomas.png",  name: "Thomas B.",  sub: "ENS Ulm" },
    { av: "AM", img: "assets/avatars/antoine.png", name: "Antoine M.", sub: "HEC Paris" },
  ];
  const [active, setActive] = useS2(0);
  const [logoFail, setLogoFail] = useS2(false);
  const reduced = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  useE2(() => {
    if (reduced) return;
    const id = setInterval(() => setActive((i) => (i + 1) % kids.length), 2600);
    return () => clearInterval(id);
  }, [reduced]);
  const yPositions = [26, 50, 74];
  return (
    <section className="section">
      <div className="wrap">
        <div className="showcase">
          <RevealV2>
            <Eyebrow>Matching sur-mesure</Eyebrow>
            <h2 className="showcase-title" style={{ marginTop: 12 }}>
              Pas d'algorithme aveugle.<br/><br/>
              <em>Le professeur parfait pour atteindre vos objectifs.</em>
            </h2>
            <p style={{ color: "var(--ink-2)", fontSize: 16, lineHeight: 1.6, maxWidth: 480, marginTop: 20 }}>
              Niveau, objectifs, personnalité, emploi du temps, style d'apprentissage : nous croisons plus de 20 critères pour chaque demande. Puis chaque match est validé à la main, par un humain. Du collège au supérieur, un binôme qui fonctionne dès le premier cours.
            </p>
            <div style={{ display: "flex", gap: 24, marginTop: 28, flexWrap: "wrap" }}>
              <div>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.1em", textTransform: "uppercase" }}>Premier cours sous</div>
                <div style={{ fontFamily: "var(--font-display, var(--font-sans))", fontSize: 36, fontWeight: 600, letterSpacing: "-0.03em", color: "var(--navy)", lineHeight: 1 }}>24h</div>
              </div>
              <div style={{ width: 1, background: "var(--line)" }} />
              <div>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.1em", textTransform: "uppercase" }}>Étudiants satisfaits du match</div>
                <div style={{ fontFamily: "var(--font-display, var(--font-sans))", fontSize: 36, fontWeight: 600, letterSpacing: "-0.03em", color: "var(--navy)", lineHeight: 1 }}>96%</div>
              </div>
            </div>
          </RevealV2>
          <RevealV2 delay={120}>
            <div className="match-viz">
              <svg className="match-lines" viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
                {kids.map((_, i) => (
                  <g key={i} className={`ml-pair ${i === active ? "is-active" : ""}`}>
                    <path d={`M 14 ${yPositions[i]} Q 32 ${yPositions[i]}, 50 50`} />
                    <path d={`M 50 50 Q 68 ${yPositions[i]}, 86 ${yPositions[i]}`} />
                  </g>
                ))}
              </svg>
              <div className="match-left">
                {kids.map((k, i) => (
                  <div key={k.av} className={`match-card ${i === active ? "is-active" : ""}`}>
                    <div className="av"><img src={k.img} alt="" /></div>
                    <div className="info"><strong>{k.name}</strong><span>{k.sub}</span></div>
                  </div>
                ))}
              </div>
              <div className={`match-center ${reduced ? "" : "is-pulsing"}`} key={active}>
                {logoFail ? (
                  <div>
                    <div className="mc-n">CE</div>
                    <div className="mc-l">Matching</div>
                  </div>
                ) : (
                  <img className="mc-logo" src="assets/logo/cours-edgar.png" alt="Cours Edgar" onError={() => setLogoFail(true)} />
                )}
              </div>
              <div className="match-right">
                {profs.map((p, i) => (
                  <div key={p.av} className={`match-card ${i === active ? "is-active" : ""}`}>
                    <div className="av"><img src={p.img} alt="" /></div>
                    <div className="info"><strong>{p.name}</strong><span>{p.sub}</span></div>
                  </div>
                ))}
              </div>
            </div>
          </RevealV2>
        </div>
      </div>
    </section>
  );
}

function CountUp({ to, suffix = "", duration = 1400 }) {
  const [val, setVal] = useS2(0);
  const ref = useR2(null);
  useE2(() => {
    const el = ref.current; if (!el) return;
    const target = parseFloat(to);
    const io = new IntersectionObserver(([e]) => {
      if (!e.isIntersecting) return;
      io.disconnect();
      const t0 = performance.now();
      const tick = (t) => {
        const p = Math.min(1, (t - t0) / duration);
        const eased = 1 - Math.pow(1 - p, 3);
        setVal(target * eased);
        if (p < 1) requestAnimationFrame(tick);
      };
      requestAnimationFrame(tick);
    }, { threshold: 0.4 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration]);
  const isFloat = String(to).includes(".");
  const display = isFloat ? val.toFixed(1) : Math.round(val);
  return <span ref={ref}>{display}<span className="suffix">{suffix}</span></span>;
}

// Scroll-scrubbed progress of a section (0 → 1 as the section crosses the viewport).
// Respects prefers-reduced-motion (returns 1 immediately) and hover:none (mobile → returns 1).
function useScrollProgress(ref) {
  const [p, setP] = useS2(0);
  const rafRef = useR2(null);
  useE2(() => {
    const el = ref.current; if (!el) return;
    const reduced = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced) { setP(1); return; }

    const update = () => {
      rafRef.current = null;
      const rect = el.getBoundingClientRect();
      const vh = window.innerHeight;
      // 0 when section just enters from bottom (rect.top == vh)
      // 1 when section just exits from top (rect.bottom == 0)
      const raw = (vh - rect.top) / (vh + rect.height);
      setP(Math.max(0, Math.min(1, raw)));
    };
    const onScroll = () => {
      if (rafRef.current != null) return;
      rafRef.current = requestAnimationFrame(update);
    };
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) {
        window.addEventListener("scroll", onScroll, { passive: true });
        update();
      } else {
        window.removeEventListener("scroll", onScroll);
      }
    }, { rootMargin: "200px 0px 200px 0px" });
    io.observe(el);
    return () => {
      io.disconnect();
      window.removeEventListener("scroll", onScroll);
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
    };
  }, []);
  return p;
}

// --- Bulletin scolaire animé ----------------------------------------------
// Les notes montent en temps réel au scroll. Pour swap vers un vrai bulletin
// anonymisé : changer les valeurs ci-dessous. Rien d'autre à toucher.
const BULLETIN_GRADES = [
  { matiere: "Mathématiques",   t1: 12.0, t2: 17.5 },
  { matiere: "Physique-Chimie", t1: 13.0, t2: 17.0 },
  { matiere: "SVT",             t1: 13.5, t2: 17.5 },
];
const BULLETIN_MOY = { t1: 12.8, t2: 17.3 };

function BulletinShowcase({ openModal }) {
  const ref = useR2(null);
  const p = useScrollProgress(ref);
  // easeOutCubic pour que le tick ralentisse vers la fin, comme CountUp
  const eased = 1 - Math.pow(1 - p, 3);
  const mix = (a, b) => a + (b - a) * eased;

  const showT2 = p > 0.5;
  const showPos = p > 0.55;
  const showSig = p > 0.85;

  return (
    <section className="section bulletin-showcase">
      <div className="wrap">
        <RevealV2>
          <Eyebrow>Résultats réels</Eyebrow>
          <h2 className="bulletin-h2">Les notes bougent. <em>Vraiment.</em></h2>
          <p className="bulletin-sub">Léa · Première S · après 3 mois avec Cours Edgar</p>
        </RevealV2>

        <div ref={ref} className="bulletin-card" role="img" aria-label="Bulletin scolaire animé : notes qui progressent du trimestre 1 au trimestre 2">
          <div className="bulletin-head">
            <span className="bulletin-label">Bulletin scolaire</span>
            <span className="bulletin-trim">
              <span className={!showT2 ? "on" : ""}>Trimestre 1</span>
              <span className="bulletin-arrow" aria-hidden="true">⟶</span>
              <span className={showT2 ? "on" : ""}>Trimestre 2</span>
            </span>
          </div>

          <div className="bulletin-rows">
            {BULLETIN_GRADES.map((g) => {
              const v = mix(g.t1, g.t2);
              const fill = Math.max(0, Math.min(100, (v / 20) * 100));
              return (
                <div key={g.matiere} className="bulletin-row">
                  <span className="bulletin-matiere">{g.matiere}</span>
                  <div className="bulletin-bar" aria-hidden="true">
                    <div className="bulletin-bar-fill" style={{ width: `${fill}%` }} />
                  </div>
                  <span className="bulletin-grade">
                    {v.toFixed(1)}<span className="bulletin-twenty">/20</span>
                  </span>
                </div>
              );
            })}
          </div>

          <div className="bulletin-moy">
            <span className="bulletin-matiere">Moyenne générale</span>
            <div className="bulletin-bar" aria-hidden="true">
              <div className="bulletin-bar-fill big" style={{ width: `${(mix(BULLETIN_MOY.t1, BULLETIN_MOY.t2) / 20) * 100}%` }} />
            </div>
            <span className="bulletin-grade big">
              {mix(BULLETIN_MOY.t1, BULLETIN_MOY.t2).toFixed(1)}<span className="bulletin-twenty">/20</span>
            </span>
          </div>

          <div className="bulletin-appr-stack">
            <p className={`bulletin-appr neg ${!showPos ? "on" : ""}`}>
              <span className="bulletin-appr-label">T1</span>
              « Des difficultés en mathématiques. Manque de méthode. »
            </p>
            <p className={`bulletin-appr pos ${showPos ? "on" : ""}`}>
              <span className="bulletin-appr-label">T2</span>
              « Progrès remarquables ce trimestre. Méthode solide, à poursuivre. »
            </p>
          </div>

        </div>

        <p className="bulletin-mention">Cas représentatif anonymisé.</p>

        <div className="bulletin-cta">
          <button className="btn btn-accent" onClick={() => openModal({ niveau: "Première", matieres: ["Mathématiques"] })}>
            Rejoindre la liste d'attente
          </button>
        </div>
      </div>
    </section>
  );
}

function StatCard({ prefix, to, suffix, label, fillPct, ghost, delay = 0 }) {
  const ref = useR2(null);
  const [started, setStarted] = useS2(false);
  useE2(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver(([e]) => {
      if (!e.isIntersecting) return;
      io.disconnect();
      setTimeout(() => setStarted(true), delay);
    }, { threshold: 0.8, rootMargin: "-15% 0px -15% 0px" });
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  return (
    <div ref={ref} className={`stat-v2 ${started ? "is-started" : ""}`}>
      <div className="stat-ghost" aria-hidden="true">{ghost}</div>
      <div className="num">
        <span className="prefix">{prefix}</span>
        <CountUp to={to} suffix={suffix} duration={1800} />
      </div>
      <div className="label">{label}</div>
      <div className="stat-bar" aria-hidden="true">
        <div className="stat-bar-fill" style={{ width: started ? `${fillPct}%` : "0%" }} />
      </div>
      <div className="stat-shimmer" aria-hidden="true" />
    </div>
  );
}

function StatsV2() {
  const stats = [
    { to: "98", prefix: "+", suffix: "%",      label: "de familles satisfaites",        fillPct: 98,  ghost: "98" },
    { to: "24", prefix: "",  suffix: " h",     label: "pour trouver votre professeur",  fillPct: 100, ghost: "24" },
    { to: "4",  prefix: "+", suffix: " points", label: "de moyenne",                     fillPct: 85,  ghost: "+4" },
    { to: "4.8", prefix: "", suffix: "/5",     label: "note moyenne sur 587 avis",      fillPct: 96,  ghost: "4.8" },
  ];
  return (
    <section className="section-sm">
      <div className="wrap">
        <RevealV2>
          <div className="stats-v2">
            {stats.map((s, i) => (
              <StatCard key={s.label} {...s} delay={i * 180} />
            ))}
          </div>
        </RevealV2>
      </div>
    </section>
  );
}

function TestimonialsV2() {
  const t = TESTIMONIALS;
  return (
    <section className="section">
      <div className="wrap">
        <div className="sec-head-v2">
          <div className="left">
            <Eyebrow>Paroles de parents</Eyebrow>
            <h2>Ils nous ont <em>fait confiance</em>.</h2>
          </div>
        </div>
        <div className="testimonials-v2">
          <RevealV2>
            <div className="testimonial-v2 hero">
              <div className="testimonial-v2-inner">
                <div className="quote-mark">“</div>
                <div className="quote">Hugo a gagné 4 points en maths en 3 mois. Son professeur de Polytechnique a su lui redonner confiance — et le goût de chercher.</div>
                <div className="author">
                  <div className="avatar"><img src={t[0].img} alt="" /></div>
                  <div className="author-meta">
                    <div className="name">Marie L.</div>
                    <div className="sub">Paris 16e · Maman d'Hugo, 1ère</div>
                  </div>
                </div>
              </div>
            </div>
          </RevealV2>
          {t.slice(1).map((it, i) => (
            <RevealV2 key={it.name} delay={(i + 1) * 100}>
              <div className="testimonial-v2">
                <div className="testimonial-v2-inner">
                  <div className="quote-mark">“</div>
                  <div className="quote">{it.quote}</div>
                  <div className="author">
                    <div className={`avatar ${it.v}`}><img src={it.img} alt="" /></div>
                    <div className="author-meta">
                      <div className="name">{it.name}</div>
                      <div className="sub">{it.sub}</div>
                    </div>
                  </div>
                </div>
              </div>
            </RevealV2>
          ))}
        </div>
      </div>
    </section>
  );
}

function SubjectsV2() {
  const [hovered, setHovered] = useS2(-1);
  const onTilt = (e) => {
    const el = e.currentTarget;
    const r = el.getBoundingClientRect();
    const px = (e.clientX - r.left) / r.width;  // 0..1
    const py = (e.clientY - r.top) / r.height;
    const rotY = (px - 0.5) * 6;   // -3° .. +3°
    const rotX = (0.5 - py) * 6;
    el.style.setProperty("--ry", `${rotY}deg`);
    el.style.setProperty("--rx", `${rotX}deg`);
    el.style.setProperty("--mx", `${px * 100}%`);
    el.style.setProperty("--my", `${py * 100}%`);
  };
  const resetTilt = (e) => {
    const el = e.currentTarget;
    el.style.setProperty("--ry", `0deg`);
    el.style.setProperty("--rx", `0deg`);
  };
  const active = hovered >= 0 ? SUBJECTS[hovered] : null;
  return (
    <section className={`section subjects-section ${hovered >= 0 ? "has-hover" : ""}`}>
      <div className="subjects-megatype" aria-hidden="true">
        <span key={hovered}>{active ? active.name : ""}</span>
      </div>
      <div className="wrap">
        <div className="sec-head-v2">
          <div className="left">
            <Eyebrow>Matières enseignées</Eyebrow>
            <h2>Du collège à la prépa, <em style={{ whiteSpace: "nowrap" }}>toutes matières</em> couvertes.</h2>
          </div>
        </div>
        <RevealV2>
          <div className="subjects-v2">
            {SUBJECTS.map((s, i) => (
              <div
                key={s.name}
                className={`subject-v2 ${hovered === i ? "is-hovered" : hovered >= 0 ? "is-dimmed" : ""}`}
                data-tag={s.tag}
                style={{ "--stagger": `${(Math.floor(i / 4) + (i % 4)) * 60}ms` }}
                onMouseMove={onTilt}
                onMouseEnter={() => setHovered(i)}
                onMouseLeave={(e) => { resetTilt(e); setHovered(-1); }}
              >
                <div className="subject-v2-inner">
                  <h5>{s.name}</h5>
                  <p>{s.note}</p>
                  <div className="n">{String(i + 1).padStart(2, "0")} / 12</div>
                </div>
              </div>
            ))}
          </div>
        </RevealV2>
      </div>
    </section>
  );
}

function HowItWorksV2() {
  const icons = [
    // 1. phone
    <svg key="i1" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.8 19.8 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.12 4.18 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"/></svg>,
    // 2. search / sparkle match
    <svg key="i2" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/><path d="M11 8v6M8 11h6"/></svg>,
    // 3. home / door
    <svg key="i3" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 10.5 12 3l9 7.5"/><path d="M5 9.5V21h14V9.5"/><path d="M10 21v-6h4v6"/></svg>,
    // 4. chart / progress
    <svg key="i4" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 3v18h18"/><path d="M7 15l4-4 3 3 5-6"/></svg>,
  ];
  const sectionRef = useR2(null);
  const [active, setActive] = useS2(0);
  const [inView, setInView] = useS2(false);
  const reduced = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  useE2(() => {
    const el = sectionRef.current; if (!el) return;
    const io = new IntersectionObserver(([e]) => setInView(e.isIntersecting), { threshold: 0.25 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  useE2(() => {
    if (!inView) return;
    if (reduced) { setActive(STEPS.length - 1); return; }
    setActive(0);
    const id = setInterval(() => setActive((i) => (i + 1) % STEPS.length), 3200);
    return () => clearInterval(id);
  }, [inView, reduced]);
  const progress = STEPS.length > 1 ? (active / (STEPS.length - 1)) * 100 : 0;
  return (
    <section className="section" ref={sectionRef}>
      <div className="wrap">
        <div className="sec-head-v2" style={{ textAlign: "center", flexDirection: "column", alignItems: "center" }}>
          <div className="left" style={{ textAlign: "center" }}>
            <Eyebrow>Comment ça marche</Eyebrow>
            <h2>De l'appel au premier cours : <em className="tracking-wide">24 h</em>.</h2>
          </div>
        </div>
        <RevealV2>
          <div className="process-v2">
            <div className="process-track" aria-hidden="true">
              <div className="process-track-fill" style={{ width: `${progress}%` }} />
              <div className="process-packet" style={{ left: `${progress}%` }} />
            </div>
            {STEPS.map((s, i) => (
              <div key={s.title} className={`process-item ${i < active ? "is-done" : ""} ${i === active ? "is-active" : ""}`}>
                <div className="process-dot">
                  <span className="pd-num">{i + 1}</span>
                  <span className="pd-icon">{icons[i]}</span>
                  <span className="pd-check" aria-hidden="true">
                    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4L19 7"/></svg>
                  </span>
                </div>
                <h4>{s.title}</h4>
                <p>{s.body}</p>
              </div>
            ))}
          </div>
        </RevealV2>
      </div>
    </section>
  );
}

function MegaCTA({ openModal }) {
  const [v, setV] = useS2({ prenom: "", tel: "", niveau: "" });
  return (
    <section className="section-sm">
      <div className="wrap">
        <div className="mega-cta">
          <div className="mega-cta-grid">
            <RevealV2>
              <Eyebrow style={{ color: "rgba(255,255,255,0.6)" }}>
                <span style={{ color: "rgba(255,255,255,0.6)" }}>Prêt à commencer</span>
              </Eyebrow>
              <h2 style={{ color: "#fff" }}>
                Trouvons le professeur <em>idéal</em> pour votre enfant.
              </h2>
              <p>Un appel de 10 minutes pour comprendre vos besoins. Un prof proposé sous 24h, issu des meilleures grandes écoles.</p>
              <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
                <a href={`tel:${PHONE.replace(/\s/g,"")}`} className="btn btn-ghost btn-mega" style={{ borderColor: "rgba(255,255,255,0.2)", color: "#fff", background: "rgba(255,255,255,0.04)" }}>
                  <PhoneIcon /> {PHONE}
                </a>
                <span style={{ fontSize: 13, color: "rgba(255,255,255,0.55)" }}>ou →</span>
              </div>
            </RevealV2>
            <RevealV2 delay={120}>
              <div className="mega-cta-form">
                <h4>Être rappelé</h4>
                <div className="row">
                  <input placeholder="Votre prénom" value={v.prenom} onChange={(e) => setV({ ...v, prenom: e.target.value })} />
                  <input placeholder="Téléphone" value={v.tel} onChange={(e) => setV({ ...v, tel: e.target.value })} />
                </div>
                <select value={v.niveau} onChange={(e) => setV({ ...v, niveau: e.target.value })} style={{ width: "100%", marginBottom: 10 }}>
                  <option value="">Niveau de l'enfant…</option>
                  {NIVEAUX.map(n => <option key={n} value={n}>{n}</option>)}
                </select>
                <button className="btn btn-accent" onClick={openModal}>
                  Prendre rendez-vous <ArrowIcon />
                </button>
                <p className="foot">Rappel sous 2h pendant les horaires d'ouverture</p>
              </div>
            </RevealV2>
          </div>
        </div>
      </div>
    </section>
  );
}

function CtaStrip({ eyebrow, title, body, openModal, variant = "primary" }) {
  return (
    <RevealV2>
      <div className={`cta-strip ${variant}`}>
        <div className="cta-strip-inner">
          <div>
            {eyebrow && (
              <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(255,255,255,0.55)", marginBottom: 12 }}>
                {eyebrow}
              </div>
            )}
            <h3 dangerouslySetInnerHTML={{ __html: title }} />
            {body && <p>{body}</p>}
          </div>
          <div className="cta-strip-actions">
            <button className="btn btn-accent" onClick={openModal}>
              Prendre rendez-vous <ArrowIcon />
            </button>
            <a href={`tel:${PHONE.replace(/\s/g,"")}`} className="btn btn-ghost">
              <PhoneIcon /> {PHONE}
            </a>
          </div>
        </div>
      </div>
    </RevealV2>
  );
}

function StickyCTAMobile({ openModal }) {
  return (
    <div className="sticky-cta-mobile" data-cta="sticky-mobile">
      <a href={`tel:${PHONE.replace(/\s/g,"")}`} className="sticky-call" aria-label="Appeler">
        <PhoneIcon />
      </a>
      <button className="btn btn-accent sticky-main" onClick={openModal}>
        Prendre rendez-vous <ArrowIcon />
      </button>
    </div>
  );
}

function ExitIntentPopup({ openModal }) {
  const [shown, setShown] = useS2(false);
  const [visible, setVisible] = useS2(false);
  const [tel, setTel] = useS2("");

  useE2(() => {
    if (shown) return;
    if (typeof window === "undefined") return;
    if (window.innerWidth < 900) return;
    try {
      if (window.sessionStorage && window.sessionStorage.getItem("ce_lead_popup_shown")) {
        setShown(true);
        return;
      }
    } catch (_) {}
    const armAt = Date.now() + 8000;
    const onMouseLeave = (e) => {
      if (shown) return;
      if (Date.now() < armAt) return;
      if (e.clientY > 0) return;
      try {
        if (window.sessionStorage && window.sessionStorage.getItem("ce_lead_popup_shown")) { setShown(true); return; }
      } catch (_) {}
      setShown(true);
      setVisible(true);
      try { window.sessionStorage && window.sessionStorage.setItem("ce_lead_popup_shown", "1"); } catch (_) {}
    };
    document.addEventListener("mouseleave", onMouseLeave);
    return () => document.removeEventListener("mouseleave", onMouseLeave);
  }, [shown]);

  if (!visible) return null;

  const submit = (e) => {
    e.preventDefault();
    setVisible(false);
    openModal({ tel });
  };

  return (
    <div className="exit-intent-overlay" onClick={() => setVisible(false)}>
      <div className="exit-intent-popup" onClick={(e) => e.stopPropagation()} data-cta="exit-intent">
        <button className="exit-close" onClick={() => setVisible(false)} aria-label="Fermer">×</button>
        <div className="hv-pill"><span className="dot" /><span>Rappel sous 2h</span></div>
        <h3>Avant de partir : laissez-nous votre numéro.</h3>
        <p>Un membre de notre équipe vous rappelle en moins de 2h pour cadrer les besoins de votre enfant. Sans engagement.</p>
        <form onSubmit={submit}>
          <input type="tel" placeholder="Votre téléphone" required value={tel} onChange={(e) => setTel(e.target.value)} />
          <button className="btn btn-accent" type="submit">Être rappelé <ArrowIcon /></button>
        </form>
        <p className="exit-foot">Ou appelez-nous : <a href={`tel:${PHONE.replace(/\s/g,"")}`}>{PHONE}</a></p>
      </div>
    </div>
  );
}

function StickyCTADesktop({ openModal }) {
  const [visible, setVisible] = useS2(false);
  const [hidden, setHidden] = useS2(false);
  useE2(() => {
    if (typeof window === "undefined") return;
    const onScroll = () => {
      const y = window.scrollY || window.pageYOffset;
      const max = (document.documentElement.scrollHeight || 0) - window.innerHeight;
      const pct = max > 0 ? y / max : 0;
      setVisible(y > 600 && pct < 0.92);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, []);
  if (hidden) return null;
  return (
    <div className={`sticky-cta-desktop ${visible ? "is-visible" : ""}`} data-cta="sticky-desktop">
      <button className="sticky-cta-close" onClick={() => setHidden(true)} aria-label="Masquer">×</button>
      <button className="btn btn-accent sticky-cta-main" onClick={openModal}>
        Prendre rendez-vous <ArrowIcon />
      </button>
    </div>
  );
}

function ScrollDepthPopup({ openModal }) {
  const [shown, setShown] = useS2(false);
  const [visible, setVisible] = useS2(false);
  const [tel, setTel] = useS2("");
  useE2(() => {
    if (shown) return;
    if (typeof window === "undefined") return;
    try {
      if (window.sessionStorage && window.sessionStorage.getItem("ce_lead_popup_shown")) {
        setShown(true);
        return;
      }
    } catch (_) {}
    const armAt = Date.now() + 6000;
    const onScroll = () => {
      if (shown) return;
      if (Date.now() < armAt) return;
      try {
        if (window.sessionStorage && window.sessionStorage.getItem("ce_lead_popup_shown")) { setShown(true); return; }
      } catch (_) {}
      const y = window.scrollY || window.pageYOffset;
      const max = (document.documentElement.scrollHeight || 0) - window.innerHeight;
      const pct = max > 0 ? y / max : 0;
      if (pct >= 0.8) {
        setShown(true);
        setVisible(true);
        try { window.sessionStorage && window.sessionStorage.setItem("ce_lead_popup_shown", "1"); } catch (_) {}
      }
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, [shown]);
  if (!visible) return null;
  const submit = (e) => {
    e.preventDefault();
    setVisible(false);
    openModal({ tel });
  };
  return (
    <div className="exit-intent-overlay" onClick={() => setVisible(false)}>
      <div className="exit-intent-popup" onClick={(e) => e.stopPropagation()} data-cta="scroll-depth">
        <button className="exit-close" onClick={() => setVisible(false)} aria-label="Fermer">×</button>
        <div className="hv-pill"><span className="dot" /><span>Premier cours en 24h</span></div>
        <h3>Discutez avec notre directeur pédagogique sur vos besoins</h3>
        <p>Laissez-nous votre numéro : un membre de l'équipe vous rappelle sous 2h pour répondre à toutes vos questions. Sans engagement.</p>
        <form onSubmit={submit}>
          <input type="tel" placeholder="Votre téléphone" required value={tel} onChange={(e) => setTel(e.target.value)} />
          <button className="btn btn-accent" type="submit">Être rappelé <ArrowIcon /></button>
        </form>
        <p className="exit-foot">Ou appelez-nous : <a href={`tel:${PHONE.replace(/\s/g,"")}`}>{PHONE}</a></p>
      </div>
    </div>
  );
}

function WhatsAppFloat() {
  const [expanded, setExpanded] = useS2(false);
  const [photoFail, setPhotoFail] = useS2(false);
  const reduced = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  useE2(() => {
    if (reduced) return;
    if (typeof window === "undefined") return;
    try {
      if (window.sessionStorage && window.sessionStorage.getItem("ce_wa_expanded")) return;
    } catch (_) {}
    const t = setTimeout(() => {
      setExpanded(true);
      try { window.sessionStorage && window.sessionStorage.setItem("ce_wa_expanded", "1"); } catch (_) {}
    }, 8000);
    const onScroll = () => setExpanded(false);
    window.addEventListener("scroll", onScroll, { passive: true, once: true });
    return () => {
      clearTimeout(t);
      window.removeEventListener("scroll", onScroll);
    };
  }, [reduced]);
  const href = `https://wa.me/${WHATSAPP.number}?text=${encodeURIComponent(WHATSAPP.defaultMessage)}`;
  return (
    <a
      href={href}
      target="_blank"
      rel="noopener noreferrer"
      className={`whatsapp-float ${expanded ? "is-expanded" : ""}`}
      data-cta="whatsapp-float"
      aria-label={`Parlez à ${WHATSAPP.founderName} sur WhatsApp`}
      onMouseEnter={() => setExpanded(true)}
      onMouseLeave={() => setExpanded(false)}
    >
      <span className="wa-icon" aria-hidden="true">
        <svg width="28" height="28" viewBox="0 0 32 32" fill="currentColor">
          <path d="M16.002 3C9.373 3 4 8.373 4 15.002c0 2.12.555 4.19 1.61 6.01L4 29l8.16-1.58a12.01 12.01 0 005.84 1.49h.01C24.637 28.91 30 23.537 30 16.91 30 8.81 23.627 3 16.002 3zm0 21.82a9.84 9.84 0 01-5.03-1.38l-.36-.21-4.85.94.97-4.73-.23-.37a9.82 9.82 0 01-1.5-5.17c0-5.43 4.42-9.85 9.85-9.85 2.63 0 5.1 1.02 6.95 2.88a9.78 9.78 0 012.88 6.96c0 5.43-4.42 9.93-9.68 9.93zm5.42-7.36c-.3-.15-1.76-.87-2.03-.97-.27-.1-.47-.15-.67.15s-.77.97-.95 1.17c-.17.2-.35.22-.65.08-.3-.15-1.26-.46-2.4-1.48-.88-.78-1.48-1.75-1.66-2.05-.17-.3-.02-.45.13-.6.13-.13.3-.35.45-.53.15-.17.2-.3.3-.5.1-.2.05-.37-.02-.52-.08-.15-.67-1.62-.92-2.22-.24-.58-.48-.5-.67-.51l-.58-.01c-.2 0-.52.07-.79.37s-1.04 1.02-1.04 2.48 1.07 2.88 1.22 3.08c.15.2 2.1 3.2 5.08 4.48.71.3 1.26.48 1.69.62.71.23 1.35.2 1.86.12.57-.08 1.76-.72 2.01-1.42.25-.7.25-1.3.17-1.42-.07-.12-.27-.2-.57-.35z"/>
        </svg>
      </span>
      <span className="wa-body">
        <span className="wa-avatar">
          {photoFail ? (
            <span className="wa-avatar-fallback">E</span>
          ) : (
            <img src={WHATSAPP.founderPhoto} alt="" onError={() => setPhotoFail(true)} />
          )}
          <span className="wa-online" />
        </span>
        <span className="wa-text">
          <span className="wa-line-1">Parlez à {WHATSAPP.founderName}</span>
          <span className="wa-line-2">{WHATSAPP.founderRole} · Répond en &lt;15 min</span>
        </span>
      </span>
    </a>
  );
}

function HomePageV2({ openModal: rawOpenModal }) {
  const openModal = (...args) => {
    try { window.sessionStorage && window.sessionStorage.setItem("ce_lead_popup_shown", "1"); } catch (_) {}
    return rawOpenModal(...args);
  };
  return (
    <React.Fragment>
      <ScrollProgress />
      <HeroV2 openModal={openModal} />
      <MarqueeBand />
      <PillarsV2 />

      <MatchingShowcase />
      <BulletinShowcase openModal={openModal} />
      <HowItWorksV2 />
      <StatsV2 />

      <section className="section-sm">
        <div className="wrap">
          <CtaStrip
            eyebrow="Prof trouvé en 24h"
            title="Un appel de 10 minutes. <em>Un prof idéal.</em>"
            body="Décrivez-nous les besoins de votre enfant — nous trouvons le professeur parfait sous 24h."
            openModal={openModal}
          />
        </div>
      </section>

      <TestimonialsV2 />
      <SubjectsV2 />

      <CtaHeroForm
        openModal={openModal}
        title="Votre enfant mérite un professeur de <em>grande école</em> pour ses cours particuliers."
        lead='Nos étudiants de HEC, Polytechnique, CentraleSupélec… ont à cœur de transmettre leur <span class="methodo">méthodologie</span> à vos enfants.'
      />

      <FAQSection />
      <MegaCTA openModal={openModal} />

      <StickyCTAMobile openModal={openModal} />
      <StickyCTADesktop openModal={openModal} />
      <WhatsAppFloat />
      <ExitIntentPopup openModal={openModal} />
      <ScrollDepthPopup openModal={openModal} />
    </React.Fragment>
  );
}

Object.assign(window, { HomePageV2 });
