/* ClientBase, Homepage Hero + feature carousel + savings simulator */

/* Shared reveal hook, triggers a "visible" flag when element enters viewport */
const useReveal = (options = {}) => {
  const ref = React.useRef(null);
  const [visible, setVisible] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (typeof IntersectionObserver === "undefined") { setVisible(true); return; }
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) { setVisible(true); io.unobserve(e.target); }
      });
    }, { threshold: options.threshold ?? 0.2, rootMargin: options.rootMargin ?? "0px 0px -40px 0px" });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, visible];
};

/* ================================================================
   FLOW ARROW, traces itself when scrolled into view
================================================================ */
const FlowArrow = ({ caption, size = "md", step, totalSteps, tone }) => {
  // Tailles réduites (60×92 → 48×72) pour serrer l'espace vertical pris
  // par la flèche entre 2 sections. Moins de blanc en respiration.
  const dim = size === "sm" ? { w: 36, h: 54 } : { w: 48, h: 72 };
  const [ref, visible] = useReveal({ threshold: 0.35 });
  const pathLen = 100;
  // tone permet de teinter la flèche selon l'audience (pro indigo par défaut,
  // var(--cli-accent) pour la vitrine client). Toutes les surfaces dérivent du tone.
  const accent     = tone || "var(--accent)";
  const accentInk  = tone ? `color-mix(in oklab, ${tone} 70%, var(--ink))` : "var(--accent-ink)";
  const accentSoft = tone ? `color-mix(in oklab, ${tone} 14%, var(--surface))` : "var(--accent-soft)";
  const accentSoft2= tone ? `color-mix(in oklab, ${tone} 28%, var(--surface))` : "var(--accent-soft-2)";
  return (
    <div ref={ref} style={{
      // Padding réduit (22px 0 16px → 8px 0 6px) pour resserrer
      // les étapes contre le contenu autour et virer le grand
      // blanc qui faisait flotter les sections.
      padding: "8px 0 6px",
      display: "flex", flexDirection: "column", alignItems: "center",
      textAlign: "center",
    }}>
      {step && (
        <div style={{
          display: "inline-flex", alignItems: "center", gap: 9,
          padding: "5px 12px 5px 5px",
          background: accentSoft,
          border: `1px solid ${accentSoft2}`,
          borderRadius: 999, marginBottom: 10,
          opacity: visible ? 1 : 0,
          transform: visible ? "translateY(0) scale(1)" : "translateY(-6px) scale(0.95)",
          transition: "opacity 0.45s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1)",
        }}>
          <span style={{
            width: 22, height: 22, borderRadius: 50,
            background: accent, color: "white",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            fontFamily: "var(--ff-display)", fontWeight: 600, fontSize: 12,
            fontVariantNumeric: "tabular-nums",
          }}>{step}</span>
          <span style={{
            fontSize: 12, fontWeight: 580, color: accentInk,
            letterSpacing: "-0.005em",
          }}>
            Étape {step}{totalSteps ? ` sur ${totalSteps}` : ""}
          </span>
        </div>
      )}
      {caption && (
        <div style={{
          fontSize: 15.5, fontStyle: "italic",
          fontFamily: "var(--ff-display)",
          marginBottom: 10, color: accentInk,
          maxWidth: 460, lineHeight: 1.35,
          fontWeight: 500,
          opacity: visible ? 1 : 0,
          transform: visible ? "translateY(0)" : "translateY(-6px)",
          transition: "opacity 0.5s ease 0.05s, transform 0.5s ease 0.05s",
        }}>
          {caption}
        </div>
      )}
      <svg aria-hidden viewBox="0 0 54 84" style={{
        width: dim.w, height: dim.h,
        color: accent,
        overflow: "visible",
        animation: visible ? "cbArrowPulse 2.4s ease-in-out 1.6s infinite" : "none",
      }}>
        <circle cx="27" cy="3" r="2" fill="currentColor"
          opacity={visible ? 0.3 : 0}
          style={{ transition: "opacity 0.3s ease 0.1s" }}/>
        <circle cx="27" cy="10" r="2.5" fill="currentColor"
          opacity={visible ? 0.55 : 0}
          style={{ transition: "opacity 0.3s ease 0.25s" }}/>
        <path d="M 27 18 C 48 34, 6 52, 27 74"
          stroke="currentColor" strokeWidth="3.6" fill="none"
          strokeLinecap="round"
          style={{
            strokeDasharray: pathLen,
            strokeDashoffset: visible ? 0 : pathLen,
            transition: "stroke-dashoffset 0.9s cubic-bezier(0.65, 0, 0.35, 1) 0.3s",
          }}/>
        <path d="M 16 64 L 27 77 L 38 64"
          stroke="currentColor" strokeWidth="3.6" fill="none"
          strokeLinecap="round" strokeLinejoin="round"
          style={{
            strokeDasharray: 40,
            strokeDashoffset: visible ? 0 : 40,
            transition: "stroke-dashoffset 0.35s ease 1.1s",
          }}/>
      </svg>
    </div>
  );
};

/* ================================================================
   HERO, cycling profession word, big centered type
================================================================ */
// Couleur du texte défilant des professions, la couleur de la marque uniquement
// (indigo pour le hero pro, le hero étant lui-même rendu côté pro). Un seul
// hue = unité visuelle plus forte, le texte ne se transforme plus en feu d'artifice.
const PROF_COLORS = [
  "var(--accent)",
];

const PROFESSIONS = [
  "PO",
  "coiffeurs",
  "coiffeuses",
  "esthéticiennes",
  "masseurs",
  "masseuses",
  "maquilleuses",
  "tatoueurs",
  "tatoueuses",
  "barbiers",
  "sophrologues",
  "naturopathes",
  "hypnothérapeutes",
  "ostéopathes",
  "kinés",
  "podologues",
  "réflexologues",
  "diététiciens",
  "coachs sportifs",
  "profs de yoga",
  "profs de pilates",
  "psychologues",
  "orthophonistes",
  "photographes",
  "toiletteurs",
  "couturières",
  "thérapeutes",
  "microblading",
  "extensions de cils",
  "indépendants",
];

/* Comparateur "vs ton outil actuel", affiché côté mobile dans le hero.
   Pour chaque outil : icône + 3 cons concrets. ClientBase a 3 pros constants. */
const TOOL_COMPARE = [
  { id: "carnet",   icon: "📓", label: "Carnet papier", cons: [
    "Aucun rappel auto = no-show garantis",
    "Si perdu, fichier client perdu",
    "Vous prenez tous les RDV au tél",
  ]},
  { id: "excel",    icon: "📊", label: "Excel / Google",  cons: [
    "Pas conçu pour la prise de RDV",
    "Pas de fiche client, pas de fidélité",
    "Aucune facture conforme",
  ]},
  { id: "planity",  icon: "💸", label: "Planity",       cons: [
    "Commission 1 à 2 € sur chaque RDV",
    "Vos clients voient 50 concurrents",
    "Que de l'agenda, rien d'autre",
  ]},
  { id: "iara",     icon: "🪙", label: "iara",          cons: [
    "Logo iara + bouton « Devenir pro » sur votre page de RDV",
    "Lien iarabeauty.com/pro/vous, pas un vrai domaine à vous",
    "Vos clientes découvrent d'autres pros via le catalogue iara",
  ]},
  { id: "insta",    icon: "📨", label: "Insta + DM",     cons: [
    "30 % des DM finissent dans Demandes",
    "10 à 15 messages pour 1 RDV",
    "Dépendance totale à l'algo Meta",
  ]},
  { id: "rien",     icon: "🤷", label: "Rien pour l'instant", cons: [
    "Tout à la mémoire = oublis garantis",
    "Aucune stat, aucun pilotage",
    "Compta = nuit blanche chaque trimestre",
  ]},
];

const CLIENTBASE_PROS = [
  "ZÉRO commission, jamais",
  "Tout-en-un : agenda + clients + factures + fidélité + RDV en ligne",
  "Vos données 100 % à vous, exportables en 1 clic",
];

/* Panneau de comparaison affiché après tap sur un outil. */
/* Comparatifs externes retirés (référencement SEO à revoir plus tard). */
const TOOL_COMPARE_PAGES = {};

const ComparatorPanel = ({ tool, onBack }) => (
  <div style={{
    animation: "cbCompareIn 0.45s cubic-bezier(.22,1,.36,1) both",
    display: "flex", flexDirection: "column", gap: 10,
  }}>
    <button onClick={onBack} style={{
      alignSelf: "flex-start",
      background: "transparent", border: "none", cursor: "pointer",
      fontFamily: "inherit", fontSize: 12, color: "var(--ink-4)",
      padding: "2px 4px",
      display: "inline-flex", alignItems: "center", gap: 4,
    }}>
      ← Choisir un autre outil
    </button>

    {/* Avec [outil], rouge doux */}
    <div style={{
      padding: "12px 14px",
      background: "oklch(97% 0.025 25)", border: "1px solid oklch(90% 0.05 25)",
      borderRadius: 11,
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
        <span style={{ fontSize: 18, lineHeight: 1 }}>{tool.icon}</span>
        <span style={{ fontSize: 12.5, fontWeight: 580, color: "oklch(38% 0.16 25)", textTransform: "uppercase", letterSpacing: "0.04em" }}>
          Avec {tool.label}
        </span>
      </div>
      <ul style={{ margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: 5 }}>
        {tool.cons.map((c, i) => (
          <li key={i} className="cb-compare-line" style={{
            display: "flex", gap: 7, alignItems: "flex-start",
            fontSize: 12.5, color: "oklch(35% 0.10 25)", lineHeight: 1.4,
            animationDelay: `${0.1 + i * 0.06}s`,
          }}>
            <span style={{ color: "oklch(55% 0.18 25)", fontWeight: 700, flexShrink: 0 }}>✗</span>
            <span>{c}</span>
          </li>
        ))}
      </ul>
    </div>

    {/* Avec ClientBase, vert / accent */}
    <div style={{
      padding: "12px 14px",
      background: "var(--accent-soft)", border: "1px solid var(--accent-soft-2)",
      borderRadius: 11,
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
        <span style={{ fontSize: 18, lineHeight: 1 }}>✦</span>
        <span style={{ fontSize: 12.5, fontWeight: 580, color: "var(--accent-ink)", textTransform: "uppercase", letterSpacing: "0.04em" }}>
          Avec ClientBase
        </span>
      </div>
      <ul style={{ margin: 0, padding: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: 5 }}>
        {CLIENTBASE_PROS.map((p, i) => (
          <li key={i} className="cb-compare-line" style={{
            display: "flex", gap: 7, alignItems: "flex-start",
            fontSize: 12.5, color: "var(--ink)", lineHeight: 1.4,
            animationDelay: `${0.32 + i * 0.06}s`,
          }}>
            <span style={{ color: "var(--accent)", fontWeight: 700, flexShrink: 0 }}>✓</span>
            <span>{p}</span>
          </li>
        ))}
      </ul>
    </div>

    {TOOL_COMPARE_PAGES[tool.id] && (
      <a href={TOOL_COMPARE_PAGES[tool.id]} style={{
        marginTop: 2, alignSelf: "stretch",
        padding: "10px 12px", textAlign: "center",
        background: "var(--surface)", border: "1px solid var(--accent-soft-2)",
        borderRadius: 10, fontFamily: "inherit", fontSize: 12.5,
        fontWeight: 580, color: "var(--accent-ink)", textDecoration: "none",
        animation: "cbCompareIn 0.6s cubic-bezier(.22,1,.36,1) 0.5s both",
      }}>
        Voir le comparatif complet ClientBase vs {tool.label} →
      </a>
    )}
  </div>
);

/* === Hook compteur animé au scroll ===
   Démarre l'animation 0 → target dès que l'élément entre dans le viewport
   (IntersectionObserver). N'anime qu'une seule fois. Retourne [value, ref].
   `duration` en ms. Ease-out pour un effet "naturel" (rapide au début,
   ralentit à la fin). */
// Hook compteur, anime 0 → target. Démarre automatiquement quand l'élément
// entre dans le viewport. Retourne [valeur courante, ref à attacher au DOM,
// fonction replay() pour re-déclencher l'animation à la demande (sur clic
// par exemple). Cancel propre de l'anim précédente avant de re-jouer.
const useCountUp = (target, { duration = 1400, decimals = 0 } = {}) => {
  const [value, setValue] = React.useState(0);
  const ref = React.useRef(null);
  const animRef = React.useRef(null);

  const animate = React.useCallback(() => {
    if (animRef.current) cancelAnimationFrame(animRef.current);
    setValue(0);
    const start = performance.now();
    const tick = (now) => {
      const t = Math.min(1, (now - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3); // ease-out cubic
      setValue(target * eased);
      if (t < 1) animRef.current = requestAnimationFrame(tick);
      else { setValue(target); animRef.current = null; }
    };
    animRef.current = requestAnimationFrame(tick);
  }, [target, duration]);

  React.useEffect(() => {
    const el = ref.current;
    if (!el || typeof IntersectionObserver === "undefined") {
      setValue(target);
      return;
    }
    let started = false;
    const obs = new IntersectionObserver((entries) => {
      if (!started && entries[0].isIntersecting) {
        started = true;
        animate();
        obs.disconnect();
      }
    }, { threshold: 0.3 });
    obs.observe(el);
    return () => obs.disconnect();
  }, [target, duration, animate]);

  return [decimals === 0 ? Math.round(value) : Number(value.toFixed(decimals)), ref, animate];
};
// Expose globalement pour que d'autres fichiers (pages-a, pages-client-vitrine,
// shared) puissent réutiliser le même odomètre fluide au scroll.
if (typeof window !== "undefined") {
  window.useCountUp = useCountUp;
}

/* Carte CA du mois, interactive : compteur animé au scroll + hover barres
   = highlight + tooltip avec le jour et le CA. */
const HeroStatsCard = () => {
  const TOTAL = 4287;
  const DAYS = [
    { label: "Lun", value: 380 },
    { label: "Mar", value: 620 },
    { label: "Mer", value: 475 },
    { label: "Jeu", value: 760 },
    { label: "Ven", value: 520 },
    { label: "Sam", value: 855 }, // pic
    { label: "Dim", value: 677 },
  ];
  const max = Math.max(...DAYS.map(d => d.value));
  const [hover, setHover] = React.useState(5); // sam par défaut
  const [count, countRef, replay] = useCountUp(TOTAL, { duration: 1500 });
  const formatted = count.toLocaleString("fr-FR");
  const active = DAYS[hover];

  return (
    <div ref={countRef} className="cb-hero-card f2"
      onClick={replay}
      title="Cliquez pour relancer le compteur"
      style={{
        display: "flex", flexDirection: "column", justifyContent: "space-between",
        gap: 6, overflow: "hidden", cursor: "pointer",
      }}>
      <div>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 6 }}>
          <span style={{
            display: "inline-flex", alignItems: "center", gap: 5,
            fontSize: 10.5, fontWeight: 580, color: "var(--ink-3)",
            textTransform: "uppercase", letterSpacing: "0.04em",
          }}>
            <Icon name="chart" size={12} style={{ color: "var(--accent-ink)" }}/>
            CA ce mois
          </span>
          <span style={{
            fontSize: 10, fontWeight: 600, color: "var(--accent-ink)",
            padding: "1px 6px", background: "var(--accent-soft)",
            borderRadius: 999, fontVariantNumeric: "tabular-nums",
          }}>+12 %</span>
        </div>
        <div style={{
          fontFamily: "var(--ff-display)", fontSize: 22, fontWeight: 600,
          letterSpacing: "-0.025em", color: "var(--accent-ink)", marginTop: 3,
          fontVariantNumeric: "tabular-nums", lineHeight: 1.1,
        }}>
          {formatted} €
        </div>
      </div>

      {/* Bar chart compact, tooltip à droite (sur la même ligne que les
          jours) pour économiser la hauteur. */}
      <div>
        <div style={{
          display: "flex", justifyContent: "space-between", alignItems: "baseline",
          fontSize: 10, color: "var(--ink-4)", marginBottom: 3,
          fontVariantNumeric: "tabular-nums", minHeight: 12,
        }}>
          <span>7 derniers jours</span>
          {active && (
            <span>
              <strong style={{ color: "var(--accent-ink)", fontWeight: 600 }}>
                {active.label}
              </strong> · {active.value.toLocaleString("fr-FR")} €
            </span>
          )}
        </div>
        <div style={{ display: "flex", gap: 2, alignItems: "flex-end", height: 24 }}
          onMouseLeave={() => setHover(5)}>
          {DAYS.map((d, i) => {
            const isActive = hover === i;
            return (
              <div key={i}
                onMouseEnter={() => setHover(i)}
                style={{
                  flex: 1, height: `${(d.value / max) * 100}%`,
                  background: isActive ? "var(--accent)" : "color-mix(in oklab, var(--accent) 35%, var(--bg))",
                  borderRadius: "2px 2px 0 0",
                  transition: "background .15s ease",
                  cursor: "pointer",
                  minHeight: 4,
                }}
                title={`${d.label} · ${d.value.toLocaleString("fr-FR")} €`}/>
            );
          })}
        </div>
      </div>
    </div>
  );
};

const Hero = ({ go }) => {
  const [profIdx, setProfIdx] = React.useState(0);
  const [pickedTool, setPickedTool] = React.useState(null);
  // Compteur de clics sur le mot défilant. Après 5 clics, on révèle le
  // mot caché « vous » (easter egg : le métier qu'on n'avait pas listé,
  // c'est l'utilisateur lui-même). Chaque clic accélère aussi le défilement
  // pendant 1.2s pour donner un feedback immédiat.
  const [clickCount, setClickCount] = React.useState(0);
  const [boost, setBoost] = React.useState(false);
  const [showSecret, setShowSecret] = React.useState(false);
  React.useEffect(() => {
    if (showSecret) return; // pause le cycle pendant l'affichage du mot caché
    const period = boost ? 600 : 2000;
    const t = setInterval(() => setProfIdx(i => (i + 1) % PROFESSIONS.length), period);
    return () => clearInterval(t);
  }, [boost, showSecret]);
  const onWordClick = () => {
    setClickCount(c => {
      const next = c + 1;
      if (next >= 5) {
        // Easter egg : on bascule sur le mot « vous » avec un petit glow,
        // puis on relance le cycle 2.5s plus tard pour ne pas casser le hero.
        setShowSecret(true);
        setTimeout(() => { setShowSecret(false); setBoost(false); }, 2500);
        return 0;
      }
      setBoost(true);
      clearTimeout(window.__cbHeroBoostT);
      window.__cbHeroBoostT = setTimeout(() => setBoost(false), 1200);
      return next;
    });
  };

  return (
    <section style={{
      position: "relative", overflow: "hidden",
      padding: "clamp(40px, 5vw, 64px) 0 clamp(36px, 4.5vw, 56px)",
      background: "var(--bg)",
    }}>
      <style>{`
        @keyframes cbFadeSlide {
          from { opacity: 0; transform: translateY(8px); }
          to   { opacity: 1; transform: translateY(0); }
        }
        @keyframes cbArrowPulse {
          0%, 100% { transform: translateY(0); }
          50% { transform: translateY(4px); }
        }
        @keyframes cbWordReveal {
          0%   { opacity: 0; filter: blur(10px); transform: translateY(10px); }
          60%  { opacity: 1; filter: blur(0);    transform: translateY(0); }
        }
        @keyframes cbHeroSecret {
          0%   { opacity: 0; transform: scale(0.6) rotate(-4deg); }
          60%  { opacity: 1; transform: scale(1.18) rotate(2deg); }
          100% { opacity: 1; transform: scale(1) rotate(0); }
        }
        @keyframes cbCompareIn {
          from { opacity: 0; transform: translateY(10px) scale(0.97); }
          to   { opacity: 1; transform: translateY(0) scale(1); }
        }
        @keyframes cbCompareLineIn {
          from { opacity: 0; transform: translateX(-6px); }
          to   { opacity: 1; transform: translateX(0); }
        }
        @keyframes cbCompareTilesIn {
          from { opacity: 0; transform: translateY(6px); }
          to   { opacity: 1; transform: translateY(0); }
        }
        .cb-tool-tile { transition: transform .12s ease, border-color .15s ease, background .15s ease; }
        .cb-tool-tile:hover { border-color: var(--accent-soft-2) !important; background: var(--surface) !important; }
        .cb-tool-tile:active { transform: scale(0.96); }
        .cb-tool-tiles-grid { animation: cbCompareTilesIn .35s cubic-bezier(.22,1,.36,1) both; }
        .cb-compare-line { animation: cbCompareLineIn .4s cubic-bezier(.22,1,.36,1) both; }

        /* DESKTOP,2 colonnes propres, mosaïque 3 cartes symétriques */
        .cb-hero {
          display: grid;
          grid-template-columns: 1.05fr 1fr;
          gap: 56px;
          align-items: center;
        }
        .cb-hero-bento {
          display: grid;
          grid-template-columns: 1fr 1fr;
          grid-template-rows: 220px 130px;
          gap: 12px;
        }
        .cb-hero-card {
          background: var(--surface);
          border: 1px solid var(--line);
          border-radius: 16px;
          padding: 16px;
          box-shadow: var(--sh-2);
          text-align: left;
          animation: cbFadeSlide 0.6s cubic-bezier(.22,1,.36,1) both;
          min-width: 0; min-height: 0;
        }
        .cb-hero-card.f1 { grid-column: 1 / -1; animation-delay: 0.1s; }
        .cb-hero-card.f2 { animation-delay: 0.2s; }
        .cb-hero-card.f3 { animation-delay: 0.3s; }

        /* MOBILE, design ultra-simple, focalisé, intégré */
        @media (max-width: 920px) {
          .cb-hero {
            grid-template-columns: 1fr !important;
            gap: 28px !important;
            text-align: center;
          }
          .cb-hero-text-col { text-align: center; }
          .cb-hero-text-col .cb-hero-eyebrow { justify-content: center !important; }
          .cb-hero-text-col .cb-hero-sub { margin-left: auto; margin-right: auto; }

          /* Bloc texte allégé */
          .cb-hero-sub-desktop { display: none !important; }
          .cb-hero-sub-mobile  { display: block !important; }
          /* Trust line visible aussi en mobile, centrée + gap réduit pour
             qu'elle wrap proprement sur 2 lignes max sans déborder. */
          .cb-hero-trust {
            justify-content: center !important;
            gap: 10px !important;
            margin-top: 14px !important;
            font-size: 12px !important;
          }

          /* CTAs symétriques : empilés, même largeur */
          .cb-hero-ctas {
            flex-direction: column !important;
            align-items: center !important;
            gap: 10px !important;
          }
          .cb-hero-ctas .btn {
            width: 100% !important;
            max-width: 340px !important;
          }
          /* On garde le SEUL bouton ghost desktop (.btn .btn-lg) pour que
             les 2 CTAs aient EXACTEMENT la même forme/padding/radius. */
          .cb-hero-cta-secondary-mobile { display: none !important; }

          /* Bento : on cache les 3 cartes desktop, on montre le sélecteur métier */
          .cb-hero-card.f1,
          .cb-hero-card.f2,
          .cb-hero-card.f3 { display: none !important; }
          .cb-hero-card.f-picker { display: flex !important; }
          .cb-hero-bento {
            grid-template-columns: 1fr !important;
            grid-template-rows: auto !important;
            max-width: 420px;
            margin: 0 auto;
          }
        }
        @media (max-width: 480px) {
          .cb-hero-text-col h1 { font-size: clamp(32px, 9.5vw, 44px) !important; }
        }
      `}</style>

      <div className="container" style={{ position: "relative" }}>
        <div className="cb-hero">
          {/* ========== COL TEXTE ========== */}
          <div className="cb-hero-text-col">
            {/* Eyebrow = badge live « X utilisateurs sur ClientBase »
                (compteur réel via Supabase RPC get_public_user_counts,
                fallback déterministe si offline). Remplace l'ancien
                « Bêta · gratuit » statique pour donner une preuve sociale
                réelle dès l'arrivée sur la home. */}
            <div className="cb-hero-eyebrow" style={{ marginBottom: 22 }}>
              {window.LiveProsBadge
                ? React.createElement(window.LiveProsBadge, { tone: "var(--accent)" })
                : null}
            </div>

            <h1 style={{
              fontSize: "clamp(36px, 5.6vw, 72px)", lineHeight: 1.05,
              letterSpacing: "-0.04em", fontWeight: 580, margin: 0,
            }}>
              Tout votre métier,<br/>
              {/* Surlignage indigo (bandeau bas) — appliqué via background +
                  box-decoration-break:clone pour que CHAQUE ligne du texte
                  wrap reçoive sa propre bande, sans déborder. Couleur unie
                  --accent à 45 % → clairement bleu, distinct du client. */}
              <span style={{
                backgroundImage: "linear-gradient(to top, color-mix(in oklab, var(--accent) 45%, transparent) 36%, transparent 36%)",
                paddingInline: "0.04em",
                boxDecorationBreak: "clone",
                WebkitBoxDecorationBreak: "clone",
              }}>dans une seule app.</span>
            </h1>

            {/* Sous-titre, version desktop riche */}
            <p className="cb-hero-sub cb-hero-sub-desktop" style={{
              marginTop: 20, fontSize: 17, color: "var(--ink-2)",
              lineHeight: 1.55, maxWidth: 520,
            }}>
              Agenda, clients, factures, fidélité, RDV en ligne,<strong style={{ color: "var(--ink)" }}>sans jongler entre 4 outils</strong>.
              Pensée pour les{" "}
              <span
                onClick={onWordClick}
                title="Cliquez pour accélérer"
                style={{
                  color: showSecret ? "var(--accent)" : PROF_COLORS[profIdx % PROF_COLORS.length],
                  fontWeight: 580, display: "inline-block",
                  transition: "color .35s ease",
                  cursor: "pointer",
                  userSelect: "none",
                  textShadow: showSecret ? "0 0 18px color-mix(in oklab, var(--accent) 40%, transparent)" : "none",
                }}>
                <span key={showSecret ? "secret" : profIdx} style={{
                  display: "inline-block",
                  animation: showSecret
                    ? "cbHeroSecret 0.55s cubic-bezier(.5,1.6,.4,1)"
                    : "cbWordReveal 0.55s cubic-bezier(0.22, 1, 0.36, 1)",
                }}>
                  {showSecret ? "vous" : PROFESSIONS[profIdx]}
                </span>
              </span>.
            </p>

            {/* Sous-titre, version mobile courte */}
            <p className="cb-hero-sub cb-hero-sub-mobile" style={{
              display: "none",
              marginTop: 16, fontSize: 16, color: "var(--ink-2)",
              lineHeight: 1.5, maxWidth: 380,
            }}>
              Agenda, RDV en ligne, factures et fidélité sur une seule plateforme
            </p>

            <div className="cb-hero-ctas" style={{ marginTop: 22, display: "flex", gap: 10, flexWrap: "wrap", alignItems: "center" }}>
              {/* CTA principal,signup pro direct (skip AuthChoice). Lueur
                  permanente indigo pour matcher visuellement le CTA client. */}
              <button onClick={() => go("signup")}
                className="btn btn-accent btn-lg"
                style={{
                  boxShadow: "0 14px 32px -12px var(--accent)",
                }}>
                Créer un compte <Icon name="arrow" size={15}/>
              </button>
              {/* CTA secondaire = "Voir la démo", plus présent : pill sage
                  avec halo discret, dot pulsant et flèche. Doit se distinguer
                  visuellement sans voler la vedette au "Créer un compte". */}
              <button onClick={() => cbStartDemo()}
                className="btn btn-lg cb-hero-cta-secondary-desktop cb-demo-btn"
                title="Lancer une démo complète, sans inscription"
                style={{
                  display: "inline-flex", alignItems: "center", gap: 10,
                  padding: "0 20px",
                  background: "color-mix(in oklab, var(--sage) 14%, var(--surface))",
                  border: "1px solid color-mix(in oklab, var(--sage) 38%, transparent)",
                  color: "var(--sage-ink)",
                  fontWeight: 580, letterSpacing: "-0.005em",
                  boxShadow: "0 8px 22px -12px color-mix(in oklab, var(--sage) 60%, transparent)",
                  transition: "transform .14s ease, box-shadow .2s ease, background .15s ease",
                }}>
                <span aria-hidden style={{
                  display: "inline-block", width: 8, height: 8, borderRadius: "50%",
                  background: "var(--sage)",
                  boxShadow: "0 0 0 3px color-mix(in oklab, var(--sage) 25%, transparent)",
                  animation: "cbDemoDot 1.8s ease-in-out infinite",
                }}/>
                <span>👀 Voir la démo</span>
                <Icon name="arrow" size={14}/>
              </button>
              {/* Mobile : démo en pill sage visible + login en lien discret */}
              <div className="cb-hero-cta-secondary-mobile" style={{
                display: "none", width: "100%", flexDirection: "column", gap: 8, alignItems: "center",
              }}>
                <button onClick={() => cbStartDemo()}
                  className="cb-demo-btn"
                  style={{
                    width: "100%", padding: "12px 16px",
                    background: "color-mix(in oklab, var(--sage) 14%, var(--surface))",
                    border: "1px solid color-mix(in oklab, var(--sage) 38%, transparent)",
                    borderRadius: 12,
                    color: "var(--sage-ink)", fontSize: 14, fontFamily: "inherit",
                    fontWeight: 580, cursor: "pointer",
                    display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 10,
                    letterSpacing: "-0.005em",
                    boxShadow: "0 8px 22px -12px color-mix(in oklab, var(--sage) 60%, transparent)",
                    transition: "transform .14s ease, box-shadow .2s ease, background .15s ease",
                  }}>
                  <span aria-hidden style={{
                    display: "inline-block", width: 8, height: 8, borderRadius: "50%",
                    background: "var(--sage)",
                    boxShadow: "0 0 0 3px color-mix(in oklab, var(--sage) 25%, transparent)",
                    animation: "cbDemoDot 1.8s ease-in-out infinite",
                  }}/>
                  <span>👀 Voir la démo</span>
                </button>
                <button onClick={() => go("login")}
                  style={{
                    background: "transparent", border: "none", cursor: "pointer",
                    color: "var(--ink-4)", fontSize: 12.5, fontFamily: "inherit",
                    textDecoration: "underline", padding: "4px 8px",
                  }}>
                  J'ai déjà un compte
                </button>
              </div>
            </div>
            <style>{`
              @keyframes cbDemoDot {
                0%, 100% { box-shadow: 0 0 0 3px color-mix(in oklab, var(--sage) 25%, transparent); }
                50%      { box-shadow: 0 0 0 6px color-mix(in oklab, var(--sage) 10%, transparent); }
              }
              .cb-demo-btn:hover {
                transform: translateY(-2px);
                background: color-mix(in oklab, var(--sage) 22%, var(--surface)) !important;
                box-shadow: 0 14px 30px -12px color-mix(in oklab, var(--sage) 70%, transparent) !important;
              }
              .cb-demo-btn:active { transform: translateY(0); }
            `}</style>

            <div className="cb-hero-trust" style={{
              marginTop: 16, display: "flex", alignItems: "center", gap: 14, flexWrap: "wrap",
              fontSize: 12.5, color: "var(--ink-4)",
            }}>
              <span>✓ Sans carte bancaire</span>
              <span style={{ opacity: 0.4 }}>•</span>
              <span>✓ Prêt en 10 minutes</span>
              <span style={{ opacity: 0.4 }}>•</span>
              <span>✓ ZÉRO commission</span>
            </div>

            {/* Bouton "Pas envie de créer un compte" retiré : doublon avec
                le CTA "Voir la démo" juste au-dessus dans la rangée CTAs. */}

            {/* Bande pills de confiance retirée (volonté du client : trop
                de répétition avec la ligne "Sans carte · 10 min · ZÉRO commission"
                juste au-dessus). Les mêmes infos restent dispos via les pages
                /alternatives, le footer et la page À propos. */}
          </div>

          {/* ========== MOSAÏQUE,3 cartes propres et symétriques ========== */}
          <div className="cb-hero-bento">
            {/* Carte hero, Agenda du jour (full width, plus grande) */}
            <div className="cb-hero-card f1" style={{ display: "flex", flexDirection: "column", gap: 10 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                <div style={{
                  width: 30, height: 30, borderRadius: 9,
                  background: "var(--accent-soft)", color: "var(--accent-ink)",
                  display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
                }}>
                  <Icon name="calendar" size={15}/>
                </div>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontSize: 13.5, fontWeight: 580, color: "var(--ink)", lineHeight: 1.2 }}>Aujourd'hui</div>
                  <div style={{ fontSize: 11.5, color: "var(--ink-4)", marginTop: 1 }}>5 RDV · 2 créneaux libres</div>
                </div>
              </div>
              <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
                {[
                  // Tous les 3 traits gauche en INDIGO (couleur de marque) —
                  // au lieu de cycler rose/sage qui étaient hors palette pro.
                  ["09:00", "Léa M.",     "Coupe + brushing", "var(--accent)"],
                  ["10:30", "Sophie D.",  "Couleur racines",  "var(--accent)"],
                  ["14:00", "Camille R.", "Balayage long",    "var(--accent)"],
                ].map(([h, n, p, c]) => (
                  <div key={h} style={{
                    display: "flex", alignItems: "center", gap: 8, minWidth: 0,
                    padding: "7px 10px",
                    background: "var(--bg-alt)", borderRadius: 9,
                    borderLeft: `2.5px solid ${c}`,
                    fontSize: 12,
                  }}>
                    <span style={{ fontWeight: 600, color: "var(--ink-2)", minWidth: 38, fontVariantNumeric: "tabular-nums", flexShrink: 0 }}>{h}</span>
                    <span style={{ fontWeight: 520, color: "var(--ink)", flexShrink: 0 }}>{n}</span>
                    <span style={{ color: "var(--ink-4)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 }}>· {p}</span>
                  </div>
                ))}
              </div>
            </div>

            {/* Carte 2, CA + mini bar chart interactif (palette sage =
                stats). Compteur animé au scroll, hover sur barres = tooltip. */}
            <HeroStatsCard/>

            {/* Carte 3, Lien public RDV (palette indigo, couleur de marque). */}
            <div className="cb-hero-card f3" style={{
              background: "linear-gradient(135deg, var(--accent-soft) 0%, var(--accent-soft-2) 100%)",
              color: "var(--accent-ink)", border: "1px solid var(--accent-soft-2)",
              boxShadow: "0 6px 16px -10px color-mix(in oklab, var(--accent) 40%, transparent)",
              display: "flex", flexDirection: "column", justifyContent: "space-between",
            }}>
              <div>
                <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                  <Icon name="link" size={13}/>
                  <span style={{ fontSize: 11, fontWeight: 580, opacity: 0.9, textTransform: "uppercase", letterSpacing: "0.04em" }}>Lien public</span>
                </div>
                <div style={{ fontSize: 13, fontWeight: 580, marginTop: 6, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                  clientbase.fr/?book=lea
                </div>
              </div>
              <div style={{ fontSize: 11, opacity: 0.92, fontWeight: 500 }}>
                📲 3 RDV pris cette semaine
              </div>
            </div>
          </div>
        </div>

        {/* Bandeau réassurance, défile en marquee continu. Chaque pilier
            a son "clin d'œil" SVG (jamais d'emoji) :
            - France → drapeau tricolore dans les lettres (Fr bleu / an blanc / ce rouge)
            - RGPD   → cadenas (chiffré)
            - 24 h   → horloge
            - 0 €    → cadeau
            Voir CbTrustBand + sub-icons dans shared.jsx (~ligne 1585). */}
        {window.CbTrustBand && React.createElement(window.CbTrustBand, {
          tone: "accent",
          items: [
            { title: window.CbTitleFrance ? React.createElement(window.CbTitleFrance) : "France",
              sub: "Conçu & hébergé en France" },
            { title: window.CbTitleWithIcon
                ? React.createElement(window.CbTitleWithIcon, {
                    icon: React.createElement(window.CbIconLock),
                    label: "RGPD",
                    color: "var(--accent)",
                  })
                : "RGPD",
              sub: "Vos données chiffrées" },
            { title: window.CbTitleWithIcon
                ? React.createElement(window.CbTitleWithIcon, {
                    icon: React.createElement(window.CbIconClock),
                    label: "24 h",
                    color: "var(--accent)",
                  })
                : "24 h",
              sub: "Support humain en français" },
            { title: window.CbTitleWithIcon
                ? React.createElement(window.CbTitleWithIcon, {
                    icon: React.createElement(window.CbIconGift),
                    label: "0 €",
                    color: "var(--accent)",
                  })
                : "0 €",
              sub: "Pendant toute la bêta" },
          ],
        })}

        {/* Flow arrow vers la suite */}
        <div style={{ marginTop: 56, textAlign: "center" }}>
          <FlowArrow step={1} totalSteps={3}
            caption="Commençons par explorer tout ce que ClientBase propose"/>
        </div>

        <Reveal delay={0.1}>
          <div id="features-preview">
            <FeatureCarousel/>
          </div>
        </Reveal>
      </div>
    </section>
  );
};

/* ================================================================
   FEATURE CAROUSEL, replaces the LiveDemo phone mockup
================================================================ */
// Chaque feature a sa "tone" qui colorie l'icône + la radial dans le card.
// Les couleurs correspondent à celles de GuideSection (pages-a.jsx) pour
// que l'utilisateur retrouve les mêmes codes couleurs partout sur le site.
// Palette vitrine canonique : on cycle indigo → rose → sauge sur les 7 features
// pour donner du rythme sans dépasser les 3 couleurs de la palette.
const FEATURES = [
  { id: "agenda",   icon: "calendar", name: "Agenda",        tone: "accent", desc: "Un agenda clair et interactif. Cliquez sur une case vide pour ajouter un RDV, marquez-le fait en un clic." },
  { id: "bookings", icon: "link",     name: "Prise de RDV",  tone: "sage",   desc: "Votre lien public à partager. Vos clients choisissent leur créneau elles-mêmes, pauses déjeuner et vacances respectées." },
  { id: "clients",  icon: "users",    name: "Clientes",      tone: "rose",   desc: "Toutes leurs infos, préférences et historique au même endroit. Contact direct par mail ou téléphone en un clic." },
  { id: "fidelite", icon: "gift",     name: "Fidélité",      tone: "accent", desc: "Une carte numérique par client. Partagez un lien, elle suit sa progression en temps réel, vos règles à vous." },
  { id: "stats",    icon: "chart",    name: "Statistiques",  tone: "sage",   desc: "CA, prestations rentables, tendances. Graphiques interactifs, sans tableur Excel." },
  { id: "factures", icon: "invoice",  name: "Facturation",   tone: "rose",   desc: "Factures conformes aux normes françaises. SIRET, TVA, mentions légales, on s'occupe de tout." },
  { id: "stock",    icon: "box",      name: "Stock",         tone: "accent", desc: "Alertes stock bas, ajustements rapides, vue d'ensemble de vos produits." },
];

// Mapping local,3 tones uniquement (palette vitrine canonique).
const HERO_TONE = {
  accent: { bg: "var(--accent-soft)", ink: "var(--accent-ink)", solid: "var(--accent)" },
  rose:   { bg: "var(--rose-soft)",   ink: "var(--rose-ink)",   solid: "var(--rose)"   },
  sage:   { bg: "var(--sage-soft)",   ink: "var(--sage-ink)",   solid: "var(--sage)"   },
};

const FeatureCard = ({ f, compact }) => {
  const tone = HERO_TONE[f.tone] || HERO_TONE.accent;
  // Hover : légère élévation + ombre douce teintée par la tone du module.
  // Géré en state local pour pouvoir colorer dynamiquement le box-shadow
  // (impossible en pure CSS sans définir une classe par tone).
  const [hover, setHover] = React.useState(false);
  return (
  <div
    className="cb-module-card"
    onMouseEnter={() => setHover(true)}
    onMouseLeave={() => setHover(false)}
    style={{
      background: "var(--surface)",
      border: "1px solid var(--line)",
      borderRadius: 16,
      padding: compact ? 22 : 28,
      boxShadow: hover
        ? `0 14px 32px -18px color-mix(in oklab, var(--accent) 60%, transparent), var(--sh-2)`
        : "var(--sh-2)",
      // height fixe (pas min-height) → toutes les cards EXACTEMENT
      // la même taille, peu importe la longueur du desc ou du mock.
      // .cb-module-card en CSS gère le mobile à part.
      height: compact ? 480 : 520,
      position: "relative", overflow: "hidden",
      width: "100%", boxSizing: "border-box",
      textAlign: "center",
      transform: hover ? "translateY(-3px)" : "translateY(0)",
      transition: "transform .25s cubic-bezier(.22,1,.36,1), box-shadow .25s ease",
  }}>
    {/* Halo radial TOUJOURS bleu de marque (var(--accent-soft)) côté pro,
        peu importe la tone du module — la teinte décorative reste sur la
        couleur de l'audience, pas sur celle du module (qui peut être
        rose, sage, etc.). */}
    <div aria-hidden style={{
      position: "absolute", top: -40, left: "50%", transform: "translateX(-50%)",
      width: 280, height: 160, borderRadius: "50%",
      background: `radial-gradient(circle, var(--accent-soft) 0%, transparent 70%)`,
      opacity: 0.6, pointerEvents: "none",
    }}/>
    {/* Layout : header (icon + nom + desc) pinned EN HAUT, mock dans le
        reste vertical avec centrage. Pour que le header soit TOUJOURS au
        même endroit (haut centré) peu importe la longueur du desc, et
        que le mock s'adapte au milieu de la zone restante. */}
    <div style={{
      position: "relative", display: "flex", flexDirection: "column",
      alignItems: "center", height: "100%",
      gap: compact ? 14 : 18,
    }}>
      <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 12, flexShrink: 0 }}>
        <div style={{
          width: 52, height: 52, borderRadius: 14,
          background: tone.bg, color: tone.ink,
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}>
          <Icon name={f.icon} size={26}/>
        </div>
        <h3 style={{
          fontSize: "clamp(22px, 2.6vw, 28px)", margin: 0,
          letterSpacing: "-0.02em",
        }}>{f.name}</h3>
        <p style={{
          margin: 0, fontSize: 15, color: "var(--ink-2)",
          lineHeight: 1.55, maxWidth: 520,
        }}>
          {f.desc}
        </p>
      </div>
      {/* Le mock prend tout l'espace vertical restant et se centre.
          Cadré dans une « shell » bg-alt + border arrondie qui donne
          une vraie impression de capture d'écran encadrée — uniforme
          pour tous les modules, peu importe le contenu interne. */}
      <div style={{
        flex: 1,
        display: "flex", alignItems: "center", justifyContent: "center",
        width: "100%",
        maxWidth: compact ? 320 : 360,
        margin: "0 auto",
        minHeight: 0,
      }}>
        <div style={{
          width: "100%",
          padding: 10,
          background: "var(--bg-alt)",
          border: "1px solid var(--line)",
          borderRadius: 14,
          boxShadow: "inset 0 1px 0 rgba(255,255,255,0.6), 0 2px 6px -3px rgba(15,18,30,0.06)",
        }}>
          <FeatureMock id={f.id}/>
        </div>
      </div>
    </div>
  </div>
  );
};

const FeatureCarousel = () => {
  const isMobile = useIsMobile(720);
  const [idx, setIdx] = React.useState(0);
  const [auto, setAuto] = React.useState(true);
  const scrollRef = React.useRef(null);
  const programmaticRef = React.useRef(false);

  // Auto-advance only on desktop, never on mobile (avoids conflicts with user swipe)
  React.useEffect(() => {
    if (!auto || isMobile) return;
    const t = setInterval(() => setIdx(i => (i + 1) % FEATURES.length), 4500);
    return () => clearInterval(t);
  }, [auto, isMobile]);

  // Desktop pill/dot click: just update idx. Mobile dot click: also programmatically scroll.
  const pick = (i) => {
    setIdx(i);
    setAuto(false);
    if (isMobile && scrollRef.current) {
      const el = scrollRef.current;
      const card = el.children[i];
      if (card) {
        programmaticRef.current = true;
        // Centre la carte dans le scrollport (compense gap + padding)
        const target = card.offsetLeft - (el.clientWidth - card.clientWidth) / 2;
        el.scrollTo({ left: Math.max(0, target), behavior: "smooth" });
        setTimeout(() => { programmaticRef.current = false; }, 600);
      }
    }
  };

  // Mobile swipe handler, détermine l'index par la carte la plus proche du centre
  const handleScroll = () => {
    if (programmaticRef.current) return;
    if (!scrollRef.current) return;
    const el = scrollRef.current;
    const center = el.scrollLeft + el.clientWidth / 2;
    let nearest = 0, best = Infinity;
    for (let i = 0; i < el.children.length; i++) {
      const c = el.children[i];
      const cCenter = c.offsetLeft + c.clientWidth / 2;
      const d = Math.abs(cCenter - center);
      if (d < best) { best = d; nearest = i; }
    }
    if (nearest !== idx && nearest < FEATURES.length) setIdx(nearest);
  };

  const current = FEATURES[idx];

  if (isMobile) {
    return (
      <div style={{ maxWidth: 720, margin: "0 auto" }}>
        {/* Small helper, just an invitation, no scrollbar */}
        <div style={{
          textAlign: "center", marginBottom: 14,
          fontSize: 13, color: "var(--ink-4)",
          fontStyle: "italic", fontFamily: "var(--ff-display)",
          display: "flex", alignItems: "center", justifyContent: "center", gap: 8,
        }}>
          <span aria-hidden>←</span>
          glissez pour explorer les {FEATURES.length} modules
          <span aria-hidden>→</span>
        </div>

        {/* Scroll-snap swipe carousel */}
        <div
          ref={scrollRef}
          onScroll={handleScroll}
          className="cb-hide-scrollbar"
          style={{
            display: "flex", gap: 12,
            overflowX: "auto",
            scrollSnapType: "x mandatory",
            WebkitOverflowScrolling: "touch",
            marginLeft: -16, marginRight: -16,
            paddingLeft: 16, paddingRight: 16,
            scrollbarWidth: "none",
          }}
        >
          {FEATURES.map((f) => (
            <div key={f.id} style={{
              flexShrink: 0,
              width: "calc(100% - 32px)",
              scrollSnapAlign: "center",
              scrollSnapStop: "always",
            }}>
              <FeatureCard f={f} compact/>
            </div>
          ))}
        </div>

        {/* Dots, clickable for jump nav */}
        <div style={{
          marginTop: 20, display: "flex", gap: 6, justifyContent: "center",
        }}>
          {FEATURES.map((_, i) => (
            <button key={i} onClick={() => pick(i)} aria-label={`Module ${i + 1}`}
              style={{
                width: i === idx ? 24 : 7, height: 7,
                borderRadius: 999,
                background: i === idx ? "var(--accent)" : "var(--line-strong)",
                border: "none", cursor: "pointer", padding: 0,
                transition: "width 0.2s, background 0.2s",
              }}
            />
          ))}
        </div>
      </div>
    );
  }

  // ===== Desktop version, pills + card + dots =====
  return (
    <div style={{ maxWidth: 720, margin: "0 auto" }}>
      <div style={{
        display: "flex", gap: 6, flexWrap: "wrap", justifyContent: "center",
      }}>
        {FEATURES.map((f, i) => {
          const active = i === idx;
          return (
            <button key={f.id} onClick={() => pick(i)} style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              padding: "7px 13px",
              // Active = indigo de marque (--accent) côté vitrine pro.
              background: active ? "var(--accent)" : "var(--surface)",
              color: active ? "white" : "var(--ink-2)",
              border: "1px solid " + (active ? "var(--accent)" : "var(--line)"),
              borderRadius: 999,
              fontSize: 12.5, fontWeight: active ? 580 : 500,
              cursor: "pointer", fontFamily: "inherit",
              boxShadow: active ? "0 6px 18px -8px var(--accent)" : "none",
              transition: "all 0.18s ease",
            }}>
              <Icon name={f.icon} size={13}/> {f.name}
            </button>
          );
        })}
      </div>

      <div style={{ marginTop: 16 }}>
        <div key={current.id} style={{ animation: "cbFadeSlide 0.35s ease" }}>
          <FeatureCard f={current}/>
        </div>
      </div>

      <div style={{
        marginTop: 18, display: "flex", gap: 6, justifyContent: "center",
      }}>
        {FEATURES.map((_, i) => (
          <button key={i} onClick={() => pick(i)} aria-label={`Module ${i + 1}`}
            style={{
              width: i === idx ? 20 : 6, height: 6,
              borderRadius: 999,
              background: i === idx ? "var(--accent)" : "var(--line-strong)",
              border: "none", cursor: "pointer", padding: 0,
              transition: "width 0.2s, background 0.2s",
            }}
          />
        ))}
      </div>
    </div>
  );
};

/* Tiny interactive mocks per feature, clickable to feel the product */

const AgendaMock = () => {
  const [done, setDone] = React.useState({});
  const list = [
    { time: "09:00", name: "Léa Morel",     svc: "Gel semi-perm.", c: ["var(--accent-soft)", "var(--accent)", "var(--accent-ink)"] },
    { time: "10:30", name: "Camille Petit", svc: "Pose complète",  c: ["var(--sage-soft)", "var(--sage)", "oklch(38% 0.08 160)"] },
    { time: "14:00", name: "Inès Dubois",   svc: "Remplissage",    c: ["oklch(97% 0.025 30)", "oklch(70% 0.14 30)", "oklch(42% 0.14 30)"] },
  ];
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      {list.map((a, i) => {
        const d = done[i];
        return (
          <button key={i} onClick={() => setDone(s => ({ ...s, [i]: !s[i] }))} style={{
            padding: "8px 12px", background: a.c[0],
            borderLeft: `3px solid ${a.c[1]}`, borderRadius: 6,
            borderTop: "1px solid transparent", borderRight: "1px solid transparent", borderBottom: "1px solid transparent",
            fontSize: 12, display: "flex", gap: 10, alignItems: "center",
            cursor: "pointer", textAlign: "left", width: "100%",
            opacity: d ? 0.55 : 1, transition: "opacity .2s",
          }}>
            <span style={{ color: a.c[2], fontWeight: 600, minWidth: 40, fontVariantNumeric: "tabular-nums" }}>{a.time}</span>
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 520, color: "var(--ink)", textDecoration: d ? "line-through" : "none" }}>{a.name}</div>
              <div style={{ fontSize: 11, color: "var(--ink-4)" }}>{a.svc}</div>
            </div>
            <span style={{
              width: 18, height: 18, borderRadius: 50,
              background: d ? a.c[1] : "transparent",
              border: `1.5px solid ${a.c[1]}`,
              display: "flex", alignItems: "center", justifyContent: "center",
              color: "white", flexShrink: 0,
            }}>
              {d && <Icon name="check" size={10} stroke={3}/>}
            </span>
          </button>
        );
      })}
      <div style={{ fontSize: 10.5, color: "var(--ink-4)", textAlign: "center", marginTop: 2 }}>
        Cliquez pour marquer fait
      </div>
    </div>
  );
};

const ClientsMock = () => {
  const [hl, setHl] = React.useState(null);
  const list = [
    { n: "Léa Morel",   v: 14, hue: 30,  mail: "lea@exemple.fr",   tel: "06 12 34 56 78" },
    { n: "Inès Dubois", v: 22, hue: 220, mail: "ines@exemple.fr",  tel: "06 98 76 54 32" },
    { n: "Sarah B.",    v: 5,  hue: 180, mail: "sarah@exemple.fr", tel: "06 11 22 33 44" },
  ];
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      {list.map((c, i) => (
        <div key={i} style={{
          display: "flex", alignItems: "center", gap: 10,
          padding: "8px 10px", background: "var(--bg-alt)",
          border: "1px solid var(--line)", borderRadius: 8, fontSize: 12,
        }}>
          <div style={{
            width: 28, height: 28, borderRadius: 50,
            background: `linear-gradient(135deg, oklch(80% 0.12 ${c.hue}), oklch(70% 0.14 ${(c.hue+40)%360}))`,
            color: "white", display: "flex", alignItems: "center", justifyContent: "center",
            fontSize: 10.5, fontWeight: 600, flexShrink: 0,
          }}>{c.n.split(" ").map(x => x[0]).join("")}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 520, color: "var(--ink)" }}>{c.n}</div>
            <div style={{ fontSize: 10.5, color: "var(--ink-4)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
              {hl && hl.i === i ? (hl.k === "mail" ? c.mail : c.tel) : `${c.v} visites`}
            </div>
          </div>
          <button onClick={() => setHl({ i, k: "mail" })} style={{
            width: 26, height: 26, borderRadius: 6, cursor: "pointer",
            background: hl && hl.i === i && hl.k === "mail" ? "var(--accent)" : "var(--surface)",
            color: hl && hl.i === i && hl.k === "mail" ? "white" : "var(--ink-3)",
            border: "1px solid var(--line)",
            display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
          }} aria-label="Mail"><Icon name="mail" size={12}/></button>
          <button onClick={() => setHl({ i, k: "tel" })} style={{
            width: 26, height: 26, borderRadius: 6, cursor: "pointer",
            background: hl && hl.i === i && hl.k === "tel" ? "var(--accent)" : "var(--surface)",
            color: hl && hl.i === i && hl.k === "tel" ? "white" : "var(--ink-3)",
            border: "1px solid var(--line)",
            display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
          }} aria-label="Téléphone"><Icon name="phone" size={12}/></button>
        </div>
      ))}
    </div>
  );
};

const BookingsMock = () => {
  const [sel, setSel] = React.useState(1);
  const [copied, setCopied] = React.useState(false);
  const copy = () => { setCopied(true); setTimeout(() => setCopied(false), 1400); };
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
      <button onClick={copy} style={{
        padding: "8px 12px", background: "var(--bg-alt)",
        border: "1px solid var(--line)", borderRadius: 8,
        display: "flex", alignItems: "center", gap: 8,
        fontSize: 12, cursor: "pointer", textAlign: "left", width: "100%",
      }}>
        <Icon name="link" size={12} style={{ color: "var(--accent-ink)", flexShrink: 0 }}/>
        <span style={{ flex: 1, color: "var(--ink-2)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
          clientbase.fr/?book=ongles-by-lea
        </span>
        <span style={{
          padding: "2px 8px", background: copied ? "var(--sage)" : "var(--ink)", color: "var(--bg)",
          borderRadius: 4, fontSize: 10, fontWeight: 600, transition: "background .2s",
        }}>{copied ? "Copié ✓" : "Copier"}</span>
      </button>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 4 }}>
        {["09:00", "10:30", "14:00", "15:30"].map((t, i) => (
          <button key={i} onClick={() => setSel(i)} style={{
            padding: "6px 4px", textAlign: "center", cursor: "pointer",
            background: i === sel ? "var(--accent)" : "var(--surface)",
            color: i === sel ? "white" : "var(--ink-2)",
            border: "1px solid " + (i === sel ? "var(--accent)" : "var(--line)"),
            borderRadius: 6, fontSize: 12, fontWeight: 520, fontVariantNumeric: "tabular-nums",
            transition: "all .15s",
          }}>{t}</button>
        ))}
      </div>
    </div>
  );
};

const FideliteMock = () => {
  const [stamps, setStamps] = React.useState(8);
  const [copied, setCopied] = React.useState(false);
  const copy = () => { setCopied(true); setTimeout(() => setCopied(false), 1400); };
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <div style={{
        padding: 16,
        background: "linear-gradient(135deg, var(--accent) 0%, oklch(45% 0.22 288) 100%)",
        borderRadius: 10, color: "white",
      }}>
        <div style={{ fontSize: 10.5, opacity: 0.85, textTransform: "uppercase", letterSpacing: "0.08em" }}>Léa Morel</div>
        <div style={{ marginTop: 12, display: "grid", gridTemplateColumns: "repeat(10, 1fr)", gap: 4 }}>
          {Array.from({ length: 10 }).map((_, i) => (
            <button key={i} onClick={() => setStamps(i + 1 === stamps ? i : i + 1)} style={{
              aspectRatio: 1, borderRadius: 50, padding: 0, cursor: "pointer",
              background: i < stamps ? "rgba(255,255,255,0.95)" : "rgba(255,255,255,0.15)",
              border: i >= stamps ? "1.5px dashed rgba(255,255,255,0.4)" : "1.5px solid transparent",
              display: "flex", alignItems: "center", justifyContent: "center",
              color: "var(--accent)", transition: "all .18s",
            }}>
              {i < stamps && <Icon name="check" size={10} stroke={3}/>}
            </button>
          ))}
        </div>
      </div>
      <button onClick={copy} style={{
        padding: "7px 10px", background: "var(--bg-alt)",
        border: "1px solid var(--line)", borderRadius: 8, cursor: "pointer",
        display: "flex", alignItems: "center", gap: 8, fontSize: 11.5, color: "var(--ink-2)",
        width: "100%",
      }}>
        <Icon name="link" size={11} style={{ color: "var(--accent-ink)" }}/>
        <span style={{ flex: 1, textAlign: "left" }}>Partager la carte à Léa</span>
        <span style={{
          padding: "2px 7px", background: copied ? "var(--sage)" : "var(--ink)", color: "var(--bg)",
          borderRadius: 4, fontSize: 10, fontWeight: 600,
        }}>{copied ? "Copié ✓" : "Copier"}</span>
      </button>
    </div>
  );
};

// StatsMock v2 : dashboard 3 KPIs (CA, RDV, Nouveaux clients) avec toggle
// période (7j / 30j / 12 mois) qui anime les chiffres + sparkline en bas.
// Plus visuel et plus parlant qu'un simple bar chart : on voit l'activité
// d'un coup d'œil + on peut basculer entre les périodes pour comparer.
const StatsMock = () => {
  const [period, setPeriod] = React.useState("month");
  const periods = [
    { key: "week",  label: "7 j" },
    { key: "month", label: "30 j" },
    { key: "year",  label: "12 mois" },
  ];
  // Data par période : { ca, rdv, newClients, delta, spark[] }
  const data = {
    week:  { ca: "1 240 €",  rdv: 18,  nc: 3,  delta: "+12 %", spark: [3,5,4,7,6,8,9] },
    month: { ca: "4 850 €",  rdv: 72,  nc: 11, delta: "+23 %", spark: [6,8,5,9,7,11,9,12,10,14] },
    year:  { ca: "52 300 €", rdv: 840, nc: 96, delta: "+38 %", spark: [3,4,5,4,6,5,7,8,7,9,10,12] },
  };
  const d = data[period];
  const maxSpark = Math.max(...d.spark);

  return (
    <div style={{
      padding: 14, background: "var(--surface)",
      border: "1px solid var(--line)", borderRadius: 10,
    }}>
      {/* Toggle période */}
      <div style={{
        display: "flex", gap: 3, padding: 3,
        background: "var(--bg-alt)", border: "1px solid var(--line)",
        borderRadius: 999, marginBottom: 12,
      }}>
        {periods.map(p => {
          const active = p.key === period;
          return (
            <button key={p.key}
              onClick={() => setPeriod(p.key)}
              style={{
                flex: 1, padding: "5px 8px",
                background: active ? "var(--accent)" : "transparent",
                color: active ? "#fff" : "var(--ink-3)",
                border: "none", borderRadius: 999,
                fontSize: 11, fontWeight: 580, cursor: "pointer", fontFamily: "inherit",
                transition: "background .18s ease, color .18s ease",
                boxShadow: active ? "0 3px 8px -3px var(--accent)" : "none",
              }}>
              {p.label}
            </button>
          );
        })}
      </div>

      {/* 3 KPIs en ligne */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8, marginBottom: 10 }}>
        {[
          { label: "CA",       value: d.ca,  delta: d.delta },
          { label: "RDV",      value: d.rdv, sub: "réservés" },
          { label: "Nouveaux", value: d.nc,  sub: "clients" },
        ].map(k => (
          <div key={k.label} style={{
            padding: "8px 9px",
            background: "var(--bg-alt)", borderRadius: 8,
            display: "flex", flexDirection: "column", gap: 2,
            minWidth: 0,
          }}>
            <div style={{ fontSize: 9.5, color: "var(--ink-4)", textTransform: "uppercase", letterSpacing: "0.04em", fontWeight: 600 }}>
              {k.label}
            </div>
            <div key={period + k.label} style={{
              fontFamily: "var(--ff-display)", fontSize: 14, fontWeight: 600,
              color: "var(--ink)", letterSpacing: "-0.018em",
              fontVariantNumeric: "tabular-nums",
              whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
              animation: "cbStatsBounce .35s cubic-bezier(.5,1.6,.4,1) both",
            }}>
              {k.value}
            </div>
            {k.delta && (
              <div style={{
                fontSize: 9.5, fontWeight: 600,
                color: "var(--sage)",
              }}>{k.delta}</div>
            )}
            {k.sub && (
              <div style={{ fontSize: 9.5, color: "var(--ink-4)" }}>{k.sub}</div>
            )}
          </div>
        ))}
      </div>

      {/* Sparkline qui s'anime au changement de période */}
      <div key={period} style={{
        display: "flex", alignItems: "flex-end", gap: 3, height: 32,
        animation: "cbStatsFade .35s ease both",
      }}>
        {d.spark.map((v, i) => (
          <div key={i} style={{
            flex: 1, height: `${(v / maxSpark) * 100}%`,
            background: `linear-gradient(180deg, var(--accent) 0%, color-mix(in oklab, var(--accent) 50%, var(--bg-alt)) 100%)`,
            borderRadius: 3,
            minHeight: 4,
            animation: `cbStatsBarIn .4s ${i * 0.03}s cubic-bezier(.22,1,.36,1) both`,
            transformOrigin: "bottom",
          }}/>
        ))}
      </div>
      <style>{`
        @keyframes cbStatsBounce {
          from { opacity: 0; transform: translateY(4px) scale(0.95); }
          60%  { transform: translateY(0) scale(1.05); }
          to   { opacity: 1; transform: translateY(0) scale(1); }
        }
        @keyframes cbStatsFade { from { opacity: 0; } to { opacity: 1; } }
        @keyframes cbStatsBarIn {
          from { transform: scaleY(0); opacity: 0; }
          to   { transform: scaleY(1); opacity: 1; }
        }
      `}</style>
    </div>
  );
};

const FacturesMock = () => {
  const [paid, setPaid] = React.useState([true, true, false]);
  const rows = [
    ["F-0142", "Léa Morel",     "45,00 €"],
    ["F-0141", "Camille Petit", "60,00 €"],
    ["F-0140", "Inès Dubois",   "38,00 €"],
  ];
  return (
    <div style={{
      border: "1px solid var(--line)", borderRadius: 10, overflow: "hidden",
      background: "var(--surface)",
    }}>
      {rows.map(([id, name, amt], i) => (
        <div key={id} style={{
          padding: "9px 12px", fontSize: 12,
          display: "flex", alignItems: "center", gap: 10,
          borderBottom: i < 2 ? "1px solid var(--line)" : "none",
        }}>
          <span style={{ color: "var(--ink-4)", fontSize: 11.5, fontWeight: 500, fontVariantNumeric: "tabular-nums" }}>{id}</span>
          <span style={{ flex: 1, fontWeight: 520 }}>{name}</span>
          <span style={{ fontWeight: 600, fontVariantNumeric: "tabular-nums" }}>{amt}</span>
          <button onClick={() => setPaid(p => p.map((v, j) => j === i ? !v : v))} style={{
            padding: "2px 7px", fontSize: 10, fontWeight: 600, borderRadius: 4, cursor: "pointer",
            background: paid[i] ? "var(--sage-soft)" : "var(--warn-soft)",
            color: paid[i] ? "oklch(38% 0.08 160)" : "var(--warn-ink)",
            border: "none", transition: "background .15s",
          }}>{paid[i] ? "Payée" : "En attente"}</button>
        </div>
      ))}
    </div>
  );
};

const StockMock = () => {
  const [qty, setQty] = React.useState([12, 3, 6]);
  const items = ["Base coat OPI", "Top coat Gelish", "Vernis nude 42"];
  const bump = (i, d) => setQty(q => q.map((v, j) => j === i ? Math.max(0, v + d) : v));
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      {items.map((n, i) => {
        const ok = qty[i] >= 5;
        return (
          <div key={i} style={{
            display: "flex", alignItems: "center", gap: 8,
            padding: "8px 12px", background: "var(--bg-alt)",
            border: "1px solid var(--line)", borderRadius: 8, fontSize: 12,
          }}>
            <div style={{ flex: 1, fontWeight: 520 }}>{n}</div>
            <button onClick={() => bump(i, -1)} style={{
              width: 22, height: 22, borderRadius: 5, border: "1px solid var(--line)",
              background: "var(--surface)", color: "var(--ink-2)", cursor: "pointer",
              display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 600,
            }}>−</button>
            <div style={{ minWidth: 22, textAlign: "center", color: "var(--ink-2)", fontWeight: 600, fontVariantNumeric: "tabular-nums" }}>{qty[i]}</div>
            <button onClick={() => bump(i, +1)} style={{
              width: 22, height: 22, borderRadius: 5, border: "1px solid var(--line)",
              background: "var(--surface)", color: "var(--ink-2)", cursor: "pointer",
              display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 600,
            }}>+</button>
            <span style={{
              padding: "2px 7px", fontSize: 10, fontWeight: 600, borderRadius: 4,
              background: ok ? "var(--sage-soft)" : "oklch(96% 0.04 30)",
              color: ok ? "oklch(38% 0.08 160)" : "oklch(48% 0.18 30)",
              transition: "all .15s",
            }}>{ok ? "OK" : "Bas"}</span>
          </div>
        );
      })}
    </div>
  );
};

const FeatureMock = ({ id }) => {
  if (id === "agenda")   return <AgendaMock/>;
  if (id === "clients")  return <ClientsMock/>;
  if (id === "bookings") return <BookingsMock/>;
  if (id === "fidelite") return <FideliteMock/>;
  if (id === "stats")    return <StatsMock/>;
  if (id === "factures") return <FacturesMock/>;
  if (id === "stock")    return <StockMock/>;
  return null;
};

/* ================================================================
   SAVINGS SIMULATOR, transparent calculations, explained hypotheses
================================================================ */
// Hypotheses (sources publiques, avril 2026) :
//   - 3 min gagnées par client (rappels SMS + réservation en ligne + fiche auto)
//   - avgTicket ~45 € (moyenne observée chez les indépendant·es prestation/esthétique)
//   - retentionBoost = +12 % de visites/an (étude NailPro 2023 sur les rappels auto)
//   - no-show : 7 % en moyenne avant, réduit à 2 % avec les rappels automatiques
//     (source : NoShow.fr baromètre 2024)
//   - toolsReplaced = 50 €/mois (Planity Essentiel)
//   - workDayHours = 7 h (journée type indé)
const SAVINGS_HYPOTHESES = {
  minPerClient: 3,
  avgTicket: 45,
  toolsReplaced: 50,
  retentionBoost: 0.12,
  avgVisitsPerClient: 3,
  noShowBefore: 0.07,
  noShowAfter: 0.02,
  workDayHours: 7,
};

const _fmtEUR = (n) => `${Math.round(n).toLocaleString("fr-FR")} €`;

const SavingsSimulator = () => {
  const [clients, setClients] = React.useState(60);
  const [ticket, setTicket] = React.useState(45);
  const [showDetails, setShowDetails] = React.useState(false);

  const h = SAVINGS_HYPOTHESES;
  const hoursPerMonth   = (clients * h.minPerClient) / 60;
  const hoursPerYear    = hoursPerMonth * 12;
  const daysPerYear     = hoursPerYear / h.workDayHours;

  const toolSavedYear   = h.toolsReplaced * 12;

  const extraVisitsYear = clients * h.avgVisitsPerClient * h.retentionBoost;
  const retentionRevYear= extraVisitsYear * ticket;

  const noShowAvoidedYr = clients * 12 * (h.noShowBefore - h.noShowAfter);
  const noShowRevenue   = noShowAvoidedYr * ticket;

  // Bonus : RDV pris tout seuls via le lien public (≈ 40 % des RDV, étude Planity 2024)
  const onlineShare     = 0.40;
  const onlineBookings  = Math.round(clients * 12 * onlineShare);

  // Bonus : appels téléphoniques évités (≈ 60 % des prises de RDV passaient par téléphone)
  const callsAvoided    = Math.round(clients * 12 * 0.6);

  const totalGainYear   = toolSavedYear + retentionRevYear + noShowRevenue;

  return (
    <section id="simulator" style={{ padding: "40px 0 48px" }}>
      <div className="container">
        <div style={{ maxWidth: 760, margin: "0 auto", textAlign: "center" }}>
          <h2 style={{ fontSize: "clamp(28px, 3.4vw, 42px)", letterSpacing: "-0.03em" }}>
            Combien pouvez-vous <span style={{ color: "var(--accent)" }}>générer avec ClientBase</span>&nbsp;?
          </h2>
          <p style={{
            marginTop: 8, fontSize: 14.5, color: "var(--ink-3)",
            maxWidth: 480, margin: "8px auto 0", lineHeight: 1.5,
          }}>
            Bougez les curseurs, les chiffres s'ajustent en direct sur vos vrais volumes.
          </p>

          {/* Sliders block */}
          <div style={{
            marginTop: 20, padding: "20px 22px",
            background: "var(--surface)", border: "1px solid var(--line)",
            borderRadius: 16,
            textAlign: "left",
          }}>
            <SimSlider
              label="Vous voyez environ"
              suffix="clients/mois"
              value={clients} min={10} max={250} step={5}
              ticks={["10", "80", "150", "250"]}
              onChange={setClients}
            />
            <div style={{ height: 10 }}/>
            <SimSlider
              label="Panier moyen"
              suffix="€ / prestation"
              value={ticket} min={15} max={150} step={5}
              ticks={["15 €", "60 €", "100 €", "150 €"]}
              onChange={setTicket}
            />
          </div>

          {/* HERO « Gain estimé » — fond enrichi :
              - Gradient principal indigo profond → violet brand
              - 2 halos radiaux blancs translucides (un large + un compact)
                qui se croisent en haut-droite pour donner de la profondeur
              - Un motif SVG dot-grid subtil en fond (texture sans peser)
              - Une bande de lumière diagonale qui glisse lentement en arrière
              - Un bord intérieur lumineux (inset ring) qui « décolle » la
                carte du reste de la page
              Couches additives, peu coûteuses, donnent une vraie sensation
              « écran premium » sans alourdir le rendu. */}
          <div style={{
            marginTop: 14, padding: "26px 28px",
            background: `
              radial-gradient(ellipse 70% 55% at 95% 0%, rgba(255,255,255,0.22), transparent 65%),
              radial-gradient(ellipse 60% 90% at 105% 100%, rgba(255,255,255,0.10), transparent 60%),
              linear-gradient(135deg, var(--accent) 0%, oklch(45% 0.22 288) 50%, oklch(38% 0.20 295) 100%)
            `,
            borderRadius: 20,
            color: "white",
            position: "relative",
            overflow: "hidden",
            textAlign: "left",
            boxShadow: `
              inset 0 1px 0 rgba(255,255,255,0.18),
              inset 0 -1px 0 rgba(0,0,0,0.18),
              0 22px 50px -22px color-mix(in oklab, var(--accent) 70%, transparent)
            `,
          }}>
            {/* Motif dot-grid subtil en fond (8px de répétition) */}
            <div aria-hidden style={{
              position: "absolute", inset: 0,
              backgroundImage: "radial-gradient(circle, rgba(255,255,255,0.10) 1px, transparent 1.5px)",
              backgroundSize: "14px 14px",
              backgroundPosition: "0 0",
              opacity: 0.5,
              pointerEvents: "none",
              maskImage: "linear-gradient(to bottom, transparent 0%, black 30%, black 70%, transparent 100%)",
              WebkitMaskImage: "linear-gradient(to bottom, transparent 0%, black 30%, black 70%, transparent 100%)",
            }}/>
            {/* Lueur orbiculaire animée en bas-gauche */}
            <div aria-hidden style={{
              position: "absolute", bottom: -60, left: -60,
              width: 200, height: 200, borderRadius: "50%",
              background: "radial-gradient(circle, rgba(255,255,255,0.22) 0%, transparent 60%)",
              pointerEvents: "none",
              animation: "cbGainGlow 7s ease-in-out infinite",
            }}/>
            {/* Bande de lumière diagonale qui balaie lentement le fond */}
            <div aria-hidden style={{
              position: "absolute", inset: 0,
              background: "linear-gradient(115deg, transparent 30%, rgba(255,255,255,0.10) 50%, transparent 70%)",
              pointerEvents: "none",
              animation: "cbGainShine 9s ease-in-out infinite",
              transformOrigin: "center",
            }}/>
            {/* Étincelles ✦ flottantes pour le côté « gain magique » */}
            <div aria-hidden style={{
              position: "absolute", top: 14, right: 22,
              fontSize: 18, opacity: 0.42,
              animation: "cbGainSpark 4s ease-in-out infinite",
            }}>✦</div>
            <div aria-hidden style={{
              position: "absolute", top: 64, right: 90,
              fontSize: 12, opacity: 0.3,
              animation: "cbGainSpark 5.5s ease-in-out infinite 0.7s",
            }}>✦</div>

            <div style={{ position: "relative", zIndex: 1 }}>
              <div style={{
                display: "inline-flex", alignItems: "center", gap: 7,
                padding: "4px 11px 4px 9px",
                background: "rgba(255,255,255,0.18)",
                border: "1px solid rgba(255,255,255,0.28)",
                borderRadius: 999,
                fontSize: 11.5, fontWeight: 600,
                textTransform: "uppercase", letterSpacing: "0.08em",
                color: "rgba(255,255,255,0.96)",
                backdropFilter: "blur(6px)",
                WebkitBackdropFilter: "blur(6px)",
              }}>
                <span style={{
                  width: 6, height: 6, borderRadius: 50,
                  background: "#fff",
                  boxShadow: "0 0 8px rgba(255,255,255,0.8)",
                  animation: "cbPulse 1.8s ease-in-out infinite",
                }}/>
                Gain estimé
              </div>
              <div style={{
                fontFamily: "var(--ff-display)", fontWeight: 600,
                fontSize: "clamp(46px, 7vw, 76px)", lineHeight: 1.02,
                letterSpacing: "-0.04em", marginTop: 12,
                fontVariantNumeric: "tabular-nums",
                textShadow: "0 2px 10px rgba(0,0,0,0.15)",
              }}>
                + <AnimatedNumber value={Math.round(totalGainYear)}/> €
                <span style={{ fontSize: "0.36em", opacity: 0.82, fontWeight: 500, fontFamily: "var(--ff-text)", marginLeft: 10 }}>
                  / an
                </span>
              </div>
              <div style={{ marginTop: 8, fontSize: 13.5, opacity: 0.92, lineHeight: 1.5, maxWidth: 480 }}>
                Soit environ <strong>{_fmtEUR(totalGainYear / 12)}</strong> de plus chaque mois dans votre poche,
                sans travailler une minute de plus.
              </div>
            </div>
            <style>{`
              @keyframes cbGainGlow {
                0%, 100% { transform: scale(1); opacity: 0.8; }
                50%      { transform: scale(1.15); opacity: 1; }
              }
              @keyframes cbGainShine {
                0%   { transform: translateX(-80%); opacity: 0; }
                40%  { opacity: 1; }
                100% { transform: translateX(80%); opacity: 0; }
              }
              @keyframes cbGainSpark {
                0%, 100% { transform: scale(1) rotate(0); opacity: 0.3; }
                50%      { transform: scale(1.3) rotate(20deg); opacity: 0.7; }
              }
            `}</style>
          </div>

          {/* Breakdown cards,2x2 (mobile) / 1x4 (desktop), toutes dynamiques */}
          <div style={{
            marginTop: 10, display: "grid",
            gridTemplateColumns: "repeat(4, 1fr)", gap: 8,
          }} className="sim-grid">
            <SimBreakdown
              icon="clock"
              value={<><AnimatedNumber value={Math.round(daysPerYear)}/> j</>}
              label="de journées libérées / an"
              sub={`≈ ${Math.round(hoursPerYear)} h économisées`}
              tone="violet"
            />
            <SimBreakdown
              icon="heart"
              value={<>+<AnimatedNumber value={Math.round(retentionRevYear)}/> €</>}
              label="de CA en plus (fidélité)"
              sub={`+${Math.round(extraVisitsYear)} visites / an`}
              tone="pink"
            />
            <SimBreakdown
              icon="shield"
              value={<><AnimatedNumber value={Math.round(noShowRevenue)}/> €</>}
              label="d'absences évitées"
              sub={`${Math.round(noShowAvoidedYr)} no-show en moins / an`}
              tone="sage"
            />
            <SimBreakdown
              icon="link"
              value={<><AnimatedNumber value={onlineBookings}/></>}
              label="RDV pris en ligne / an"
              sub={`${callsAvoided} appels évités`}
              tone="accent"
            />
          </div>

          {/* Method toggle */}
          <button onClick={() => setShowDetails(!showDetails)} style={{
            marginTop: 14,
            display: "inline-flex", alignItems: "center", gap: 6,
            padding: "6px 12px",
            background: "transparent", border: "1px solid var(--line)",
            borderRadius: 999, cursor: "pointer",
            fontSize: 12.5, color: "var(--ink-2)", fontFamily: "inherit",
            transition: "background 0.2s ease, border-color 0.2s ease, color 0.2s ease",
          }}
            onMouseEnter={e => { e.currentTarget.style.background = "var(--bg-alt)"; e.currentTarget.style.borderColor = "var(--line-strong)"; }}
            onMouseLeave={e => { e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "var(--line)"; }}
          >
            <Icon name="sparkle" size={12} style={{
              transition: "transform .3s cubic-bezier(0.22, 1, 0.36, 1)",
              transform: showDetails ? "rotate(180deg)" : "rotate(0)",
            }}/>
            {showDetails ? "Masquer le détail du calcul" : "Comment on calcule ?"}
          </button>

          <div style={{
            display: "grid",
            gridTemplateRows: showDetails ? "1fr" : "0fr",
            opacity: showDetails ? 1 : 0,
            transition: "grid-template-rows .4s cubic-bezier(0.22, 1, 0.36, 1), opacity .3s ease",
          }}>
            <div style={{ overflow: "hidden" }}>
              <div style={{
                marginTop: 12, padding: "16px 18px", textAlign: "left",
                background: "var(--bg-alt)", border: "1px dashed var(--line-strong)",
                borderRadius: 12, fontSize: 13.5, color: "var(--ink-2)", lineHeight: 1.55,
              }}>
                <ul style={{ listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 10 }}>
                  <li>
                    <strong>⏱ Temps gagné</strong>,<strong>{h.minPerClient} min par client</strong> grâce aux rappels SMS auto,
                    à la réservation en ligne et aux fiches mises à jour automatiquement.
                    Sur {clients} clients/mois → {hoursPerYear.toFixed(0)}&nbsp;h / an, soit <strong>{daysPerYear.toFixed(1)} journées</strong> de {h.workDayHours}&nbsp;h rendues à votre vie perso.
                  </li>
                  <li>
                    <strong>♥ Fidélité</strong>, les rappels auto + la carte numérique génèrent <strong>+{Math.round(h.retentionBoost * 100)}&nbsp;%</strong> de visites en plus&nbsp;:
                    {` `}{Math.round(extraVisitsYear)}&nbsp;visites × {ticket}&nbsp;€ = <strong>{_fmtEUR(retentionRevYear)}</strong>.
                    Source&nbsp;: <em>Impact of Automated Reminders on Client Retention</em> (NailPro, 2023).
                  </li>
                  <li>
                    <strong>🛡 Absences évitées</strong>, le no-show moyen passe de <strong>{Math.round(h.noShowBefore * 100)}&nbsp;%</strong> à <strong>{Math.round(h.noShowAfter * 100)}&nbsp;%</strong> avec les rappels SMS.
                    Soit {Math.round(noShowAvoidedYr)} RDV sauvés × {ticket}&nbsp;€ = <strong>{_fmtEUR(noShowRevenue)}</strong> par an.
                    Source&nbsp;: <em>Baromètre du no-show</em> (NoShow.fr, 2024).
                  </li>
                  <li>
                    <strong>🔗 RDV pris en ligne</strong>,≈ <strong>40 %</strong> des réservations se font directement via votre lien public
                    (étude Planity 2024). Sur {clients} clients/mois × 12 → <strong>{onlineBookings} RDV pris tout seuls / an</strong>,
                    et autant d'appels que vous ne prenez plus pendant vos prestations.
                  </li>
                  <li>
                    <strong>€ Outils remplacés</strong>, un seul abonnement à la place de Planity (~{h.toolsReplaced}&nbsp;€/mois) = <strong>{toolSavedYear}&nbsp;€ / an</strong> inclus dans le total.
                  </li>
                </ul>
                <div style={{
                  marginTop: 12, paddingTop: 10, borderTop: "1px solid var(--line)",
                  fontSize: 12, color: "var(--ink-4)", fontStyle: "italic",
                }}>
                  Estimations. Votre situation varie selon votre métier et votre clientèle, écrivez-nous pour une estimation sur mesure.
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
};

const SimSlider = ({ label, suffix, value, min, max, step, ticks, onChange }) => (
  <div>
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", flexWrap: "wrap", gap: 8 }}>
      <div style={{ fontSize: 13, color: "var(--ink-3)", fontWeight: 500 }}>{label}</div>
      <div style={{
        fontFamily: "var(--ff-display)", fontSize: "clamp(22px, 3vw, 30px)",
        fontWeight: 580, letterSpacing: "-0.025em", color: "var(--accent-ink)",
        fontVariantNumeric: "tabular-nums",
      }}>
        <AnimatedNumber value={value}/>
        <span style={{ fontSize: 13, color: "var(--ink-3)", fontWeight: 450, fontFamily: "var(--ff-text)", marginLeft: 6 }}>
          {suffix}
        </span>
      </div>
    </div>
    <input type="range" min={min} max={max} step={step} value={value}
      onChange={(e) => onChange(+e.target.value)}
      style={{ width: "100%", accentColor: "var(--accent)", cursor: "pointer", marginTop: 8 }}
    />
    <div style={{ display: "flex", justifyContent: "space-between", marginTop: 2, fontSize: 11, color: "var(--ink-4)", fontVariantNumeric: "tabular-nums" }}>
      {ticks.map((t, i) => <span key={i}>{t}</span>)}
    </div>
  </div>
);

const SIM_TONES = {
  violet: { bg: "oklch(95% 0.06 268)", ink: "oklch(38% 0.18 268)" },
  pink:   { bg: "oklch(95% 0.05 340)", ink: "oklch(42% 0.14 340)" },
  sage:   { bg: "var(--sage-soft)",    ink: "oklch(38% 0.08 160)" },
  accent: { bg: "var(--accent-soft)",  ink: "var(--accent-ink)"   },
};
const SimBreakdown = ({ icon, value, label, sub, tone }) => {
  const t = SIM_TONES[tone] || SIM_TONES.accent;
  return (
    <div style={{
      padding: "14px 12px", textAlign: "left",
      background: "var(--surface)", border: "1px solid var(--line)",
      borderRadius: 12,
    }}>
      <div style={{
        width: 26, height: 26, borderRadius: 7,
        background: t.bg, color: t.ink,
        display: "flex", alignItems: "center", justifyContent: "center",
      }}>
        <Icon name={icon} size={13}/>
      </div>
      <div style={{
        fontFamily: "var(--ff-display)", fontSize: "clamp(18px, 2.4vw, 22px)",
        fontWeight: 600, letterSpacing: "-0.025em", color: "var(--ink)",
        marginTop: 8, fontVariantNumeric: "tabular-nums",
      }}>
        {value}
      </div>
      <div style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 2, lineHeight: 1.35 }}>
        {label}
      </div>
      <div style={{ fontSize: 11, color: "var(--ink-4)", marginTop: 4, fontStyle: "italic" }}>
        {sub}
      </div>
    </div>
  );
};

/* Smoothly tween an integer, gives the slider numbers a bit of life */
const AnimatedNumber = ({ value }) => {
  const [display, setDisplay] = React.useState(value);
  const rafRef = React.useRef(null);
  const fromRef = React.useRef(value);
  const startRef = React.useRef(0);
  React.useEffect(() => {
    fromRef.current = display;
    startRef.current = performance.now();
    const dur = 260;
    const tick = (now) => {
      const t = Math.min(1, (now - startRef.current) / dur);
      const eased = 1 - Math.pow(1 - t, 3);
      const v = Math.round(fromRef.current + (value - fromRef.current) * eased);
      setDisplay(v);
      if (t < 1) rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => { if (rafRef.current) cancelAnimationFrame(rafRef.current); };
    // eslint-disable-next-line
  }, [value]);
  return <>{display}</>;
};

const SimResultCard = ({ icon, value, label, basis }) => (
  <div style={{
    padding: "18px 14px", textAlign: "left",
    background: "var(--surface)", border: "1px solid var(--line)",
    borderRadius: 12,
  }}>
    <div style={{
      width: 30, height: 30, borderRadius: 8,
      background: "var(--accent-soft)", color: "var(--accent-ink)",
      display: "flex", alignItems: "center", justifyContent: "center",
    }}>
      <Icon name={icon} size={15}/>
    </div>
    <div style={{
      fontFamily: "var(--ff-display)", fontSize: "clamp(22px, 3vw, 30px)",
      fontWeight: 580, letterSpacing: "-0.03em", color: "var(--ink)",
      marginTop: 10,
    }}>
      {value}
    </div>
    <div style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 1 }}>
      {label}
    </div>
    <div style={{
      fontSize: 11.5, color: "var(--ink-4)",
      marginTop: 8, lineHeight: 1.4, fontStyle: "italic",
    }}>
      {basis}
    </div>
  </div>
);

// Backwards-compat aliases
const SimNumber = SimResultCard;
const SimCard = SimResultCard;

/* Generic reveal wrapper, fades in + slides up when entering viewport */
const Reveal = ({ children, delay = 0, as = "div", ...rest }) => {
  const [ref, visible] = useReveal({ threshold: 0.15 });
  const Tag = as;
  return (
    <Tag ref={ref} {...rest} style={{
      ...rest.style,
      opacity: visible ? 1 : 0,
      transform: visible ? "translateY(0)" : "translateY(24px)",
      transition: `opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1) ${delay}s, transform 0.7s cubic-bezier(0.22, 1, 0.36, 1) ${delay}s`,
      willChange: "opacity, transform",
    }}>{children}</Tag>
  );
};

Object.assign(window, {
  Hero, FeatureCarousel, FeatureCard, FeatureMock,
  SavingsSimulator, SimResultCard, SimNumber, SimCard,
  FlowArrow, Reveal, useReveal,
});
