// ============================================================
// NOMERUS · DEDICATED PAGES (features, pricing, brokers)
// ============================================================

// ──────────────────────────────────────────────────────────────
// FEATURES
// ──────────────────────────────────────────────────────────────
const WFeatures = ({ go }) => {
  const W = window.W;
  const Icon = window.Icon;
  const Reveal = window.Reveal;
  // Courbes de démo mémoïsées UNE fois (hook au niveau composant, jamais dans
  // un .map — respecte les Rules of Hooks et évite de régénérer à chaque render).
  const sparkCurves = React.useMemo(
    () => [0, 1, 2].map(() => window.qtMakeCurve(80, 100, 1.2, 2)),
    [],
  );
  return (
    <div style={{ background: W.bg, color: W.text, fontFamily: W.sans }}>
      <section style={{ borderBottom: `1px solid ${W.border}` }}>
        <div style={{ maxWidth: 1280, margin: "0 auto", padding: "clamp(56px, 7vw, 88px) 28px 60px" }}>
          <Reveal>
            <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 2, marginBottom: 14 }}>// FONCTIONNALITÉS</div>
            <h1 style={{ fontFamily: W.sans, fontSize: "clamp(36px, 5vw, 56px)", fontWeight: 700, letterSpacing: -1.6, margin: "0 0 20px", lineHeight: 1.05, maxWidth: 900 }}>
              Tout ce qu'un trader sérieux attend d'un journal. <span style={{ color: W.indigo }}>Rien de superflu.</span>
            </h1>
            <p style={{ fontFamily: W.sans, fontSize: 17, color: W.textDim, lineHeight: 1.6, maxWidth: 700, margin: 0 }}>
              Nomerus remplace le tableur que tu ne remplis plus : import en un geste, les stats qui expliquent ton P&L, et un Coach IA qui lit tes trades — pas tes espoirs.
            </p>
          </Reveal>
        </div>
      </section>

      {/* Three deep dives */}
      <section>
        <div style={{ maxWidth: 1280, margin: "0 auto", padding: "0 28px" }}>
          {[
            {
              num: "01",
              tag: "JOURNAL",
              title: "Importe une fois. Analyse pour toujours.",
              body: "Glisse l'export CSV de ton broker (MetaTrader, cTrader, et tout broker qui exporte ses trades) ou saisis-les à la main. Dédoublonnage automatique : tu peux réimporter le même fichier sans créer de doublons. La sync broker automatique arrive bientôt.",
              bullets: ["Import CSV — colonnes mappées automatiquement", "Saisie manuelle en quelques secondes", "Dédoublonnage par empreinte de trade", "Sync broker automatique : bientôt"],
              chip: ["CSV MT4/MT5", "CTRADER", "SAISIE MANUELLE", "SYNC · BIENTÔT"],
            },
            {
              num: "02",
              tag: "ANALYSE",
              title: "Les stats qui expliquent ton P&L. Pas des vanity metrics.",
              body: "On calcule les chiffres qui font vraiment bouger l'équité : Sharpe glissant, edge horaire par paire, échelle de drawdown, winrate par session. Tout a un graphique, tout est exportable.",
              bullets: ["Tout ton historique, tous comptes", "Attribution P&L par compte", "Heatmaps · heure × jour × paire", "Filtres session, instrument et plateforme"],
              chip: ["SHARPE", "SORTINO", "DRAWDOWN", "WINRATE"],
            },
            {
              num: "03",
              tag: "COACH",
              title: "Coach IA : le collègue que tu aurais voulu avoir.",
              body: "Il lit tes 30 derniers jours de trades et parle la langue du risque — pas de l'horoscope. Chaque constat est chiffré depuis tes propres données : sessions qui te coûtent, actifs qui portent ton P&L, dérives de discipline.",
              bullets: ["Analyse tes 30 derniers jours de trades", "Suggère des ajustements issus de tes propres données", "Risk management, psychologie, setups", "Premier debrief offert à l'inscription"],
              chip: ["EDGE", "RISQUE", "RÉGLAGE", "POST-MORTEM"],
            },
          ].map((s, i) => (
            <div key={s.num} className="w-stack" style={{
              display: "grid", gridTemplateColumns: "1fr 1fr", gap: 56,
              padding: "clamp(56px, 7vw, 80px) 0", borderBottom: i < 2 ? `1px solid ${W.border}` : "none",
              alignItems: "center",
            }}>
              <div style={{ order: i % 2 === 1 ? 2 : 1 }}>
                <div style={{ display: "flex", alignItems: "baseline", gap: 14, marginBottom: 18 }}>
                  <span style={{ fontFamily: W.mono, fontSize: 56, fontWeight: 700, color: W.indigoSoft, letterSpacing: -2, lineHeight: 1 }}>{s.num}</span>
                  <span style={{ fontFamily: W.mono, fontSize: 11, color: W.indigo, letterSpacing: 2, fontWeight: 600 }}>· {s.tag}</span>
                </div>
                <h2 style={{ fontFamily: W.sans, fontSize: 32, fontWeight: 700, letterSpacing: -0.8, margin: "0 0 18px", lineHeight: 1.15 }}>{s.title}</h2>
                <p style={{ fontFamily: W.sans, fontSize: 15, color: W.textDim, lineHeight: 1.65, margin: "0 0 24px", maxWidth: 480 }}>{s.body}</p>
                <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
                  {s.bullets.map(b => (
                    <div key={b} style={{ display: "flex", gap: 12, fontFamily: W.sans, fontSize: 14, color: W.text }}>
                      <span style={{ color: W.indigo, marginTop: 2 }}><Icon name="check" size={14}/></span>{b}
                    </div>
                  ))}
                </div>
              </div>

              {/* Visual mock */}
              <div className="w-card" style={{ order: i % 2 === 1 ? 1 : 2, background: W.panel, border: `1px solid ${W.borderStrong}`, borderRadius: 8, overflow: "hidden" }}>
                <div style={{
                  padding: "10px 14px", borderBottom: `1px solid ${W.border}`,
                  fontFamily: W.mono, fontSize: 10, color: W.textMute, letterSpacing: 1.6,
                  display: "flex", justifyContent: "space-between",
                }}>
                  <span>// {s.tag} · LIVE</span>
                  <span style={{ color: W.green }}>● {s.num} / 03</span>
                </div>
                <div style={{ padding: 22 }}>
                  <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 18 }}>
                    {s.chip.map(c => (
                      <span key={c} style={{
                        fontFamily: W.mono, fontSize: 10, letterSpacing: 1.5,
                        padding: "4px 10px", borderRadius: 3,
                        background: W.indigoSoft, color: W.indigo,
                        border: `1px solid ${W.borderStrong}`,
                      }}>{c}</span>
                    ))}
                  </div>
                  <window.QTSpark
                    data={sparkCurves[i]}
                    color={W.indigo}
                    height={160}
                  />
                  <div style={{
                    display: "grid", gridTemplateColumns: "repeat(4, 1fr)",
                    gap: 0, marginTop: 14, borderTop: `1px solid ${W.border}`, paddingTop: 14,
                    fontFamily: W.mono, fontSize: 11,
                  }}>
                    {[["TRADES", "142"], ["WIN", "64%"], ["SHARPE", "1.82"], ["DD", "-4.2%"]].map(([k, v], j) => (
                      <div key={k}>
                        <div style={{ color: W.textMute, letterSpacing: 1.2, fontSize: 9 }}>{k}</div>
                        <div style={{ color: j === 3 ? W.red : W.text, marginTop: 4, fontSize: 14 }}>{v}</div>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            </div>
          ))}
        </div>
      </section>

      {/* Le Brief */}
      <section style={{ borderTop: `1px solid ${W.border}` }}>
        <div style={{ maxWidth: 1280, margin: "0 auto", padding: "clamp(56px, 7vw, 80px) 28px" }}>
          <Reveal>
            <div className="w-stack" style={{ display: "grid", gridTemplateColumns: "1fr 2fr", gap: 56, alignItems: "start" }}>
              <div>
                <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 2, marginBottom: 12 }}>// LE BRIEF</div>
                <h2 style={{ fontFamily: W.sans, fontSize: "clamp(28px, 3.2vw, 36px)", fontWeight: 700, letterSpacing: -1, margin: 0, lineHeight: 1.12 }}>
                  Le journal des marchés,<br/>sans le bruit.
                </h2>
              </div>
              <div>
                <p style={{ fontFamily: W.sans, fontSize: 16, color: W.textDim, lineHeight: 1.65, margin: "8px 0 18px", maxWidth: 640 }}>
                  Macro, forex, crypto, indices : Le Brief condense l'actualité des marchés en articles factuels et sourcés, rédigés par IA à partir d'une veille multi-sources et mis à jour plusieurs fois par jour. Directement dans ton espace Nomerus, inclus dans les deux plans.
                </p>
                <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
                  {["MACRO", "FOREX", "CRYPTO", "INDICES"].map(c => (
                    <span key={c} style={{
                      fontFamily: W.mono, fontSize: 10, letterSpacing: 1.5,
                      padding: "4px 10px", borderRadius: 3,
                      background: W.indigoSoft, color: W.indigo,
                      border: `1px solid ${W.borderStrong}`,
                    }}>{c}</span>
                  ))}
                </div>
              </div>
            </div>
          </Reveal>
        </div>
      </section>

      {/* Comparison */}
      <section style={{ background: W.bgAlt, borderTop: `1px solid ${W.border}`, borderBottom: `1px solid ${W.border}` }}>
        <div style={{ maxWidth: 1280, margin: "0 auto", padding: "clamp(64px, 8vw, 100px) 28px" }}>
          <Reveal>
            <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 2, marginBottom: 12 }}>// COMPARER</div>
            <h2 style={{ fontFamily: W.sans, fontSize: "clamp(30px, 3.4vw, 40px)", fontWeight: 700, letterSpacing: -1.2, margin: "0 0 40px", lineHeight: 1.1 }}>
              Nomerus vs. le tableur que tu abandonnes chaque mois.
            </h2>
          </Reveal>

          <div style={{ background: W.panel, border: `1px solid ${W.border}`, borderRadius: 4, overflow: "hidden" }}>
            <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: W.sans, fontSize: 14 }}>
              <thead>
                <tr style={{ background: W.panel2 }}>
                  <th style={{ textAlign: "left", padding: "16px 22px", color: W.textMute, fontFamily: W.mono, fontSize: 10, letterSpacing: 1.6, fontWeight: 500 }}>CAPACITÉ</th>
                  <th style={{ textAlign: "center", padding: "16px 22px", color: W.indigo, fontFamily: W.mono, fontSize: 11, letterSpacing: 1.8, fontWeight: 700 }}>NOMERUS</th>
                  <th style={{ textAlign: "center", padding: "16px 22px", color: W.textMute, fontFamily: W.mono, fontSize: 10, letterSpacing: 1.6, fontWeight: 500 }}>TABLEUR</th>
                  <th style={{ textAlign: "center", padding: "16px 22px", color: W.textMute, fontFamily: W.mono, fontSize: 10, letterSpacing: 1.6, fontWeight: 500 }}>UI BROKER</th>
                </tr>
              </thead>
              <tbody>
                {[
                  ["P&L unifié multi-brokers", true, false, false],
                  ["Import CSV sans ressaisie", true, false, "partial"],
                  ["Historique pluri-années consolidé", true, "partial", "partial"],
                  ["Debrief IA sur tes propres trades", true, false, false],
                  ["Analyse edge horaire", true, "partial", false],
                  ["Agrégation multi-comptes", true, "partial", false],
                  ["Export CSV / JSON en un clic", true, true, false],
                  ["Données chiffrées, hébergées en UE", true, false, "partial"],
                ].map((row, i) => (
                  <tr key={i} className="w-cmp-row" style={{ borderTop: `1px solid ${W.border}` }}>
                    <td style={{ padding: "14px 22px", color: W.text }}>{row[0]}</td>
                    {row.slice(1).map((v, j) => (
                      <td key={j} style={{ textAlign: "center", padding: "14px 22px" }}>
                        {v === true && <span style={{ color: W.green }}><Icon name="check" size={16}/></span>}
                        {v === false && <span style={{ color: W.textMute, fontFamily: W.mono }}>—</span>}
                        {v === "partial" && <span style={{ fontFamily: W.mono, fontSize: 10, color: W.amber, letterSpacing: 1.4 }}>PARTIEL</span>}
                      </td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </section>

      {/* Final CTA */}
      <section>
        <Reveal style={{ maxWidth: 1280, margin: "0 auto", padding: "clamp(64px, 8vw, 100px) 28px", textAlign: "center" }}>
          <h2 style={{ fontFamily: W.sans, fontSize: "clamp(32px, 4.4vw, 44px)", fontWeight: 700, letterSpacing: -1.4, margin: "0 0 20px", lineHeight: 1.05 }}>
            Vois-le sur tes propres trades. <span style={{ color: W.indigo }}>Ça prend trois minutes.</span>
          </h2>
          <button onClick={() => go("signup")} className="w-cta" style={{
            background: W.indigo, color: W.bg, border: "none", cursor: "pointer",
            padding: "16px 28px", borderRadius: 5,
            fontFamily: W.mono, fontSize: 12, fontWeight: 700, letterSpacing: 2,
          }}>
            COMMENCER GRATUITEMENT →
          </button>
        </Reveal>
      </section>
    </div>
  );
};

// ──────────────────────────────────────────────────────────────
// PRICING (dedicated page wraps shared table + FAQ)
// ──────────────────────────────────────────────────────────────
const WPricing = ({ go }) => {
  const W = window.W;
  const Reveal = window.Reveal;
  return (
    <div style={{ background: W.bg, color: W.text, fontFamily: W.sans }}>
      <section style={{ borderBottom: `1px solid ${W.border}` }}>
        <div style={{ maxWidth: 1280, margin: "0 auto", padding: "clamp(52px, 6vw, 70px) 28px 0", textAlign: "center" }}>
          <Reveal>
            <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 2, marginBottom: 14 }}>// TARIFS</div>
            <h1 style={{ fontFamily: W.sans, fontSize: "clamp(36px, 5vw, 56px)", fontWeight: 700, letterSpacing: -1.6, margin: "0 0 18px", lineHeight: 1.05 }}>
              Un plan Gratuit pour commencer. <span style={{ color: W.indigo }}>Pro pour aller plus loin.</span>
            </h1>
            <p style={{ fontFamily: W.sans, fontSize: 17, color: W.textDim, lineHeight: 1.6, maxWidth: 640, margin: "0 auto 60px" }}>
              Le plan Gratuit est vraiment utilisable : import CSV, vraies stats, un debrief IA offert. Le Pro débloque les trades illimités, le Coach IA en continu et l'analyse par graphique — annulable en un clic, sans engagement.
            </p>
          </Reveal>
        </div>
      </section>

      <window.WPricingTable go={go}/>

      {/* FAQ */}
      <section>
        <div style={{ maxWidth: 880, margin: "0 auto", padding: "clamp(64px, 8vw, 100px) 28px" }}>
          <Reveal>
            <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 2, marginBottom: 12, textAlign: "center" }}>// FAQ</div>
            <h2 style={{ fontFamily: W.sans, fontSize: "clamp(28px, 3.2vw, 36px)", fontWeight: 700, letterSpacing: -1, margin: "0 0 36px", lineHeight: 1.1, textAlign: "center" }}>
              Questions fréquentes.
            </h2>
          </Reveal>
          <div style={{ display: "flex", flexDirection: "column", gap: 0 }}>
            {[
              ["Nomerus détient-il mes fonds ?", "Non. Ton capital reste chez ton broker. Nomerus ne lit que tes trades (import CSV aujourd'hui, sync API en lecture seule demain), sans aucune autorisation de retrait. Nous n'avons pas, et ne pouvons pas demander, de droits de trade ou de retrait."],
              ["Quels plans proposez-vous ?", "Deux plans. Gratuit (0 CHF, sans carte) : import CSV + saisie manuelle, jusqu'à 30 trades par mois, stats de base, Coach IA 30 messages/jour, un debrief IA offert. Pro (14,99 CHF/mois ou 119 CHF/an) : trades illimités, Coach IA 300 messages/jour, analyse IA graphique par graphique, sync broker prioritaire. Tu passes à Pro quand tu veux, annulation en un clic, sans engagement."],
              ["Que deviennent mes données si je pars ?", "Elles restent à toi. Tu peux exporter chaque trade, chaque frais et chaque note en CSV ou JSON à tout moment, et supprimer ton compte efface tes données associées. Aucune rétention cachée."],
              ["Puis-je ajouter des trades manuellement ?", "Oui — paper-trade ou exécutions hors plateforme peuvent être ajoutés à la main (bouton « Nouveau trade » dans le Journal) ou importés depuis un export CSV. Le dédoublonnage évite les doublons si tu réimportes le même fichier."],
              ["Mes données sont-elles utilisées pour entraîner des modèles ?", "Non. Tes P&L, tes trades et ton historique de chat ne sont jamais utilisés pour entraîner un modèle — ni le nôtre, ni celui de quiconque."],
              ["Quels brokers supportez-vous ?", "Aujourd'hui : import CSV depuis n'importe quel broker qui exporte ses trades (formats MetaTrader 5, cTrader et Bybit testés), plus la saisie manuelle. La synchronisation automatique par clés API arrive broker par broker — on l'affichera seulement quand elle marchera vraiment."],
            ].map(([q, a], i) => (
              <details key={i} style={{ borderTop: `1px solid ${W.border}`, padding: "20px 0", cursor: "pointer" }}>
                <summary style={{
                  display: "flex", alignItems: "center", justifyContent: "space-between",
                  fontFamily: W.sans, fontSize: 16, fontWeight: 600, color: W.text,
                  listStyle: "none", cursor: "pointer",
                }}>
                  {q}
                  <span style={{ color: W.indigo, fontFamily: W.mono, fontSize: 18 }}>+</span>
                </summary>
                <div style={{ fontFamily: W.sans, fontSize: 14, color: W.textDim, lineHeight: 1.65, marginTop: 12, maxWidth: 720 }}>
                  {a}
                </div>
              </details>
            ))}
          </div>
        </div>
      </section>
    </div>
  );
};

// ──────────────────────────────────────────────────────────────
// BROKERS — lighter content page
// ──────────────────────────────────────────────────────────────
const WBrokers = ({ go }) => {
  const W = window.W;
  const Reveal = window.Reveal;
  // Liste honnête : `live` signifie « import CSV testé avec l'export de ce
  // broker ». La sync automatique n'est dispo pour AUCUN broker aujourd'hui
  // (beta privée) — pas de badge LIVE mensonger.
  const all = [
    // Import CSV testé avec les exports de ces brokers.
    { id: "bybit",     name: "Bybit",              type: "Crypto",      region: "Global",    live: true },
    { id: "mt5",       name: "MetaTrader 5",       type: "Multi-asset", region: "Global",    live: true },
    { id: "ctrader",   name: "cTrader",            type: "Forex / CFD", region: "Europe",    live: true },
    // Sur la roadmap de la sync automatique.
    { id: "icmarkets", name: "IC Markets",         type: "Forex / CFD", region: "Australia", live: false },
    { id: "ibkr",      name: "Interactive Brokers",type: "Multi-asset", region: "USA",       live: false },
    { id: "oanda",     name: "OANDA",              type: "Forex / CFD", region: "USA",       live: false },
    { id: "kraken",    name: "Kraken",             type: "Crypto",      region: "USA",       live: false },
    { id: "kucoin",    name: "KuCoin",             type: "Crypto",      region: "Global",    live: false },
    { id: "tradier",   name: "Tradier",            type: "Equities",    region: "USA",       live: false },
    { id: "tasty",     name: "Tastytrade",         type: "Options",     region: "USA",       live: false },
    { id: "fxcm",      name: "FXCM",               type: "Forex / CFD", region: "Europe",    live: false },
  ];

  const liveCount    = all.filter(b => b.live).length;
  const plannedCount = all.length - liveCount;

  return (
    <div style={{ background: W.bg, color: W.text, fontFamily: W.sans, minHeight: "60vh" }}>
      <section style={{ borderBottom: `1px solid ${W.border}` }}>
        <div style={{ maxWidth: 1280, margin: "0 auto", padding: "clamp(52px, 6vw, 70px) 28px 50px" }}>
          <Reveal>
            <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 2, marginBottom: 14 }}>// INTÉGRATIONS</div>
            <h1 style={{ fontFamily: W.sans, fontSize: "clamp(34px, 4.6vw, 52px)", fontWeight: 700, letterSpacing: -1.4, margin: "0 0 18px", lineHeight: 1.05 }}>
              L'import CSV marche aujourd'hui. <span style={{ color: W.indigo }}>La sync automatique arrive.</span>
            </h1>
            <p style={{ fontFamily: W.sans, fontSize: 16, color: W.textDim, lineHeight: 1.6, maxWidth: 720 }}>
              Nomerus est broker-agnostique par conception : si ton broker exporte un CSV, tu peux l'importer dès aujourd'hui ({liveCount} formats testés, les autres marchent en général aussi). La synchronisation automatique par clés API arrive — chaque broker ci-dessous est honnêtement labellisé <span style={{ fontFamily: W.mono, fontSize: 13, color: W.indigo, letterSpacing: 1.2 }}>SYNC PRÉVUE</span> tant qu'elle n'est pas livrée.
            </p>
            <div style={{ marginTop: 18, display: "flex", gap: 18, flexWrap: "wrap", fontFamily: W.mono, fontSize: 11, color: W.textDim, letterSpacing: 1.4 }}>
              <span><span style={{ color: W.green }}>● {liveCount} CSV TESTÉS</span></span>
              <span style={{ color: W.border }}>|</span>
              <span><span style={{ color: W.indigo }}>◇ {plannedCount} SYNC PRÉVUES</span></span>
            </div>
          </Reveal>
        </div>
      </section>
      <section>
        <div style={{ maxWidth: 1280, margin: "0 auto", padding: "clamp(48px, 6vw, 60px) 28px" }}>
          <Reveal>
          <div className="w-stack" style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14 }}>
            {all.map(b => (
              <div key={b.id} className="w-card" style={{
                background: W.panel,
                border: `1px solid ${b.live ? "rgba(91,217,154,0.28)" : W.border}`,
                borderRadius: 6, padding: 22,
                display: "flex", flexDirection: "column", gap: 14, minHeight: 170,
                opacity: b.live ? 1 : 0.78,
              }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
                  <div style={{
                    width: 38, height: 38, borderRadius: 4,
                    background: W.indigoSoft, color: W.indigo, fontFamily: W.mono, fontWeight: 700, fontSize: 14,
                    display: "flex", alignItems: "center", justifyContent: "center",
                    border: `1px solid ${W.borderStrong}`,
                  }}>{b.name[0]}</div>
                  {b.live ? (
                    <span style={{ fontFamily: W.mono, fontSize: 9, padding: "2px 8px", borderRadius: 3, letterSpacing: 1.5, background: "rgba(91,217,154,0.1)", color: W.green, border: `1px solid rgba(91,217,154,0.3)` }}>● CSV TESTÉ</span>
                  ) : (
                    <span style={{ fontFamily: W.mono, fontSize: 9, padding: "2px 8px", borderRadius: 3, letterSpacing: 1.5, background: W.indigoSoft, color: W.indigo, border: `1px solid ${W.borderStrong}` }}>◇ SYNC PRÉVUE</span>
                  )}
                </div>
                <div style={{ fontFamily: W.sans, fontSize: 16, fontWeight: 600 }}>{b.name}</div>
                <div style={{ fontFamily: W.mono, fontSize: 10, color: W.textMute, letterSpacing: 1.4, marginTop: "auto", display: "flex", justifyContent: "space-between" }}>
                  <span>{b.type.toUpperCase()}</span>
                  <span>{b.region.toUpperCase()}</span>
                </div>
              </div>
            ))}
          </div>
          </Reveal>
        </div>
      </section>
    </div>
  );
};

// NOTE: WDocs and WBlog were removed in the honesty pass — their
// content was placeholder (fake post titles, fake authors, dead
// `href="#"` links to nonexistent doc pages). When real docs and
// blog content exist, restore the components and re-add the routes
// to index.html.

// ──────────────────────────────────────────────────────────────
// LEGAL / COMPANY PAGES (about, legal, terms, privacy, risk)
// Rédigées pour un exploitant individuel domicilié en Suisse :
// impressum exigé par l'art. 3 al. 1 let. s LCD, information sur
// les données exigée par les art. 19–21 nLPD (+ RGPD pour les
// visiteurs de l'UE), cookies au sens de l'art. 45c let. b LTC.
// ──────────────────────────────────────────────────────────────
const NOMERUS_LEGAL_UPDATED = "10 juillet 2026";
// Adresse de contact publique (pro). Nécessite un alias gratuit : Cloudflare
// Email Routing (domaine nomerus.com) forward contact@nomerus.com → Gmail perso.
// Voir docs/CONTACT_EMAIL_SETUP.md.
const NOMERUS_CONTACT_EMAIL = "contact@nomerus.com";
const NOMERUS_OPERATOR = "Loïc Rebetez";
// Adresse postale de contact publiée (LCD art. 3 al. 1 let. s). « Suisse » est
// rendu sur la ligne suivante par le composant.
const NOMERUS_OPERATOR_ADDRESS = "Rue Saint-Imier 11, 2802 Develier";

// Coquille partagée : eyebrow + titre + date + corps en sections.
const WLegalShell = ({ eyebrow, title, intro, sections }) => {
  const W = window.W;
  const Reveal = window.Reveal;
  return (
    <div style={{ background: W.bg, color: W.text, fontFamily: W.sans, minHeight: "70vh" }}>
      <section style={{ borderBottom: `1px solid ${W.border}` }}>
        <div style={{ maxWidth: 880, margin: "0 auto", padding: "clamp(52px, 6vw, 72px) 28px 36px" }}>
          <Reveal>
            <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 2, marginBottom: 14 }}>// {eyebrow}</div>
            <h1 style={{ fontFamily: W.sans, fontSize: "clamp(32px, 4.4vw, 48px)", fontWeight: 700, letterSpacing: -1.4, margin: "0 0 14px", lineHeight: 1.06 }}>
              {title}
            </h1>
            {intro && (
              <p style={{ fontFamily: W.sans, fontSize: 16, color: W.textDim, lineHeight: 1.6, maxWidth: 680, margin: 0 }}>{intro}</p>
            )}
            <div style={{ marginTop: 18, fontFamily: W.mono, fontSize: 10, color: W.textMute, letterSpacing: 1.4 }}>
              DERNIÈRE MISE À JOUR · {NOMERUS_LEGAL_UPDATED.toUpperCase()}
            </div>
          </Reveal>
        </div>
      </section>

      <section>
        <div style={{ maxWidth: 880, margin: "0 auto", padding: "clamp(36px, 5vw, 56px) 28px clamp(56px, 8vw, 90px)" }}>
          <div style={{ display: "flex", flexDirection: "column", gap: 30 }}>
            {sections.map(([h, body], i) => (
              <div key={i}>
                {h && (
                  <h2 style={{ fontFamily: W.sans, fontSize: 19, fontWeight: 600, color: W.text, margin: "0 0 10px", letterSpacing: -0.3 }}>{h}</h2>
                )}
                <div style={{ fontFamily: W.sans, fontSize: 14, color: W.textDim, lineHeight: 1.7, maxWidth: 720 }}>{body}</div>
              </div>
            ))}
          </div>
        </div>
      </section>
    </div>
  );
};

// Petit lien mail réutilisable dans les corps de texte.
const WMail = () => (
  <a href={`mailto:${NOMERUS_CONTACT_EMAIL}`} style={{ color: window.W.indigo, textDecoration: "none" }}>{NOMERUS_CONTACT_EMAIL}</a>
);
// Lien interne SPA dans un corps de texte légal.
const WLegalLink = ({ go, route, children }) => (
  <button onClick={() => go(route)} style={{
    background: "transparent", border: "none", padding: 0, cursor: "pointer",
    font: "inherit", color: window.W.indigo,
  }}>{children}</button>
);

const WAbout = ({ go }) => {
  const W = window.W;
  return (
    <WLegalShell
      eyebrow="À PROPOS"
      title="Un poste de trading pour les gens sérieux."
      intro="Nomerus est un projet indépendant : un journal de trading qui transforme tes trades en edge lisible, pour les traders qui veulent une performance répétable plutôt que du feeling."
      sections={[
        ["Notre raison d'être", "Les bons traders journalisent. Le problème, c'est que personne ne tient un journal manuel sur la durée. Nomerus rend la journalisation indolore (import CSV, saisie rapide, bientôt sync automatique) — puis transforme cette pile de trades en edge lisible : équité, drawdown, winrate par session, Coach IA. Et pour le contexte, Le Brief : le journal des marchés, rédigé par IA, factuel et sourcé."],
        ["Indie et honnête", "Nomerus est développé en indie. On indique honnêtement ce qui marche aujourd'hui (import CSV, saisie manuelle, Coach IA, Le Brief) vs. ce qui est prévu (sync broker automatique) — pas de faux badges. Aucune autorisation de retrait ne sera jamais demandée sur tes comptes broker."],
        ["Nous écrire", <span>Une question, un bug, une demande presse ? Passe par la <WLegalLink go={go} route="contact">page Contact</WLegalLink> ou écris-nous à <WMail/>.</span>],
      ]}
    />
  );
};

// ── MENTIONS LÉGALES / IMPRESSUM (art. 3 al. 1 let. s LCD) ──
const WLegal = ({ go }) => {
  const W = window.W;
  return (
    <WLegalShell
      eyebrow="LÉGAL · MENTIONS LÉGALES"
      title="Mentions légales"
      intro="Informations sur l'exploitant du site et du service Nomerus, conformément au droit suisse."
      sections={[
        ["Exploitant du site", <span>
          Nomerus est un projet individuel exploité par :<br/><br/>
          <strong style={{ color: W.text }}>{NOMERUS_OPERATOR}</strong><br/>
          {NOMERUS_OPERATOR_ADDRESS ? <span>{NOMERUS_OPERATOR_ADDRESS}<br/></span> : null}
          Suisse<br/>
          E-mail : <WMail/>
        </span>],
        ["Hébergement", "Le site est hébergé par Vercel Inc., 440 N Barranca Ave #4133, Covina, CA 91723, États-Unis. Les données applicatives (comptes, trades, conversations) sont hébergées par Supabase sur des serveurs situés dans l'Union européenne."],
        ["Propriété intellectuelle", "Le nom « Nomerus », le logo, le design du site et de l'application ainsi que l'ensemble des contenus (textes, graphiques, code) sont protégés. Toute reproduction ou exploitation sans accord écrit préalable est interdite. Les noms de brokers et marques cités appartiennent à leurs titulaires respectifs et ne sont mentionnés qu'à titre d'information de compatibilité."],
        ["Responsabilité", "Les informations publiées sur ce site sont fournies à titre indicatif, sans garantie d'exactitude ou d'exhaustivité. Nomerus décline toute responsabilité quant au contenu des sites tiers accessibles par des liens externes. L'utilisation du service est régie par les Conditions d'utilisation."],
        ["Droit applicable", <span>Le présent site et le service Nomerus sont régis par le droit suisse. Voir aussi les <WLegalLink go={go} route="terms">Conditions d'utilisation</WLegalLink>, la <WLegalLink go={go} route="privacy">Politique de confidentialité</WLegalLink> et l'<WLegalLink go={go} route="risk">Avertissement sur les risques</WLegalLink>.</span>],
      ]}
    />
  );
};

const WTerms = ({ go }) => {
  const W = window.W;
  return (
    <WLegalShell
      eyebrow="LÉGAL · CGU"
      title="Conditions d'utilisation"
      intro="Ces conditions régissent l'accès et l'utilisation de Nomerus. En créant un compte ou en utilisant le service, tu les acceptes."
      sections={[
        ["1. Objet", <span>Les présentes conditions d'utilisation (« CGU ») forment un contrat entre toi et {NOMERUS_OPERATOR}, exploitant de Nomerus (voir les <WLegalLink go={go} route="legal">Mentions légales</WLegalLink>). Elles s'appliquent au site et à l'application web Nomerus.</span>],
        ["2. Service", "Nomerus est un outil de journalisation et d'analyse de trades. Ton historique entre par import CSV ou saisie manuelle (et, à terme, par des accès broker en lecture seule). Nomerus ne passe pas d'ordres, ne gère pas de fonds, n'effectue aucun retrait et ne fournit aucun conseil en investissement."],
        ["3. Compte et âge minimum", "Le service est réservé aux personnes majeures et capables de discernement. Tu es responsable de la confidentialité de tes identifiants et de toute activité sur ton compte. Tu t'engages à fournir des informations exactes et à les tenir à jour."],
        ["4. Plans et abonnement", "Nomerus propose un plan Gratuit, sans frais, et un plan Pro payant. Le prix et les conditions du plan Pro sont affichés avant toute souscription et le paiement est traité par Stripe. L'abonnement est résiliable à tout moment depuis ton compte et reste actif jusqu'à la fin de la période payée. Les fonctionnalités de chaque plan peuvent évoluer, sans effet rétroactif sur tes données."],
        ["5. Tes données et contenus", "Tes trades, P&L, notes et conversations restent ta propriété. Tu nous accordes uniquement le droit de les traiter pour faire fonctionner le service. Tu peux les exporter (CSV / JSON) à tout moment. Tes données ne sont jamais vendues et ne sont jamais utilisées pour entraîner un modèle d'IA, ni le nôtre ni celui d'un tiers. Le traitement des données personnelles est décrit dans la Politique de confidentialité."],
        ["6. Utilisation acceptable", "Tu t'engages à ne pas : utiliser le service à des fins illégales ; tenter d'accéder aux données d'autres utilisateurs ; surcharger, sonder ou contourner les mesures de sécurité ; extraire massivement le contenu (scraping) ; revendre l'accès au service ; utiliser le Coach IA pour générer des contenus illicites."],
        ["7. Propriété intellectuelle", "Le code, le design, la marque et les contenus de Nomerus restent la propriété exclusive de l'exploitant. Les CGU ne t'accordent aucun droit sur ceux-ci, hormis un droit d'utilisation personnel, non exclusif et non transférable du service."],
        ["8. Disponibilité", "Le service est fourni « en l'état » et « selon disponibilité ». Des interruptions, bugs ou pertes de fonctionnalités peuvent survenir. Nous te recommandons d'exporter régulièrement tes données. Nous pouvons faire évoluer ou interrompre des fonctionnalités ; en cas d'arrêt complet du service, tu seras prévenu suffisamment à l'avance pour exporter tes données."],
        ["9. Avertissement sur les risques", <span>Le trading comporte un risque élevé de perte en capital. Les statistiques et les réponses du Coach IA sont des outils d'analyse de ton propre historique et ne constituent en aucun cas un conseil en investissement. Lis l'<WLegalLink go={go} route="risk">Avertissement sur les risques</WLegalLink>, qui fait partie intégrante des présentes CGU.</span>],
        ["10. Responsabilité", "Dans les limites permises par le droit suisse (art. 100 CO), toute responsabilité pour les dommages indirects, les pertes de gain et les pertes de trading est exclue. Demeure réservée la responsabilité pour dol ou faute grave, ainsi que toute responsabilité qui ne peut être exclue légalement. Tes décisions de trading relèvent de ta seule responsabilité."],
        ["11. Résiliation", "Tu peux supprimer ton compte à tout moment depuis les paramètres ; tes données personnelles sont alors effacées conformément à la Politique de confidentialité. Nous pouvons suspendre ou résilier un compte en cas de violation des présentes CGU, si possible après avertissement préalable."],
        ["12. Modifications", "Ces CGU peuvent évoluer ; la date de mise à jour figure en haut de page. En cas de modification substantielle, les utilisateurs disposant d'un compte seront informés (e-mail ou avis dans l'application) avant l'entrée en vigueur. L'utilisation du service après cette date vaut acceptation."],
        ["13. Droit applicable et for", "Les présentes CGU sont soumises au droit suisse, à l'exclusion des règles de conflit de lois. Le for est au domicile de l'exploitant en Suisse, sous réserve des fors impératifs prévus par la loi (notamment pour les consommateurs)."],
        ["14. Contact", <span>Pour toute question relative aux présentes CGU : <WMail/>.</span>],
      ]}
    />
  );
};

const WPrivacy = ({ go }) => {
  const W = window.W;
  const managesCookies = () => { if (window.NomerusAnalytics && window.NomerusAnalytics.openConsent) window.NomerusAnalytics.openConsent(); };
  return (
    <WLegalShell
      eyebrow="LÉGAL · CONFIDENTIALITÉ"
      title="Politique de confidentialité"
      intro="Cette déclaration explique quelles données personnelles Nomerus traite, pourquoi, et quels sont tes droits. Elle répond aux exigences de la loi fédérale suisse sur la protection des données (nLPD) et, pour les utilisateurs de l'UE, du RGPD."
      sections={[
        ["1. Responsable du traitement", <span>
          Le responsable du traitement au sens de l'art. 5 let. j nLPD est :<br/><br/>
          <strong style={{ color: W.text }}>{NOMERUS_OPERATOR}</strong> — Nomerus<br/>
          {NOMERUS_OPERATOR_ADDRESS ? <span>{NOMERUS_OPERATOR_ADDRESS}<br/></span> : null}
          Suisse<br/>
          E-mail : <WMail/>
        </span>],
        ["2. Données traitées", <span>
          <strong style={{ color: W.text }}>Données de compte</strong> — adresse e-mail, nom affiché, mot de passe (haché) ou identifiant Google si tu utilises la connexion Google.<br/><br/>
          <strong style={{ color: W.text }}>Données de trading</strong> — les trades, exécutions, P&L et notes que tu importes (CSV), saisis manuellement ou synchronises via un accès broker en lecture seule. Les éventuelles clés API broker sont chiffrées (AES-GCM) avant stockage et ne sont jamais affichées en clair.<br/><br/>
          <strong style={{ color: W.text }}>Conversations avec le Coach IA</strong> — tes messages et l'historique de chat, ainsi que les statistiques de trading nécessaires pour formuler la réponse.<br/><br/>
          <strong style={{ color: W.text }}>Données techniques et d'usage</strong> — adresse IP, type de navigateur, pages consultées et interactions, collectées pour la sécurité et — uniquement avec ton accord — pour la mesure d'audience (voir section 4).
        </span>],
        ["3. Finalités", "Nous traitons ces données pour : fournir le service (journal, statistiques, Coach IA) ; créer et sécuriser ton compte ; gérer un éventuel abonnement ; répondre à tes demandes ; comprendre l'usage du site et améliorer le produit (uniquement avec ton consentement) ; respecter nos obligations légales. Tes données ne sont jamais vendues et ne servent jamais à entraîner un modèle d'IA."],
        ["4. Cookies et mesure d'audience", <span>
          Le site utilise deux catégories de cookies et de stockage local :<br/><br/>
          <strong style={{ color: W.text }}>Essentiels</strong> — nécessaires au fonctionnement : session de connexion (Supabase), préférences locales de l'application et mémorisation de ton choix concernant les cookies. Ils ne requièrent pas de consentement (art. 45c let. b LTC).<br/><br/>
          <strong style={{ color: W.text }}>Mesure d'audience</strong> — déposés uniquement si tu les acceptes via la bannière : pages vues, parcours et interactions, ainsi que des enregistrements de session dans lesquels les champs saisis (e-mail, mots de passe, montants) sont masqués. Ces données sont traitées pour notre compte par notre prestataire de mesure d'audience PostHog et hébergées dans l'Union européenne.<br/><br/>
          Tu peux retirer ou modifier ton choix à tout moment : <button onClick={managesCookies} style={{ background: "transparent", border: `1px solid ${W.border}`, borderRadius: 4, padding: "6px 12px", cursor: "pointer", fontFamily: W.mono, fontSize: 11, color: W.indigo, letterSpacing: 1 }}>GÉRER MES COOKIES</button>
        </span>],
        ["5. Destinataires (sous-traitants)", <span>
          Nous partageons les données uniquement avec les prestataires nécessaires au fonctionnement du service, qui les traitent pour notre compte :<br/><br/>
          <strong style={{ color: W.text }}>Supabase</strong> — authentification, base de données et fonctions serveur ; données hébergées dans l'UE.<br/>
          <strong style={{ color: W.text }}>Vercel</strong> — hébergement du site (États-Unis).<br/>
          <strong style={{ color: W.text }}>Anthropic</strong> — génération des réponses du Coach IA (États-Unis) ; les messages transmis ne sont pas utilisés pour entraîner ses modèles.<br/>
          <strong style={{ color: W.text }}>PostHog</strong> — mesure d'audience (hébergement UE), uniquement avec ton consentement.<br/>
          <strong style={{ color: W.text }}>Stripe</strong> — traitement des paiements lorsque le plan Pro sera lancé ; Nomerus ne stocke aucune donnée de carte.<br/>
          <strong style={{ color: W.text }}>Google</strong> — uniquement si tu choisis la connexion Google (OAuth) ; le site charge par ailleurs des polices depuis Google Fonts.
        </span>],
        ["6. Communication à l'étranger", "Certains prestataires traitent des données en dehors de la Suisse : dans l'UE/EEE (niveau de protection reconnu comme adéquat par le Conseil fédéral) et aux États-Unis. Les transferts vers les États-Unis reposent sur le Swiss-U.S. Data Privacy Framework lorsque le prestataire y est certifié, ou sur des clauses contractuelles types reconnues (art. 16 nLPD)."],
        ["7. Durée de conservation", "Tes données de compte et de trading sont conservées tant que ton compte est actif. Si tu supprimes ton compte, les données associées sont effacées. Les données de mesure d'audience et les journaux techniques sont conservés pour des durées limitées, puis supprimés ou agrégés. Certaines données peuvent être conservées plus longtemps lorsqu'une obligation légale l'exige (p. ex. données comptables liées à un abonnement payant : 10 ans, art. 958f CO)."],
        ["8. Sécurité", "Les échanges avec le site et la base de données sont chiffrés (TLS). L'accès aux données est cloisonné par utilisateur au niveau de la base de données (row level security). Les clés API broker sont chiffrées avec AES-GCM et utilisables uniquement en lecture seule. Aucune transmission sur Internet n'étant infaillible, nous te recommandons un mot de passe unique et robuste."],
        ["9. Tes droits", <span>
          Conformément aux art. 25 ss nLPD (et, si le RGPD s'applique à toi, aux art. 15 ss RGPD), tu peux : demander l'accès aux données te concernant ; les faire rectifier ; les faire effacer ; t'opposer à un traitement ; retirer un consentement à tout moment ; demander la remise de tes données dans un format électronique courant (art. 28 nLPD — l'export CSV / JSON est d'ailleurs disponible en libre-service dans l'app).<br/><br/>
          Pour exercer ces droits, écris-nous à <WMail/>. Tu peux également saisir le Préposé fédéral à la protection des données et à la transparence (PFPDT, <a href="https://www.edoeb.admin.ch" target="_blank" rel="noopener noreferrer" style={{ color: W.indigo, textDecoration: "none" }}>edoeb.admin.ch</a>) ou, si tu résides dans l'UE, ton autorité de protection des données locale.
        </span>],
        ["10. Modifications", "Cette politique peut évoluer avec le service ; la date de mise à jour figure en haut de page. En cas de changement substantiel (nouveau prestataire, nouvelle finalité), les utilisateurs disposant d'un compte en seront informés."],
      ]}
    />
  );
};

const WRisk = ({ go }) => {
  const W = window.W;
  return (
    <WLegalShell
      eyebrow="LÉGAL · RISQUE"
      title="Avertissement sur les risques"
      intro="Le trading d'instruments financiers comporte un risque élevé de perte. Lis attentivement ce qui suit."
      sections={[
        ["Risque de perte en capital", "Le trading sur le Forex, les crypto-actifs, les CFD, les actions et les produits dérivés comporte un risque élevé et peut entraîner la perte totale de ton capital investi. N'investis que des sommes que tu peux te permettre de perdre."],
        ["Pas de conseil en investissement", "Nomerus est un outil de journalisation et d'analyse. Aucun contenu de l'application ou du site — y compris les statistiques, les suggestions du Coach IA et les exemples — ne constitue un conseil en investissement, une recommandation ou une sollicitation à acheter ou vendre un quelconque instrument. Nomerus n'est pas un intermédiaire financier au sens de la LSFin et n'est soumis à aucune surveillance de la FINMA."],
        ["Performances passées", "Les performances passées, simulées ou réelles, ne préjugent pas des performances futures. Les résultats affichés à des fins d'illustration ne garantissent aucun résultat."],
        ["Ta responsabilité", "Tes décisions de trading relèvent de ta seule responsabilité. Nomerus se connecte à tes comptes en lecture seule et n'exécute jamais d'ordre en ton nom. En cas de doute, consulte un conseiller financier réglementé."],
      ]}
    />
  );
};

// ──────────────────────────────────────────────────────────────
// CONTACT — formulaire branché sur public.contact_messages
// (INSERT anon via RLS, aucune lecture publique — voir la
// migration 20260708150000_contact_messages.sql).
// ──────────────────────────────────────────────────────────────
const NOMERUS_CONTACT_TOPICS = [
  ["general",     "Question générale"],
  ["support",     "Support / aide"],
  ["bug",         "Signaler un bug"],
  ["press",       "Presse & médias"],
  ["partnership", "Partenariat"],
  ["other",       "Autre"],
];

const WContact = ({ go }) => {
  const W = window.W;
  const Reveal = window.Reveal;
  const Icon = window.Icon;

  const [name, setName]       = React.useState("");
  const [email, setEmail]     = React.useState("");
  const [topic, setTopic]     = React.useState("general");
  const [message, setMessage] = React.useState("");
  const [trap, setTrap]       = React.useState(""); // honeypot anti-bot
  const [status, setStatus]   = React.useState("idle"); // idle | sending | sent | error
  const [errMsg, setErrMsg]   = React.useState("");

  const fieldStyle = {
    width: "100%", boxSizing: "border-box",
    background: W.bg, border: `1px solid ${W.border}`, borderRadius: 4,
    color: W.text, fontFamily: W.sans, fontSize: 14,
    padding: "11px 14px", outline: "none",
  };
  const labelStyle = { fontFamily: W.mono, fontSize: 10, color: W.textMute, letterSpacing: 1.6, display: "block", marginBottom: 6 };
  const focus = e => e.target.style.borderColor = W.indigo;
  const blur  = e => e.target.style.borderColor = W.border;

  const canSend = email.trim().length > 3 && message.trim().length >= 10 && status !== "sending";

  const submit = async (e) => {
    e.preventDefault();
    if (!canSend) return;
    // Un bot qui remplit le champ caché : on affiche « envoyé » sans rien écrire.
    if (trap) { setStatus("sent"); return; }
    setStatus("sending");
    setErrMsg("");
    const res = await window.nomerusContact.send({ name, email, topic, message });
    if (res.ok) {
      setStatus("sent");
    } else {
      setStatus("error");
      setErrMsg(res.error || "Une erreur est survenue.");
    }
  };

  const resetForm = () => {
    setName(""); setEmail(""); setTopic("general"); setMessage("");
    setStatus("idle"); setErrMsg("");
  };

  return (
    <div style={{ background: W.bg, color: W.text, fontFamily: W.sans, minHeight: "70vh" }}>
      <section style={{ borderBottom: `1px solid ${W.border}` }}>
        <div style={{ maxWidth: 1280, margin: "0 auto", padding: "clamp(52px, 6vw, 72px) 28px 44px" }}>
          <Reveal>
            <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 2, marginBottom: 14 }}>// CONTACT</div>
            <h1 style={{ fontFamily: W.sans, fontSize: "clamp(34px, 4.6vw, 52px)", fontWeight: 700, letterSpacing: -1.4, margin: "0 0 16px", lineHeight: 1.05 }}>
              Une question ? <span style={{ color: W.indigo }}>On répond vite.</span>
            </h1>
            <p style={{ fontFamily: W.sans, fontSize: 16, color: W.textDim, lineHeight: 1.6, maxWidth: 640, margin: 0 }}>
              Bug, question sur ton import CSV, demande presse ou juste envie de dire bonjour : écris-nous ici. Nomerus est un projet indie — c'est un humain qui lit, et qui répond en général sous 24 à 48 h.
            </p>
          </Reveal>
        </div>
      </section>

      <section>
        <div className="w-stack" style={{
          maxWidth: 1280, margin: "0 auto", padding: "clamp(40px, 5vw, 56px) 28px clamp(56px, 8vw, 90px)",
          display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 40, alignItems: "start",
        }}>
          {/* ── Formulaire ── */}
          <Reveal>
            <div className="w-card" style={{ background: W.panel, border: `1px solid ${W.borderStrong}`, borderRadius: 8, overflow: "hidden" }}>
              <div style={{
                padding: "10px 16px", borderBottom: `1px solid ${W.border}`,
                fontFamily: W.mono, fontSize: 10, color: W.textMute, letterSpacing: 1.6,
                display: "flex", justifyContent: "space-between",
              }}>
                <span>// NOUVEAU MESSAGE</span>
                <span style={{ color: status === "sent" ? W.green : W.indigo }}>
                  {status === "sent" ? "● ENVOYÉ" : status === "sending" ? "● ENVOI…" : "● BROUILLON"}
                </span>
              </div>

              {status === "sent" ? (
                <div style={{ padding: "clamp(32px, 4vw, 48px)", textAlign: "center" }}>
                  <div style={{
                    width: 52, height: 52, borderRadius: "50%", margin: "0 auto 18px",
                    background: "rgba(91,217,154,0.1)", border: "1px solid rgba(91,217,154,0.3)",
                    display: "flex", alignItems: "center", justifyContent: "center", color: W.green,
                  }}>
                    <Icon name="check" size={22}/>
                  </div>
                  <h2 style={{ fontFamily: W.sans, fontSize: 22, fontWeight: 700, letterSpacing: -0.5, margin: "0 0 10px" }}>Message envoyé.</h2>
                  <p style={{ fontFamily: W.sans, fontSize: 14, color: W.textDim, lineHeight: 1.65, maxWidth: 400, margin: "0 auto 24px" }}>
                    Merci ! On te répond à <span style={{ color: W.text }}>{email.trim() || "ton adresse"}</span> — en général sous 24 à 48 h ouvrées.
                  </p>
                  <button onClick={resetForm} style={{
                    background: "transparent", color: W.indigo, border: `1px solid ${W.borderStrong}`,
                    cursor: "pointer", padding: "11px 20px", borderRadius: 5,
                    fontFamily: W.mono, fontSize: 11, fontWeight: 700, letterSpacing: 1.6,
                  }}>
                    ENVOYER UN AUTRE MESSAGE
                  </button>
                </div>
              ) : (
                <form onSubmit={submit} style={{ padding: "clamp(20px, 3vw, 28px)" }}>
                  <div className="w-stack" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 16 }}>
                    <label style={{ display: "block" }}>
                      <span style={labelStyle}>NOM <span style={{ color: W.border }}>· OPTIONNEL</span></span>
                      <input type="text" value={name} maxLength={120} placeholder="Ton prénom ou pseudo"
                        onChange={e => setName(e.target.value)} onFocus={focus} onBlur={blur} style={fieldStyle}/>
                    </label>
                    <label style={{ display: "block" }}>
                      <span style={labelStyle}>EMAIL *</span>
                      <input type="email" value={email} required placeholder="toi@exemple.com"
                        onChange={e => setEmail(e.target.value)} onFocus={focus} onBlur={blur} style={fieldStyle}/>
                    </label>
                  </div>

                  <label style={{ display: "block", marginBottom: 16 }}>
                    <span style={labelStyle}>SUJET</span>
                    <select value={topic} onChange={e => setTopic(e.target.value)} onFocus={focus} onBlur={blur}
                      style={{ ...fieldStyle, cursor: "pointer", appearance: "auto" }}>
                      {NOMERUS_CONTACT_TOPICS.map(([v, l]) => <option key={v} value={v}>{l}</option>)}
                    </select>
                  </label>

                  <label style={{ display: "block", marginBottom: 6 }}>
                    <span style={labelStyle}>MESSAGE *</span>
                    <textarea value={message} required minLength={10} maxLength={4000} rows={7}
                      placeholder="Décris ta question ou ton problème. Pour un bug : ce que tu as fait, ce que tu attendais, ce qui s'est passé."
                      onChange={e => setMessage(e.target.value)} onFocus={focus} onBlur={blur}
                      style={{ ...fieldStyle, resize: "vertical", minHeight: 140, lineHeight: 1.6 }}/>
                  </label>
                  <div style={{ fontFamily: W.mono, fontSize: 10, color: W.textMute, letterSpacing: 1.2, textAlign: "right", marginBottom: 18 }}>
                    {message.trim().length} / 4000
                  </div>

                  {/* Honeypot : invisible pour les humains, rempli par les bots. */}
                  <input type="text" value={trap} onChange={e => setTrap(e.target.value)}
                    tabIndex={-1} autoComplete="off" aria-hidden="true"
                    style={{ position: "absolute", left: -9999, width: 1, height: 1, opacity: 0 }}
                    name="website" placeholder="Ne pas remplir"/>

                  {status === "error" && (
                    <div style={{
                      marginBottom: 16, padding: "11px 14px", borderRadius: 4,
                      background: "rgba(255,107,107,0.08)", border: "1px solid rgba(255,107,107,0.3)",
                      fontFamily: W.sans, fontSize: 13, color: W.red, lineHeight: 1.5,
                    }}>
                      {errMsg} — ou écris-nous directement : <WMail/>
                    </div>
                  )}

                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 14 }}>
                    <button type="submit" disabled={!canSend} className="w-cta" style={{
                      background: canSend ? W.indigo : W.panel2, color: canSend ? W.bg : W.textMute,
                      border: "none", cursor: canSend ? "pointer" : "not-allowed",
                      padding: "14px 24px", borderRadius: 5,
                      fontFamily: W.mono, fontSize: 12, fontWeight: 700, letterSpacing: 2,
                    }}>
                      {status === "sending" ? "ENVOI…" : "ENVOYER LE MESSAGE →"}
                    </button>
                    <span style={{ fontFamily: W.sans, fontSize: 12, color: W.textMute }}>
                      Ton adresse ne sert qu'à te répondre. Jamais de spam.
                    </span>
                  </div>
                </form>
              )}
            </div>
          </Reveal>

          {/* ── Infos directes ── */}
          <Reveal>
            <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
              {[
                ["EMAIL DIRECT", <span>Tu préfères ta boîte mail ? Écris-nous à <WMail/> — même canal, même humain.</span>],
                ["TEMPS DE RÉPONSE", <span>En général <span style={{ color: W.text }}>sous 24 à 48 h ouvrées</span>. Les bugs bloquants (import CSV impossible, connexion) passent en priorité.</span>],
                ["SUPPORT & BUGS", <span>Pour aller plus vite : indique ton broker, et si possible joins par email les premières lignes du CSV qui pose problème (sans données sensibles).</span>],
                ["QUESTIONS FRÉQUENTES", <span>Plans, données, brokers supportés : la réponse est peut-être déjà dans la <WLegalLink go={go} route="pricing">FAQ de la page Tarifs</WLegalLink>.</span>],
              ].map(([h, body]) => (
                <div key={h} className="w-card" style={{ background: W.panel, border: `1px solid ${W.border}`, borderRadius: 6, padding: "18px 20px" }}>
                  <div style={{ fontFamily: W.mono, fontSize: 10, color: W.indigo, letterSpacing: 1.8, marginBottom: 8 }}>// {h}</div>
                  <div style={{ fontFamily: W.sans, fontSize: 13, color: W.textDim, lineHeight: 1.65 }}>{body}</div>
                </div>
              ))}
            </div>
          </Reveal>
        </div>
      </section>
    </div>
  );
};

window.WFeatures = WFeatures;
window.WPricing = WPricing;
window.WBrokers = WBrokers;
window.WAbout = WAbout;
window.WContact = WContact;
window.WLegal = WLegal;
window.WTerms = WTerms;
window.WPrivacy = WPrivacy;
window.WRisk = WRisk;
