// All page sections. const { useState, useEffect, useRef } = React; /* ---------- Reveal hook ---------- */ // Single shared observer attached on mount. Auto-reveals any element with // `.reveal` class on the page — no per-component refs needed. let __revealInit = false; function ensureRevealObserver() { if (__revealInit) return; __revealInit = true; const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } }); }, { threshold: 0.08, rootMargin: "0px 0px -40px 0px" }); const observe = () => document.querySelectorAll(".reveal:not(.in)").forEach(el => io.observe(el)); observe(); // Re-scan on mutations (handles late mounts). const mo = new MutationObserver(observe); mo.observe(document.body, { childList: true, subtree: true }); // Safety: after 1.5s, force-reveal anything still hidden (e.g. if observer missed it). setTimeout(() => document.querySelectorAll(".reveal:not(.in)").forEach(el => { const r = el.getBoundingClientRect(); if (r.top < window.innerHeight && r.bottom > 0) el.classList.add("in"); }), 1500); } function useReveal() { useEffect(() => { ensureRevealObserver(); }, []); // Return null so existing `ref={useReveal()}` calls don't break — they just // won't have a ref attached, which is fine since the global observer handles it. return null; } /* ---------- NAV ---------- */ function Nav({ mode, setMode }) { const [scrolled, setScrolled] = useState(false); const [hidden, setHidden] = useState(false); useEffect(() => { let lastY = window.scrollY; const onScroll = () => { const y = window.scrollY; setScrolled(y > 12); // Hide as soon as we scroll past a small threshold; show again when near top. if (y > 120 && y > lastY) setHidden(true); else if (y < 80) setHidden(false); lastY = y; }; window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); return ( ); } /* ---------- HERO ---------- */ const HERO_HEADLINES = { speed: { eyebrow: "Agence IA française", h1: <>Votre entreprise,
20× plus rapide grâce à l'IA., sub: "Lymorya intègre l'IA et l'automatisation dans les PME et ETI françaises.", }, execute: { eyebrow: "Agence IA française", h1: <>L'IA qui exécute,
vos équipes qui décident., sub: "On déploie des automatisations sur-mesure dans votre stack existante. Vos collaborateurs reprennent la main sur ce qui a vraiment de la valeur.", }, focus: { eyebrow: "Agence IA française", h1: <>Automatisez ce qui
vous ralentit., sub: "Audit, build et déploiement d'agents IA pour PME/ETI françaises. Trois mois pour transformer un service. Garantie résultat ou on continue gratuitement.", }, }; function Hero({ headlineKey, heroVisualVariant }) { const ref = useReveal(); const data = HERO_HEADLINES[headlineKey] || HERO_HEADLINES.speed; return (
{/* Background grid */}

{data.h1}

{data.sub}

Réserver un audit gratuit Voir les cas d'usage
{/* Trust micro-row */}
{["#FF5C28", "#4D8DFF", "#3DDC97"].map((c, i) => ( ))}
+24 PME/ETI accompagnées en 2025
); } /* ---------- CLIENT LOGOS (marquee) ---------- */ function ClientLogos() { const clients = [ { name: "Safran", src: "assets/logos/safran-w.png" }, { name: "Century 21", src: "assets/logos/century21-w.png" }, { name: "Auchan", src: "assets/logos/auchan-w.png" }, { name: "Décathlon", src: "assets/logos/decathlon-w.png" }, { name: "GE Aerospace", src: "assets/logos/ge-aerospace-w.png" }, { name: "Les Saveurs de Maya", src: "assets/logos/saveurs-maya-w.png" }, { name: "Sacem", src: "assets/logos/sacem.png", custom: "sacem" }, ]; // Duplicate for seamless loop const row = [...clients, ...clients, ...clients]; return (
Ils nous font confiance
{row.map((c, i) => { if (c.custom === "sacem") { return (
{ e.currentTarget.style.opacity = 1; }} onMouseLeave={e => { e.currentTarget.style.opacity = 0.55; }} > sacem
); } if (c.custom === "decathlon") { return (
{ e.currentTarget.style.opacity = 1; }} onMouseLeave={e => { e.currentTarget.style.opacity = 0.55; }} >Decathlon
); } return ( {c.name} { e.currentTarget.style.opacity = 1; }} onMouseLeave={e => { e.currentTarget.style.opacity = 0.55; }} /> ); })}
); } /* ---------- LOGO BAR / METRICS ---------- */ function LogoBar() { const ref = useReveal(); const stats = [ { value: "24+", label: "Entreprise accompagnées" }, { value: "184h", label: "Économisées en moyenne / mois" }, { value: "8 sem.", label: "Délai moyen de déploiement" }, { value: "97%", label: "Des workflows en production à 6 mois" }, ]; return (
{stats.map((s, i) => (
{s.value}
{s.label}
))}
); } /* ---------- SECTION HEADER ---------- */ function SectionHead({ eyebrow, title, sub, align = "left" }) { return (
{eyebrow}

{title}

{sub &&

{sub}

}
); } /* ---------- PACKAGES ---------- */ function Packages() { const ref = useReveal(); const pkgs = [ { id: "genese", name: "Genèse", price: "", Icon: IconCompass, tagline: "Audit stratégique IA", desc: "1 à 2 automatisations déployées sur vos processus les plus chronophages.", bullets: ["Audit", "1-2 automatisations", "Support","Guide utilisateur","Documentation"], cta: "Réserver un audit", featured: false, }, { id: "synthese", name: "Synthèse", price: "", Icon: IconWaves, tagline: "Automatisations ponctuelles", desc: "ROI moyen de 5x dès la première année.", bullets: ["Audit", "3-5 automatisations", "Tableau de bord","Intégration de vos outils","Formation d'équipe","Documentation","Support prenium 90 jours","Session d’optimisation"], cta: "Réserver un audit", featured: true, }, { id: "osmose", name: "Osmose", price: "", Icon: IconInfinity, tagline: "Accompagnement continu", desc: "Votre partenaire IA stratégique", bullets: ["Audit IA complet", "Outil IA sur mesure", "Intégration dans l'écosystème","Formation à l'outil","Tableau de bord ROI","Support premium à vie","Optimisations mensuelles"], cta: "Réserver un audit", featured: false, }, ]; return (
{pkgs.map(p => (
{ e.currentTarget.style.transform = "translateY(-4px)"; }} onMouseLeave={e => { e.currentTarget.style.transform = "none"; }} > {p.featured && (
Le plus choisi
)}

{p.name}

{p.tagline}

{p.desc}

    {p.bullets.map(b => (
  • {b}
  • ))}
{p.price}
{p.cta}
))}
); } /* ---------- USE CASES ---------- */ function UseCases() { const ref = useReveal(); const cases = [ { Icon: IconLeads, title: "Qualification de leads automatique", time: "Gain : 12h/sem.", desc: "Chaque lead entrant est scoré, enrichi et routé vers le bon commercial en moins de 60 secondes." }, { Icon: IconChart, title: "Reporting mensuel généré en 2 min", time: "Gain : 8h/mois", desc: "Extraction multi-sources, mise en forme automatique, envoi PDF ou Slack au comité de direction." }, { Icon: IconUserPlus, title: "Onboarding client 100% automatisé", time: "Gain : 4h/client", desc: "De la signature au premier login : contrats, accès, e-mails, formation. Sans intervention humaine." }, { Icon: IconMail, title: "Tri & réponse aux emails support", time: "Gain : 22h/sem.", desc: "Classification, brouillon de réponse, escalade des cas complexes. Vous gardez la main sur le ton." }, { Icon: IconInvoice, title: "Traitement des factures fournisseurs", time: "Gain : 14h/sem.", desc: "OCR, vérification, rapprochement, intégration comptable. Validation finale en 1 clic." }, { Icon: IconPhone, title: "Prise de RDV par agent vocal", time: "Disponible 24/7", desc: "Un agent IA répond, qualifie et planifie sur votre agenda. Avec un naturel troublant." }, ]; return (
{cases.map((c, i) => (
e.currentTarget.style.background = "var(--bg-card-hover)"} onMouseLeave={e => e.currentTarget.style.background = "var(--bg-elev)"} >
{c.time}

{c.title}

{c.desc}

))}
); } /* ---------- METHODE ---------- */ function Methode() { const ref = useReveal(); const steps = [ { n: "01", title: "Audit", time: "3 jours", desc: "On observe vos équipes, on cartographie les process, on chiffre les pertes de temps actuelles." }, { n: "02", title: "Diagnostic", time: "1 semaine", desc: "On vous remet une roadmap priorisée par ROI. Vous validez le périmètre du premier chantier." }, { n: "03", title: "Développement", time: "4–8 semaines", desc: "On code, on teste, on itère avec vos utilisateurs métier. Pas de big bang, des releases hebdomadaires." }, { n: "04", title: "Déploiement", time: "Continu", desc: "Mise en prod, formation, monitoring. On reste à vos côtés ou on passe la main proprement." }, ]; return (
{/* Timeline line */}
{steps.map((s, i) => (
{s.n}
{s.time}

{s.title}

{s.desc}

))}
); } /* ---------- TESTIMONIALS ---------- */ function Testimonials() { const ref = useReveal(); const items = [ { quote: "On a récupéré l'équivalent d'un mi-temps sur le service achats en six semaines. L'équipe Lymorya a compris notre métier avant même de toucher au code.", author: "Camille Bertin", role: "", company: "", }, { quote: "Ce qui change avec Lymorya : ils livrent. On avait testé deux autres prestataires avant, beaucoup de slides, peu de production. Là, premier workflow en prod en quatre semaines.", author: "Yannick Mercier", role: "", company: "", }, { quote: "La phase d'audit à elle seule valait le prix. On a découvert trois process automatisables qu'on n'imaginait pas. ROI atteint au bout de cinq mois.", author: "Lina Aubert", role: "", company: "", }, ]; return (
{items.map((t, i) => (
{[0,1,2,3,4].map(i => )}

« {t.quote} »

{t.author.split(" ").map(n => n[0]).join("")}
{t.author}
{t.role}
))}
); } /* ---------- FAQ ---------- */ function FAQ() { const ref = useReveal(); const [open, setOpen] = useState(0); const items = [ { q: "Combien de temps avant de voir un premier résultat ?", a: "Notre cycle standard est de 4 à 8 semaines entre la signature et le premier workflow en production. La phase d'audit dure 3 jours, le diagnostic 1 semaine, et la construction démarre dès la validation du périmètre. Vous voyez des releases incrémentales chaque semaine — pas de big bang." }, { q: "Faut-il avoir des données « propres » ou un SI moderne ?", a: "Non. Nous travaillons aussi bien avec des Excel partagés qu'avec des ERP modernes. Une partie de notre travail est précisément de structurer ce qui existe pour que l'IA puisse s'y greffer. Si votre stack est vraiment trop fragile, on vous le dira honnêtement." }, { q: "Mes données restent-elles en France ?", a: "Selon votre cas d'usage, nous déployons sur des infrastructures hébergées en France (Scaleway, OVH) ou en UE. Les modèles sensibles peuvent tourner en self-hosted dans votre VPC. Nous signons des DPA conformes RGPD pour chaque mission." }, { q: "Et si l'IA fait une erreur ?", a: "Nos workflows incluent toujours un mécanisme de validation humain pour les décisions à fort impact. Pour le reste, on monitore les taux d'erreur en continu et on déclenche des alertes au-delà de seuils définis avec vous. La fiabilité moyenne en prod sur nos déploiements 2025 est de 99,3%." }, { q: "Vous remplacez nos équipes ?", a: "Non. Nous automatisons les tâches à faible valeur ajoutée pour que vos équipes en fassent plus de celles à forte valeur. Aucun de nos clients n'a réduit ses effectifs après une mission Lymorya — mais beaucoup ont annulé un recrutement prévu." }, { q: "Quelle différence avec un cabinet de conseil ?", a: "On code. Un cabinet vous remet une recommandation, on vous remet un workflow qui tourne en prod. Notre audit débouche systématiquement sur du livrable technique — pas sur un PowerPoint et un devis pour la phase suivante." }, ]; return (
06 — FAQ

Les questions qu'on nous pose souvent.

Vous ne trouvez pas votre réponse ?

Posez-la directement
{items.map((it, i) => (

{it.a}

))}
); } /* ---------- CONTACT FORM ---------- */ function ContactForm() { const [form, setForm] = useState({ name: "", email: "", message: "", consent: false }); const [status, setStatus] = useState("idle"); // idle | sending | sent | error const submitted = status === "sent"; const sending = status === "sending"; const update = (k) => (e) => setForm({ ...form, [k]: e.target.type === "checkbox" ? e.target.checked : e.target.value }); const onSubmit = async (e) => { e.preventDefault(); if (!form.name || !form.email || !form.consent || sending) return; setStatus("sending"); try { const res = await fetch("https://formsubmit.co/ajax/contact@lymorya.com", { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify({ name: form.name, email: form.email, message: form.message, _subject: `Nouvelle demande d'audit — ${form.name}`, _template: "table", _captcha: "false", }), }); const data = await res.json().catch(() => ({})); if (res.ok && (data.success === "true" || data.success === true || res.status === 200)) { setStatus("sent"); } else { setStatus("error"); } } catch { setStatus("error"); } }; const fieldStyle = { width: "100%", padding: "14px 16px", background: "transparent", border: "1px solid var(--border-strong)", borderRadius: 12, color: "var(--text)", fontSize: 15, fontFamily: "inherit", outline: "none", transition: "border-color 0.2s, background 0.2s", }; const labelStyle = { fontSize: 11, fontFamily: '"JetBrains Mono", monospace', color: "var(--text-dim)", letterSpacing: "0.08em", textTransform: "uppercase", marginBottom: 10, display: "block", }; return (
{/* Left: copy */}
Contact

30 minutes.
Zéro engagement.

Réservez votre audit IA gratuit. On analyse vos processus et on vous montre en moyenne combien d'heures et d'argent vous pouvez récupérer.

100 % de valeur. On vous recontacte sous 24 h.

    {[ ["01", "Audit gratuit en visio"], ["02", "Recommandations chiffrées"], ["03", "Réponse sous 24 h"], ].map(([n, l]) => (
  • {n} {l}
  • ))}
{/* Right: form */}
{submitted ? (

Message reçu.

On revient vers vous dans les 24 heures.

) : ( <>
e.target.style.borderColor = "var(--accent)"} onBlur={e => e.target.style.borderColor = "var(--border-strong)"} />
e.target.style.borderColor = "var(--accent)"} onBlur={e => e.target.style.borderColor = "var(--border-strong)"} />