// ArticlePage — full article template with cover, highlights, table, FAQ

const ArticlePage = ({ slug, articles, onBack, onOpen }) => {
  const a = articles.find(x => x.slug === slug) || articles[0];
  const related = articles.filter(x => x.slug !== a.slug).slice(0, 3);
  const [openFaq, setOpenFaq] = React.useState(0);

  React.useEffect(() => { window.scrollTo({ top: 0, behavior: 'instant' }); }, [slug]);

  return (
    <div className="article-page">
      <div className="article-wrap">
        <div className="back-row">
          <button className="back-btn" onClick={onBack}>
            <span className="back-arrow">←</span> Retour aux articles
          </button>
        </div>

        <header className="article-head">
          <div className="article-meta-top">
            <span className="article-cat-pill">{a.cat}</span>
            <span className="dot-sep">·</span>
            <span className="mono">{a.date}</span>
            <span className="dot-sep">·</span>
            <span className="mono">{a.read} MIN DE LECTURE</span>
          </div>
          <h1 className="article-title serif">{a.title}</h1>
          <p className="article-deck">{a.excerpt}</p>
          <div style={{ display: 'flex', justifyContent: 'center' }}>
            <div className="article-author">
              <span className="card-author-avatar" style={{ background: `oklch(70% 0.04 ${a.slug.length * 23})`, width: 36, height: 36, fontSize: 13 }}>
                {a.author.split(' ').map(s => s[0]).join('')}
              </span>
              <div style={{ textAlign: 'left' }}>
                <div className="article-author-name">{a.author}</div>
                <div className="article-author-role">Analyste senior · Hardware & Semi-conducteurs</div>
              </div>
            </div>
          </div>
        </header>

        <div className="article-cover" style={{ background: a.cover }}>
          <Motif kind={a.motif} />
          <div className="article-cover-overlay" />
        </div>

        <div className="prose-col">
          <article className="article-prose">
          <div className="highlights">
            <div className="highlights-label mono"><span className="dot dot-accent"></span> CE QU'IL FAUT RETENIR</div>
            <ul>
              <li><span className="hl-emoji">📈</span><div><strong>Marges exceptionnelles</strong> — la pricing power est intacte malgré la concurrence annoncée.</div></li>
              <li><span className="hl-emoji">🏗️</span><div><strong>Capex saturé</strong> — le carnet de commandes 2027 est déjà rempli à 84%.</div></li>
              <li><span className="hl-emoji">⚡</span><div><strong>Énergie</strong> — chaque rack consomme 132 kW, soit 8x un serveur classique.</div></li>
              <li><span className="hl-emoji">🌍</span><div><strong>Géographie</strong> — 71% des capacités installées le sont en Amérique du Nord.</div></li>
            </ul>
          </div>

          <p className="lede" id="intro">
            <span className="dropcap">L</span>orsque NVIDIA a présenté Blackwell B200 fin 2024, peu d'analystes
            anticipaient que la génération suivante creuserait l'écart à ce point. <strong>Deux ans plus tard,
            les chiffres sont sans appel</strong> : 78% de marge brute, un carnet de commandes saturé jusqu'au
            quatrième trimestre 2027, et une capitalisation qui a doublé depuis l'annonce.
          </p>

          <p>
            Pourtant, à chaque trimestre, des voix s'élèvent pour annoncer la fin du règne. Google avec ses TPU,
            Amazon avec Trainium, AMD avec MI400 — tous promettent de briser le monopole. Aucun n'y est parvenu.
            Cet article propose une lecture des raisons structurelles, au-delà du simple effet de mode.
          </p>

          <h2 id="analyse" className="serif">L'analyse en trois points</h2>

          <h3 className="serif">1. CUDA : le fossé invisible</h3>
          <p>
            Le hardware seul ne suffit pas. CUDA, l'environnement logiciel propriétaire de NVIDIA, totalise
            <strong> 4 millions de développeurs actifs</strong> et 18 ans d'optimisations cumulées. Migrer une
            stack ML d'envergure vers une alternative coûte entre 6 et 24 mois d'ingénierie — un coût
            d'opportunité que la plupart des acteurs refusent d'assumer tant que les performances suivent.
          </p>

          <h3 className="serif">2. NVLink et la bande passante mémoire</h3>
          <p>
            Sur des charges d'entraînement à grande échelle, ce n'est plus le compute qui limite, c'est la
            bande passante entre puces. NVLink 5 atteint <strong>1.8 TB/s</strong> par GPU, soit 14x ce
            qu'offre PCIe 5.0. Sans interconnect équivalent, les concurrents sont relégués à l'inférence —
            un marché plus large mais aux marges divisées par trois.
          </p>

          <h3 className="serif">3. L'effet Jensen</h3>
          <p>
            Roadmap publique sur 5 ans, annonces synchronisées avec les besoins clients, capacité d'exécution
            quasi-militaire. <span className="hl">NVIDIA tient sa cadence depuis 12 ans sans glissement majeur</span> —
            une régularité que le marché valorise désormais comme un moat à part entière.
          </p>

          <h2 id="chiffres" className="serif">Les chiffres-clés en un coup d'œil</h2>

          <div className="table-wrap">
            <table className="data-table">
              <thead>
                <tr><th>Métrique</th><th>2024</th><th>2025</th><th>2026e</th><th className="trend">Tendance</th></tr>
              </thead>
              <tbody>
                <tr><td>Revenus Datacenter (Mds $)</td><td>47.5</td><td>98.2</td><td>156.4</td><td><span className="trend-up">↑ +59%</span></td></tr>
                <tr><td>Marge brute</td><td>72%</td><td>76%</td><td>78%</td><td><span className="trend-up">↑ stable</span></td></tr>
                <tr><td>Carnet de commandes (mois)</td><td>9</td><td>14</td><td>18</td><td><span className="trend-up">↑ saturé</span></td></tr>
                <tr><td>Concurrents crédibles</td><td>0</td><td>1</td><td>2</td><td><span className="trend-flat">→ marginal</span></td></tr>
                <tr><td>Part de marché GPU IA</td><td>92%</td><td>89%</td><td>85%</td><td><span className="trend-down">↓ érosion lente</span></td></tr>
              </tbody>
            </table>
            <div className="table-source mono">SOURCE : RAPPORTS ANNUELS, ESTIMATIONS BLOOMBERG · MAJ 04/2026</div>
          </div>

          <h2 id="these" className="serif">La thèse d'investissement</h2>

          <blockquote className="pullquote">
            <span className="quote-mark">"</span>
            <p>Tant que l'effort d'entraînement des modèles de fondation continue de doubler tous les six mois,
            le goulet d'étranglement restera le compute — et NVIDIA reste le seul fournisseur capable de livrer
            à l'échelle requise.</p>
            <cite>— Théo Marchand, Avril 2026</cite>
          </blockquote>

          <p>
            La question n'est plus de savoir si NVIDIA est cher. La question est de savoir <em>combien de
            temps</em> le multiple peut tenir. Notre estimation : tant que les hyperscalers (Microsoft, Google,
            Amazon, Meta) maintiennent leur capex collectif au-dessus de 280 Mds $, soit au moins jusqu'à
            mi-2027.
          </p>

          <p>
            Le risque principal n'est ni AMD, ni Google, ni la Chine. C'est <strong>une rupture méthodologique</strong> —
            un nouveau paradigme d'apprentissage qui rendrait inutile la course au compute brut. Les premiers
            signaux existent (mixture-of-experts, modèles de raisonnement), mais aucun n'a encore renversé
            l'équation économique.
          </p>

          <h2 id="faq" className="serif">Questions fréquentes</h2>
          <div className="faq">
            {[
              { q: "Faut-il acheter NVIDIA aujourd'hui ?", a: "Cet article ne constitue pas un conseil en investissement. Notre méthodologie consiste à exposer les facteurs structurels — la décision d'allocation reste personnelle et doit tenir compte de votre horizon, de votre tolérance au risque, et de la composition globale de votre portefeuille." },
              { q: "Quelle est la différence entre Blackwell et Hopper ?", a: "Blackwell (B200) double la performance d'entraînement par rapport à Hopper (H100) tout en réduisant la consommation par token de 25%. La principale innovation est l'architecture dual-die qui permet d'embarquer 208 milliards de transistors par puce." },
              { q: "Les TPU de Google ne sont-ils pas compétitifs ?", a: "Pour des charges spécifiques (notamment l'inférence sur des modèles Google), oui. Mais ils ne sont pas commercialisés en dehors de Google Cloud, ce qui limite leur impact sur le marché captable par les concurrents externes." },
              { q: "Quel est le risque géopolitique principal ?", a: "Les restrictions d'export vers la Chine ont déjà coûté environ 8 Mds $ de revenus à NVIDIA. Une escalade pourrait amputer 12-15% des revenus annuels, mais serait probablement compensée par la demande domestique américaine et européenne." },
              { q: "Existe-t-il des alternatives via ETF ?", a: "Plusieurs ETF (BOTZ, AIQ, IRBO) offrent une exposition au secteur. Voir notre comparatif détaillé pour les frais et la composition réelle de chaque produit." },
            ].map((f, i) => (
              <div key={i} className={"faq-item" + (openFaq === i ? " is-open" : "")}>
                <button className="faq-q" onClick={() => setOpenFaq(openFaq === i ? -1 : i)}>
                  <span className="faq-num mono">0{i+1}</span>
                  <span className="faq-text">{f.q}</span>
                  <span className="faq-toggle">{openFaq === i ? "−" : "+"}</span>
                </button>
                <div className="faq-a">
                  <div className="faq-a-inner">{f.a}</div>
                </div>
              </div>
            ))}
          </div>

          <div className="article-tags">
            <span className="mono tag-label">TAGS</span>
            <span className="tag">NVIDIA</span>
            <span className="tag">Hardware</span>
            <span className="tag">Semi-conducteurs</span>
            <span className="tag">Datacenter</span>
            <span className="tag">Long terme</span>
          </div>

          <div className="article-end">
            <div className="end-line"></div>
            <span className="mono">FIN DE L'ARTICLE</span>
            <div className="end-line"></div>
          </div>
        </article>
        </div>
      </div>

      <section className="related" style={{ marginTop: 48 }}>
        <div className="container">
          <div className="related-head">
            <h2 className="serif">À lire ensuite</h2>
            <a href="#" className="related-all" onClick={(e) => { e.preventDefault(); onBack(); }}>
              Tous les articles <span className="arrow">→</span>
            </a>
          </div>
          <div className="grid-3">
            {related.map(r => <ArticleCard key={r.slug} a={r} onOpen={onOpen} />)}
          </div>
        </div>
      </section>
    </div>
  );
};

window.ArticlePage = ArticlePage;

// === Subscribe Page ===
const SubscribePage = ({ onBack }) => {
  const [plan, setPlan] = React.useState("annual");
  const [email, setEmail] = React.useState("");
  const [name, setName] = React.useState("");
  const [done, setDone] = React.useState(false);
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState("");

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (submitting) return;
    setError("");
    setSubmitting(true);
    try {
      const res = await fetch("/api/subscribe", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ email, firstname: name, plan }),
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        const code = data && data.error;
        setError(
          code === "invalid_email"
            ? "Cet email ne semble pas valide."
            : "Une erreur est survenue. Réessayez dans un instant."
        );
        return;
      }
      setDone(true);
    } catch {
      setError("Connexion impossible. Vérifiez votre réseau et réessayez.");
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="subscribe-page">
      <div className="subscribe-wrap">
        <button className="back-btn" onClick={onBack} style={{ marginBottom: 32 }}>
          <span className="back-arrow">←</span> Retour
        </button>
        <div className="subscribe-grid">
          <div>
            <div className="sub-eyebrow"><span className="dot-live"></span> Newsletter premium</div>
            <h1 className="serif sub-title">Rejoignez les <span className="accent">12 400</span> investisseurs qui prennent l'IA au sérieux.</h1>
            <p className="sub-deck">
              Une analyse approfondie chaque mardi, des notes de marché à chaud, et l'accès complet aux archives — sans publicité, sans sponsor, sans bullshit.
            </p>
            <ul className="sub-perks">
              <li><span className="check">✓</span><div><strong>Une analyse longue</strong> chaque mardi matin (12-18 min de lecture)</div></li>
              <li><span className="check">✓</span><div><strong>Des notes de marché</strong> publiées à chaud sur les annonces majeures</div></li>
              <li><span className="check">✓</span><div><strong>Accès illimité</strong> à 142 analyses archivées et au glossaire</div></li>
              <li><span className="check">✓</span><div><strong>Tableaux de données</strong> mis à jour mensuellement (ETF, valorisations, capex)</div></li>
              <li><span className="check">✓</span><div><strong>Désabonnement</strong> en un clic, à tout moment</div></li>
            </ul>
          </div>
          <div className="sub-card">
            {done ? (
              <div style={{ padding: '40px 0', textAlign: 'center' }}>
                <div style={{ fontSize: 48, marginBottom: 16 }}>✉️</div>
                <h3 className="serif" style={{ marginBottom: 8 }}>Bienvenue, {name || 'investisseur'}.</h3>
                <p style={{ color: 'var(--ink-2)', fontSize: 14 }}>Un email de confirmation vient d'être envoyé à {email}.</p>
              </div>
            ) : (
              <form className="sub-form" onSubmit={handleSubmit}>
                <h3 className="serif">Commencer l'abonnement</h3>
                <div className="sub-card-sub">14 jours d'essai gratuit · sans engagement</div>

                <div className="sub-field">
                  <label>Prénom</label>
                  <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Théo" required disabled={submitting} />
                </div>
                <div className="sub-field">
                  <label>Email</label>
                  <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="vous@email.fr" required disabled={submitting} />
                </div>
                <div className="sub-field">
                  <label>Formule</label>
                  <div className="sub-radio">
                    <div className={"sub-radio-opt" + (plan === "monthly" ? " on" : "")} onClick={() => !submitting && setPlan("monthly")}>
                      <div className="sub-radio-h">Mensuel<span className="sub-radio-price">9 € / mois</span></div>
                      <div className="sub-radio-d">Flexible</div>
                    </div>
                    <div className={"sub-radio-opt" + (plan === "annual" ? " on" : "")} onClick={() => !submitting && setPlan("annual")}>
                      <div className="sub-radio-h">Annuel<span className="sub-radio-price">79 € / an</span></div>
                      <div className="sub-radio-d">Économisez 27%</div>
                    </div>
                  </div>
                </div>
                {error && (
                  <div className="sub-error" role="alert" style={{ color: '#b91c1c', fontSize: 13, marginTop: 4 }}>{error}</div>
                )}
                <button type="submit" className="btn btn-primary sub-submit" disabled={submitting}>
                  {submitting ? "Envoi…" : <>Démarrer l'essai gratuit <span className="arrow">→</span></>}
                </button>
                <div className="sub-fine">Aucun prélèvement durant les 14 premiers jours. Annulation possible à tout moment.</div>
              </form>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

window.SubscribePage = SubscribePage;
