// ============================================================
// MONARCH AVOCAT — Site (React, single-page artifact)
// ============================================================
const { useState, useEffect, useContext, createContext, Fragment, useRef } = React;
const HERO_IMG = "assets/hero.webp";
const CAL_LINK = "hugo-groslambert/diagnostic1h";
const CAL_ORIGIN = "https://cal.eu";
const CAL_EMBED_JS = "https://app.cal.eu/embed/embed.js";
const CAL_URL = `${CAL_ORIGIN}/${CAL_LINK}`;
// Charge le script d'embed Cal une seule fois et l'initialise (popup de réservation).
function useCalEmbed() {
useEffect(() => {
if (window.__monarchCalInit) return;
window.__monarchCalInit = true;
(function (C, A, L) {
let p = function (a, ar) {a.q.push(ar);};
let d = C.document;
C.Cal = C.Cal || function () {
let cal = C.Cal;let ar = arguments;
if (!cal.loaded) {cal.ns = {};cal.q = cal.q || [];d.head.appendChild(d.createElement("script")).src = A;cal.loaded = true;}
if (ar[0] === L) {
const api = function () {p(api, arguments);};
const namespace = ar[1];
api.q = api.q || [];
if (typeof namespace === "string") {cal.ns[namespace] = cal.ns[namespace] || api;p(cal.ns[namespace], ar);p(cal, ["initNamespace", namespace]);} else p(cal, ar);
return;
}
p(cal, ar);
};
})(window, CAL_EMBED_JS, "init");
try {
window.Cal("init", { origin: CAL_ORIGIN });
window.Cal("ui", { hideEventTypeDetails: false, layout: "month_view" });
} catch (e) {}
}, []);
}
// Ouvre la popup Cal ; repli sur l'ouverture d'onglet si le script n'est pas chargé.
function openCal(e) {
if (window.Cal) {
if (e) e.preventDefault();
window.Cal("modal", { calLink: CAL_LINK, config: { layout: "month_view" } });
}
// sinon : le lien href s'ouvre normalement (repli)
}
const C = {
blanc: "#FFFFFF",
albatre: "#FAF9F6",
encre: "#1B1D1C",
ardoise: "#5B7C99",
ardoiseFonce: "#3D5468",
sauge: "#5C6F5C",
saugeFonce: "#48584A",
gris: "#737373",
grisClair: "#9A9A95",
trait: "#E4E1DA"
};
const FONTS = {
serif: "'Fraunces', Georgia, serif",
body: "'Archivo', system-ui, sans-serif",
editorial: "'Spectral', Georgia, serif"
};
// ---------- i18n ----------
const LANGS = ["fr", "en", "es", "it"];
const LangContext = createContext({ lang: "fr", setLang: () => {} });
function useT() {
const { lang } = useContext(LangContext);
return (key) => {
const T = window.MONARCH_TRANSLATIONS || {};
const d = T[lang] || T.fr || {};
return d[key] ?? (T.fr && T.fr[key]) ?? key;
};
}
// Render translated HTML inline. tag defaults to span.
function TT({ k, tag = "span", style, className }) {
const t = useT();
return React.createElement(tag, {
style,
className,
dangerouslySetInnerHTML: { __html: t(k) }
});
}
// Inject Google Fonts + keyframes once
function useFonts() {
useEffect(() => {
const id = "monarch-fonts";
if (document.getElementById(id)) return;
const link = document.createElement("link");
link.id = id;
link.rel = "stylesheet";
link.href =
"https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Spectral:wght@400;500&family=Archivo:wght@300;400;500;600&display=swap";
document.head.appendChild(link);
const style = document.createElement("style");
style.textContent = `
@keyframes monarchRise { from { opacity:0; transform:translateY(22px);} to {opacity:1; transform:translateY(0);} }
@keyframes monarchFade { from { opacity:0;} to {opacity:1;} }
html { scroll-behavior: smooth; box-sizing: border-box; }
*, *::before, *::after { box-sizing: inherit; }
body { margin: 0; overflow-x: hidden; }
.monarch-article-body p { font-size: 18px; line-height: 1.78; color: #2c2e2d; margin: 0 0 22px; }
.monarch-article-body h2 { font-family: 'Fraunces', Georgia, serif; font-size: 26px; font-weight: 500; letter-spacing: -0.01em; margin: 40px 0 14px; }
.monarch-article-body h3 { font-family: 'Fraunces', Georgia, serif; font-size: 21px; font-weight: 500; margin: 32px 0 10px; }
.monarch-article-body ul, .monarch-article-body ol { font-size: 18px; line-height: 1.78; color: #2c2e2d; padding-left: 22px; margin: 0 0 22px; }
.monarch-article-body li { margin-bottom: 8px; }
.monarch-article-body blockquote { font-family: 'Fraunces', Georgia, serif; font-size: 24px; line-height: 1.4; font-weight: 500; color: #3D5468; border-left: 2px solid #5B7C99; margin: 30px 0; padding: 4px 0 4px 26px; }
.monarch-article-body a { color: #3D5468; text-decoration: underline; text-underline-offset: 3px; }
.monarch-article-body img { width: 100%; height: auto; margin: 24px 0; }
/* Template éditorial Publications */
.monarch-article-tpl-body p { font-size: 18px; line-height: 1.8; color: #232524; margin: 0 0 24px; }
.monarch-article-tpl-body h2 { color: #5C6F5C; font-size: clamp(24px,3vw,32px); margin: 48px 0 16px; }
.monarch-article-tpl-body h3 { color: #5C6F5C; font-size: 22px; margin: 34px 0 10px; }
.monarch-article-tpl-body blockquote { font-family: 'Fraunces', Georgia, serif; font-size: 21px; line-height: 1.5; font-weight: 500; color: #48584A; background: #F6F3EA; border-left: 3px solid #5C6F5C; margin: 32px 0; padding: 22px 26px; }
.monarch-article-tpl-body blockquote p { font-family: 'Fraunces', Georgia, serif; font-size: 21px; color: #48584A; margin: 0; }
.monarch-article-tpl-body a { color: #48584A; }
.monarch-article-tpl-body ol { font-size: 18px; line-height: 1.8; color: #232524; padding-left: 24px; margin: 0 0 24px; }
.monarch-article-tpl-body code { font-family: ui-monospace, monospace; font-size: 0.9em; background: #F6F3EA; padding: 2px 6px; border-radius: 3px; }
.monarch-article-tpl-body strong { color: #1B1D1C; }
@media (max-width: 900px) {
.m-article-grid { grid-template-columns: 1fr !important; gap: 0 !important; }
.m-article-toc { display: none !important; }
.m-article-tpl > div { padding-left: 22px !important; padding-right: 22px !important; }
}
/* ----- Menu mobile ----- */
.m-nav-toggle { display: none; }
.m-nav-mobile { display: none; }
.m-refrow-resp {}
/* ======================= RESPONSIVE ======================= */
@media (max-width: 880px) {
.m-wrap { padding-left: 22px !important; padding-right: 22px !important; }
/* header */
.m-nav-desktop { display: none !important; }
.m-nav-toggle { display: inline-flex !important; }
.m-logo-sub { font-size: 8px !important; letter-spacing: 0.2em !important; }
/* hero */
.m-hero { padding-top: 96px !important; }
.m-hero-grid { grid-template-columns: 1fr !important; min-height: 0 !important; }
.m-hero-copy { padding: 6px 0 32px 0 !important; }
.m-hero-copy h1 { font-size: clamp(38px, 11vw, 56px) !important; }
.m-hero-img { display: none !important; }
.m-hero-rule { display: none !important; }
/* CTA bandeaux 1fr/auto */
.m-2auto { grid-template-columns: 1fr !important; gap: 22px !important; }
.m-2auto .m-cta-btn, .m-2auto .m-cta-btn > a, .m-2auto a.m-cta-btn { width: 100% !important; justify-content: center !important; }
/* constat */
.m-chaos { grid-template-columns: 1fr !important; gap: 30px !important; }
/* méthode piliers */
.m-pillar { grid-template-columns: 46px 1fr !important; gap: 16px !important; padding: 30px 0 !important; }
/* process */
.m-process-head { grid-template-columns: 1fr !important; gap: 14px !important; margin-bottom: 44px !important; }
.m-process-steps { grid-template-columns: 1fr !important; gap: 4px !important; }
.m-process-line { display: none !important; }
.m-process-step { display: grid !important; grid-template-columns: 46px 1fr !important; gap: 16px; align-items: start; text-align: left !important; padding: 18px 0; border-bottom: 1px solid #E4E1DA; }
.m-process-step > div:first-child { margin-bottom: 0 !important; justify-content: flex-start !important; }
.m-process-step h3 { text-align: left !important; margin-top: 6px !important; margin-bottom: 0 !important; }
.m-process-step p { display: none !important; }
/* domaines */
.m-domains { grid-template-columns: 1fr !important; }
.m-domains > div { border-right: none !important; }
/* doctrine */
.m-doctrine { grid-template-columns: 1fr !important; gap: 26px !important; }
/* profil */
.m-profil { grid-template-columns: 1fr !important; gap: 40px !important; }
.m-profil-aside { position: static !important; top: auto !important; }
.m-profil-photo { max-width: 320px; }
/* listes d'articles */
.m-postrow { grid-template-columns: 1fr !important; gap: 8px !important; padding: 26px 0 !important; }
.m-postrow-arrow { display: none !important; }
.m-postrow-meta { display: flex !important; flex-direction: row !important; gap: 14px; align-items: center; }
.m-postrow-meta span { margin-top: 0 !important; }
/* livres blancs */
.m-livre { grid-template-columns: 48px 1fr !important; gap: 16px !important; }
.m-livre-btn { grid-column: 1 / -1 !important; width: 100% !important; }
/* article */
.m-article { padding-top: 110px !important; }
.m-article > div, .m-legal > div { padding-left: 22px !important; padding-right: 22px !important; }
.m-legal { padding-top: 112px !important; }
/* sections : resserrer la hauteur */
.m-sect { padding-top: 66px !important; padding-bottom: 66px !important; }
.m-sect-lg { padding-top: 72px !important; padding-bottom: 72px !important; }
}
@media (max-width: 540px) {
.m-wrap { padding-left: 18px !important; padding-right: 18px !important; }
.m-wins { grid-template-columns: 1fr 1fr !important; gap: 22px 18px !important; }
.m-blog-chips { gap: 8px !important; }
}
@media (max-width: 700px) {
.m-refrow { grid-template-columns: 38px 1fr !important; gap: 14px !important; }
.m-refrow-meta { display: none !important; }
.m-refrow-ex { display: none !important; }
}
`;
document.head.appendChild(style);
}, []);
}
// ---------- Small UI atoms ----------
function Eyebrow({ children, color }) {
return (
{children}
);
}
function PrimaryBtn({ textKey, children, full, big, small, style }) {
const t = useT();
const [hover, setHover] = useState(false);
const label = textKey ? t(textKey) : children;
return (
setHover(true)}
onMouseLeave={() => setHover(false)}
style={{
display: "inline-flex",
alignItems: "center",
gap: 10,
fontFamily: FONTS.body,
fontSize: big ? 16 : small ? 13.5 : 15,
fontWeight: 600,
letterSpacing: "0.01em",
padding: big ? "19px 38px" : small ? "12px 20px" : "17px 30px",
borderRadius: 2,
background: hover ? C.saugeFonce : C.sauge,
color: "#fff",
cursor: "pointer",
textDecoration: "none",
transform: hover ? "translateY(-2px)" : "none",
boxShadow: hover ? "0 14px 30px -12px rgba(76,88,74,.6)" : "none",
transition: "all .35s cubic-bezier(.2,.7,.3,1)",
width: full ? "100%" : "auto",
justifyContent: full ? "center" : "flex-start",
...style
}}>
{label}{" "}
→
);
}
function MonarchSite() {
useFonts();
useCalEmbed();
const [page, setPage] = useState("home");
const [slug, setSlug] = useState(null);
const lang = "fr";
useEffect(() => { document.documentElement.setAttribute("lang", "fr"); }, []);
const go = (p, s = null) => {setPage(p);setSlug(s);window.scrollTo({ top: 0 });};
return (
{} }}>
{page === "home" &&
}
{page === "profil" &&
}
{page === "blog" &&
}
{page === "encyclo" &&
}
{page === "simulateur" &&
}
{page === "article" &&
}
{page === "legal" &&
}
);
}
// ---------- Header ----------
function Header({ page, go }) {
const t = useT();
const [scrolled, setScrolled] = useState(false);
const [menuOpen, setMenuOpen] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 40);
window.addEventListener("scroll", onScroll, { passive: true });
return () => window.removeEventListener("scroll", onScroll);
}, []);
useEffect(() => {
document.body.style.overflow = menuOpen ? "hidden" : "";
return () => { document.body.style.overflow = ""; };
}, [menuOpen]);
const solid = scrolled || page !== "home" || menuOpen;
const NavLink = ({ to, hash, children }) =>
{
if (hash) {
if (page !== "home") {
go("home");
setTimeout(() => {
const el = document.getElementById(hash);
if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 80, behavior: "smooth" });
}, 80);
} else {
const el = document.getElementById(hash);
if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 80, behavior: "smooth" });
}
} else {
go(to);
}
}}
style={{
fontFamily: FONTS.body,
fontSize: 14.5,
fontWeight: 500,
color: C.encre,
opacity: page === to ? 1 : 0.78,
background: "none",
border: "none",
cursor: "pointer",
padding: 0,
borderBottom: page === to ? `1px solid ${C.encre}` : "1px solid transparent",
paddingBottom: 2
}}>
{children}
;
return (
go("home")}
style={{ display: "flex", flexDirection: "column", lineHeight: 1, background: "none", border: "none", cursor: "pointer", textAlign: "left", padding: 0 }}>
MONARCH
{t("logo.sub")}
{t("nav.method")}
Les simulateurs
{t("nav.lawyer")}
{t("nav.journal")}
setMenuOpen((o) => !o)}
style={{ display: "none", flexDirection: "column", justifyContent: "center", gap: 5, width: 42, height: 42, background: "none", border: "none", cursor: "pointer", padding: 8 }}>
{menuOpen &&
{ setMenuOpen(false); go("home"); setTimeout(() => { const el = document.getElementById("methode"); if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 70, behavior: "smooth" }); }, 90); }}>{t("nav.method")}
{ setMenuOpen(false); go("simulateur"); }}>Les simulateurs
{ setMenuOpen(false); go("profil"); }}>{t("nav.lawyer")}
{ setMenuOpen(false); go("encyclo"); }}>{t("nav.journal")}
}
);
}
function MobileLink({ children, onClick }) {
return (
{children}
);
}
// ---------- HOME ----------
function Home() {
return (
);
}
function Wrap({ children, style, className }) {
return
{children}
;
}
// ---------- SIMULATEURS (page dédiée) ----------
function SimulatorPage() {
const groups = [
{ cat: "Trésorerie & rémunération", items: [
{ id: "extraction", label: "Sortir la trésorerie", comp: "HoldingDiagnostic" },
{ id: "remu", label: "Coût réel de la rémunération", comp: "RemunerationFrictionSimulator" },
{ id: "fees", label: "Honoraires entre sociétés", comp: "ManagementFeesSimulator" },
{ id: "capi", label: "Faire fructifier mes placements", comp: "FinancialCapitalizationSimulator" },
{ id: "temps", label: "Le levier du temps (intérêts composés)", comp: "CompoundInterestSimulator" }
] },
{ cat: "Vendre l'entreprise", items: [
{ id: "titresAbat", label: "Vendre mes titres", comp: "AdvancedSecuritiesSimulator" },
{ id: "fondsEI", label: "Vendre mon fonds (en nom propre)", comp: "SoleProprietorshipSaleSimulator" },
{ id: "fonds", label: "Vendre mon fonds (en société)", comp: "AssetSaleSimulator" },
{ id: "dmto", label: "Frais d'enregistrement de l'acheteur", comp: "TransferTaxSimulator" },
{ id: "apport", label: "Reporter l'impôt (apport-cession)", comp: "ApportCessionSimulator" },
{ id: "obo", label: "Me verser du cash (OBO)", comp: "OBOSimulator" },
{ id: "lboDette", label: "Racheter une entreprise (LBO)", comp: "CorporateBuyoutDebtSimulator" }
] },
{ cat: "Transmettre à ma famille", items: [
{ id: "dmtg", label: "Droits de donation & succession", comp: "DMTGSimulator" },
{ id: "dutreil", label: "Transmettre mon entreprise (Dutreil)", comp: "DutreilSimulator" },
{ id: "fbo", label: "Transmettre à un enfant repreneur", comp: "FamilyBuyOutSimulator" }
] },
{ cat: "Mon patrimoine", items: [
{ id: "immoDicho", label: "Revendre un bien immobilier", comp: "RealEstateDichotomySimulator" },
{ id: "oboImmo", label: "Rendre liquide un bien (OBO)", comp: "PersonalRealEstateOBOSimulator" },
{ id: "immoDette", label: "Acheter un bien locatif à crédit", comp: "RealEstateDebtSimulator" },
{ id: "matrimonial", label: "Protéger l'entreprise (mariage)", comp: "MatrimonialStressTest" }
] }
];
const all = groups.flatMap((g) => g.items);
const [sim, setSim] = useState("extraction");
const active = all.find((t) => t.id === sim) || all[0];
const Comp = typeof window !== "undefined" ? window[active.comp] : null;
return (
Les outils du cabinet
Simulateurs d'ingénierie patrimoniale
Choisissez la problématique qui vous concerne. Chaque simulation est indicative et ouvre la voie à un échange sur-mesure.
{groups.map((g) => (
{g.cat}
{g.items.map((it) => {
const on = it.id === sim;
return (
{ setSim(it.id); window.scrollTo({ top: 0 }); }}
style={{ textAlign: "left", fontFamily: FONTS.body, fontSize: 14.5, fontWeight: on ? 600 : 500, color: on ? "#fff" : C.encre, background: on ? C.encre : C.blanc, border: `1px solid ${on ? C.encre : C.trait}`, padding: "12px 14px", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8, transition: "all .2s" }}>
{it.label}
→
);
})}
))}
{typeof Comp === "function" ? React.createElement(Comp) : null}
);
}
// ---------- ENCYCLOPÉDIE (page dédiée) ----------
function Encyclopedie({ go, slug }) {
if (typeof window === "undefined" || typeof window.EncyclopediePage !== "function") {
return Chargement de l'encyclopédie…
;
}
return React.createElement(window.EncyclopediePage, { go, slug });
}
// ---------- LIVRES BLANCS (page dédiée) ----------
function LivresPage() {
const livres = (typeof window !== "undefined" && window.MONARCH_LIVRES) || [];
const [gate, setGate] = useState(null); // livre en attente de déblocage
const Modal = window.MSC && window.MSC.LeadModal;
const download = (livre) => {
if (window.MSC) { window.MSC.leadCapture({ email: window.MSC.getLeadEmail() || "" }, "livre:" + livre.slug); }
const a = document.createElement("a");
a.href = livre.fichier; a.download = ""; a.target = "_blank"; a.rel = "noopener";
document.body.appendChild(a); a.click(); a.remove();
};
const request = (livre) => {
const has = window.MSC && window.MSC.getLeadEmail();
if (has) { download(livre); } else { setGate(livre); }
};
return (
{Modal && gate &&
setGate(null)} onUnlock={() => { const l = gate; setGate(null); download(l); }} />}
Ressources · Livres blancs
Des guides de fond pour décider en connaissance de cause.
Téléchargez gratuitement nos analyses, en échange de votre adresse e-mail.
{livres.map((l) =>
request(l)} />)}
{livres.length === 0 && Les premiers livres blancs arrivent bientôt.
}
);
}
function LivreRow({ livre, onGet }) {
const [hover, setHover] = useState(false);
return (
setHover(true)} onMouseLeave={() => setHover(false)} className="m-livre"
style={{ display: "grid", gridTemplateColumns: "64px 1fr auto", gap: 28, alignItems: "center", padding: "30px 0", borderBottom: `1px solid ${C.trait}`, background: hover ? C.albatre : "transparent", transition: "background .3s" }}>
Livre blanc
{livre.titre}
{livre.sousTitre}
Télécharger →
);
}
function Hero() {
const t = useT();
return (
{t("hero.eyebrow")}
{t("hero.h1.l1")}
{t("hero.h1.l2")}
{t("hero.h1.l3_italic")}
{t("hero.body")}
{t("hero.subnote")}
);
}
function ConstatCta() {
return (
);
}
function HeroCta() {
const t = useT();
return (
{t("herocta.eyebrow")}
{t("herocta.text")}
);
}
function Chaos() {
const t = useT();
const keys = ["chaos.item1", "chaos.item2", "chaos.item3", "chaos.item4"];
return (
{t("chaos.eyebrow")}
{t("chaos.title")}
{t("chaos.sub")}
{keys.map((k, i) =>
{String(i + 1).padStart(2, "0")}
)}
);
}
function Pivot() {
const t = useT();
return (
);
}
function Method() {
const t = useT();
const pillars = [
{ n: "01", tKey: "method.p1.t", bKey: "method.p1.b" },
{ n: "02", tKey: "method.p2.t", bKey: "method.p2.b" },
{ n: "03", tKey: "method.p3.t", bKey: "method.p3.b" }];
return (
{t("method.eyebrow")}
{t("method.title")}
{t("method.sub")}
{pillars.map((p, i) =>
)}
);
}
function Process() {
const t = useT();
const steps = [
{ n: "01", tKey: "process.s1.t", bKey: "process.s1.b" },
{ n: "02", tKey: "process.s2.t", bKey: "process.s2.b" },
{ n: "03", tKey: "process.s3.t", bKey: "process.s3.b" },
{ n: "04", tKey: "process.s4.t", bKey: "process.s4.b" },
{ n: "05", tKey: "process.s5.t", bKey: "process.s5.b" }];
return (
{t("process.eyebrow")}
{t("process.title")}
{t("process.sub")}
{steps.map((s) =>
{s.n}
{t(s.tKey)}
{t(s.bKey)}
)}
);
}
function Domains() {
const t = useT();
const ds = [
{ nKey: "domains.d1.n", tKey: "domains.d1.t", bKey: "domains.d1.b" },
{ nKey: "domains.d2.n", tKey: "domains.d2.t", bKey: "domains.d2.b" },
{ nKey: "domains.d3.n", tKey: "domains.d3.t", bKey: "domains.d3.b" }];
return (
{t("domains.eyebrow")}
{t("domains.title")}
{t("domains.cta.eyebrow")}
{t("domains.cta.text")}
);
}
function Doctrine() {
const t = useT();
return (
{t("doctrine.eyebrow")}
{t("doctrine.sub")}
«
{t("doctrine.quote")}
»
{t("doctrine.attr")}
);
}
function FinalCta({ titleKey, textKey }) {
const t = useT();
return (
);
}
// ---------- PROFIL ----------
function Profil({ go }) {
const t = useT();
return (
{t("profil.eyebrow")}
{t("profil.win3.v")} {t("profil.win3.unit")} >} l={t("profil.win3.l")} />
{t("profil.midcta.eyebrow")}
{t("profil.midcta.text")}
{t("profil.h1")}
{t("profil.h2")}
{t("profil.h3")}
{t("profil.h4")}
);
}
function ProseH({ children }) {
return {children} ;
}
function Win({ v, l }) {
return (
);
}
// ---------- BLOG ----------
// minutes de lecture (~200 mots/min) à partir du HTML
function readingTime(html) {
const text = (html || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
const words = text ? text.split(" ").length : 0;
return Math.max(1, Math.round(words / 200));
}
function allCategories() {
const defined = (window.MONARCH_CATEGORIES || []).slice();
const used = [];
(window.MONARCH_POSTS || []).forEach((p) => { if (p.cat && !used.includes(p.cat)) used.push(p.cat); });
// catégories définies d'abord (dans l'ordre), puis toute catégorie utilisée non listée
used.forEach((c) => { if (!defined.includes(c)) defined.push(c); });
return defined.filter((c) => used.includes(c)); // ne garder que celles ayant au moins 1 article
}
function Blog({ go }) {
const t = useT();
const all = (window.MONARCH_POSTS || []).slice();
const cats = allCategories();
const [query, setQuery] = useState("");
const q = query.trim().toLowerCase();
const match = (p) => {
if (!q) return true;
const hay = `${p.title} ${p.excerpt} ${p.cat} ${(p.body || "").replace(/<[^>]+>/g, " ")}`.toLowerCase();
return hay.includes(q);
};
const matched = all.filter(match);
const num = (n) => String(n).padStart(2, "0");
// entrées par thème (ordre des catégories = ordre du « livre »)
const chapters = cats.map((c) => ({
cat: c,
entries: matched.filter((p) => p.cat === c).sort((a, b) => (a.iso || "").localeCompare(b.iso || ""))
})).filter((ch) => ch.entries.length > 0);
return (
{t("blog.eyebrow")}
{t("blog.h1")}
{t("blog.sub")}
{all.length === 0 ?
{t("blog.empty")}
:
⌕
setQuery(e.target.value)} placeholder={t("blog.search")}
style={{ width: "100%", fontFamily: FONTS.body, fontSize: 15, color: C.encre, background: "#fff", border: `1px solid ${C.trait}`, borderRadius: 2, padding: "13px 16px 13px 40px", outline: "none" }} />
{chapters.length === 0 ?
{t("blog.noresult")}
:
{chapters.map((ch, ci) =>
{num(ci + 1)}
{ch.cat}
{ch.entries.length} {ch.entries.length > 1 ? "références" : "référence"}
{ch.entries.map((p, ei) =>
go("article", p.slug)} />
)}
)}
}
}
);
}
function RefRow({ num, post, onOpen }) {
const [hover, setHover] = useState(false);
const mins = readingTime(post.body);
return (
setHover(true)} onMouseLeave={() => setHover(false)}
className="m-refrow"
style={{ display: "grid", gridTemplateColumns: "62px 1fr auto", gap: 22, alignItems: "center", padding: "22px 16px 22px 0", paddingLeft: 16, borderBottom: `1px solid ${C.trait}`, cursor: "pointer", background: hover ? C.albatre : "transparent", transition: "background .25s" }}>
{num}
{post.title}
{post.excerpt &&
{post.excerpt}
}
{mins} min
→
);
}
function PostRow({ post, onOpen, t }) {
const [hover, setHover] = useState(false);
const mins = readingTime(post.body);
return (
setHover(true)}
onMouseLeave={() => setHover(false)}
className="m-postrow"
style={{ display: "grid", gridTemplateColumns: "160px 1fr 40px", gap: 40, padding: "38px 0", borderBottom: `1px solid ${C.trait}`, alignItems: "center", background: hover ? C.albatre : "transparent", transition: "background .3s", cursor: "pointer" }}>
{post.date}
{mins} {t ? t("blog.minread") : "min"}
{post.cat}
{post.title}
{post.excerpt &&
{post.excerpt}
}
→
);
}
// ---------- ARTICLE (template éditorial) ----------
const ARTICLE_VERT = "#5C6F5C"; // vert sauge (palette du site)
const ARTICLE_IVOIRE = "#F6F3EA"; // ivoire
function slugifyHeading(s) {
return (s || "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
}
function Article({ slug, go }) {
const t = useT();
const posts = window.MONARCH_POSTS || [];
const post = posts.find((p) => p.slug === slug);
const related = post ? posts.filter((p) => p.slug !== post.slug && p.cat === post.cat).sort((a, b) => (b.iso || "").localeCompare(a.iso || "")).slice(0, 3) : [];
const bodyRef = useRef(null);
const [toc, setToc] = useState([]);
const [activeId, setActiveId] = useState("");
const [openFaq, setOpenFaq] = useState(0);
// Construire le sommaire à partir des du corps + scroll-spy
useEffect(() => {
if (!post || !bodyRef.current) return;
const hs = Array.from(bodyRef.current.querySelectorAll("h2"));
const items = hs.map((h, i) => {
const id = h.id || (slugifyHeading(h.textContent) || "section-" + i);
h.id = id;
h.style.scrollMarginTop = "100px";
return { id, text: h.textContent };
});
setToc(items);
if (!items.length) return;
const obs = new IntersectionObserver((entries) => {
entries.forEach((e) => { if (e.isIntersecting) setActiveId(e.target.id); });
}, { rootMargin: "-90px 0px -65% 0px", threshold: 0 });
hs.forEach((h) => obs.observe(h));
return () => obs.disconnect();
}, [post]);
// JSON-LD (Article + FAQPage)
useEffect(() => {
if (!post) return;
const faq = Array.isArray(post.faq) ? post.faq : [];
const graph = [{
"@type": "Article",
"headline": post.title,
"datePublished": post.iso || undefined,
"articleSection": post.cat || undefined,
"author": { "@type": "Person", "name": "Hugo Groslambert" },
"publisher": { "@type": "Organization", "name": "Monarch Avocat" }
}];
if (faq.length) graph.push({
"@type": "FAQPage",
"mainEntity": faq.map((f) => ({ "@type": "Question", "name": f.q, "acceptedAnswer": { "@type": "Answer", "text": f.a } }))
});
const el = document.createElement("script");
el.type = "application/ld+json";
el.id = "monarch-article-jsonld";
el.textContent = JSON.stringify({ "@context": "https://schema.org", "@graph": graph });
document.getElementById("monarch-article-jsonld") && document.getElementById("monarch-article-jsonld").remove();
document.head.appendChild(el);
return () => { el.remove(); };
}, [post]);
if (!post) {
return (
Article introuvable.
go("blog")} style={{ marginTop: 16, color: C.ardoiseFonce, background: "none", border: "none", cursor: "pointer", fontFamily: FONTS.body, fontSize: 15, fontWeight: 600, padding: 0 }}>← {t("blog.back")}
);
}
const essentiel = post.essentiel ? (Array.isArray(post.essentiel) ? post.essentiel : [post.essentiel]) : [];
const faq = Array.isArray(post.faq) ? post.faq : [];
return (
go("blog")} style={{ color: ARTICLE_VERT, background: "none", border: "none", cursor: "pointer", fontFamily: FONTS.body, fontSize: 14, fontWeight: 600, padding: 0, letterSpacing: "0.02em", marginBottom: 30, display: "inline-flex", alignItems: "center", gap: 8 }}>← {t("blog.back")}
{/* Header */}
{post.cover &&
}
{/* Corps : ToC sticky + article */}
{/* Sommaire sticky */}
{toc.length > 0 &&
Sommaire
}
{/* Colonne de lecture */}
{/* L'essentiel */}
{essentiel.length > 0 &&
L'essentiel
{essentiel.map((e, i) =>
—
)}
}
{/* FAQ */}
{faq.length > 0 &&
Questions fréquentes
{faq.map((f, i) => {
const open = openFaq === i;
return (
setOpenFaq(open ? -1 : i)} aria-expanded={open}
style={{ width: "100%", textAlign: "left", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 18, padding: "20px 0", background: "none", border: "none", cursor: "pointer", fontFamily: FONTS.serif, fontSize: 18, fontWeight: 500, color: C.encre }}>
{f.q}
+
{open &&
}
);
})}
}
{/* CTA */}
{related.length > 0 &&
{t("blog.related")}
{related.map((r) =>
go("article", r.slug)}
style={{ width: "100%", textAlign: "left", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 24, padding: "20px 0", borderBottom: `1px solid ${C.trait}`, background: "none", border: "none", cursor: "pointer", fontFamily: FONTS.body }}>
{r.cat}
{r.title}
→
)}
}
);
}
// ---------- LÉGAL ----------
function Legal({ go }) {
const t = useT();
const H = ({ children }) => {children} ;
const P = ({ children }) => {children}
;
const Ph = ({ children }) => {children} ;
return (
{t("legal.eyebrow")}
{t("legal.h1")}
Éditeur du site
Le présent site est édité par Hugo Groslambert , avocat inscrit au Barreau de Toulouse.
Téléphone : +33 6 69 56 99 18 — Courriel : contact@monarch-avocat.fr
Directeur de la publication : Hugo Groslambert.
Profession et règles applicables
Avocat au Barreau de Toulouse, Maître Hugo Groslambert est soumis aux règles de la profession d'avocat : la loi n° 71-1130 du 31 décembre 1971, le décret n° 91-1197 du 27 novembre 1991, le Règlement Intérieur National (RIN) du Conseil National des Barreaux et le règlement intérieur du Barreau de Toulouse.
Le titre d'avocat est un titre professionnel français protégé. La structure relève de l'Ordre des Avocats du Barreau de Toulouse .
Médiation de la consommation
Conformément aux articles L.611-1 et suivants du Code de la consommation, le client consommateur peut recourir gratuitement au médiateur de la consommation de la profession d'avocat.
Hébergement
Le site est hébergé par Hostinger International Ltd. , 61 Lordou Vironos Street, 6023 Larnaca, Chypre — www.hostinger.fr .
Propriété intellectuelle
L'ensemble des contenus (textes, articles, identité visuelle, photographies) est protégé par le droit d'auteur et reste la propriété de l'éditeur, sauf mention contraire. Toute reproduction ou réutilisation sans autorisation est interdite.
Données personnelles (RGPD)
Les informations transmises via le formulaire de prise de rendez-vous ou par courriel sont utilisées uniquement pour répondre à votre demande et ne sont pas cédées à des tiers. Conformément au RGPD et à la loi « Informatique et Libertés », vous disposez d'un droit d'accès, de rectification, d'effacement et d'opposition sur vos données, en écrivant à contact@monarch-avocat.fr. Réclamation possible auprès de la CNIL (www.cnil.fr).
Confidentialité
Les échanges avec un avocat sont couverts par le secret professionnel. Les informations diffusées sur ce site ont une vocation générale et d'information ; elles ne constituent pas une consultation juridique et ne sauraient engager la responsabilité de l'éditeur.
go("home")} style={{ marginTop: 36, color: C.ardoiseFonce, background: "none", border: "none", cursor: "pointer", fontFamily: FONTS.body, fontSize: 15, fontWeight: 600, padding: 0 }}>← Retour à l'accueil
);
}
// ---------- Footer ----------
function Footer({ go }) {
const t = useT();
return (
MONARCH
{t("footer.sub")}
go("home")} style={{ color: "#b9bbb8", background: "none", border: "none", cursor: "pointer", padding: 0, fontFamily: "inherit", fontSize: "inherit" }}>{t("footer.nav.home")}
go("profil")} style={{ color: "#b9bbb8", background: "none", border: "none", cursor: "pointer", padding: 0, fontFamily: "inherit", fontSize: "inherit" }}>{t("footer.nav.lawyer")}
go("encyclo")} style={{ color: "#b9bbb8", background: "none", border: "none", cursor: "pointer", padding: 0, fontFamily: "inherit", fontSize: "inherit" }}>{t("footer.nav.journal")}
go("legal")} style={{ color: "#b9bbb8", background: "none", border: "none", cursor: "pointer", padding: 0, fontFamily: "inherit", fontSize: "inherit" }}>{t("footer.nav.legal")}
{ if (window.monarchCookiesOpen) window.monarchCookiesOpen(); }} style={{ color: "#b9bbb8", background: "none", border: "none", cursor: "pointer", padding: 0, fontFamily: "inherit", fontSize: "inherit" }}>Gérer les cookies
);
}
// ---------- Mount ----------
// Charge les contenus édités dans l'admin (posts.json / livres.json / encyclopedie.json),
// puis monte le site. En l'absence de ces fichiers, on garde les valeurs des fichiers .js.
(function () {
const tryLoad = (url, key, isArray) =>
fetch(url, { cache: "no-store" })
.then((r) => (r.ok ? r.json() : null))
.then((data) => {
if (!data) return;
if (isArray) { if (Array.isArray(data) && data.length) window[key] = data; }
else if (data && typeof data === "object" && (data.entries || data.modules)) window[key] = data;
})
.catch(() => {});
Promise.all([
tryLoad("posts.json", "MONARCH_POSTS", true),
tryLoad("livres.json", "MONARCH_LIVRES", true),
tryLoad("encyclopedie.json", "MONARCH_ENCYCLO", false)
]).then(() => {
ReactDOM.createRoot(document.getElementById("root")).render( );
});
})();