<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta name="theme-color" content="#000000" />

  <!-- Anti-flash light mode : pose data-theme avant le 1er paint pour
       éviter le FOUC (flash dark → light) au reload. Lit localStorage
       puis fallback sur prefers-color-scheme système. Try/catch défensifs
       pour les browsers en mode privé qui throw sur localStorage. -->
  <script>
    (function() {
      var t;
      try { t = localStorage.getItem('fpf_theme'); } catch (e) {}
      if (!t) {
        try { t = matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'; } catch (e) { t = 'dark'; }
      }
      if (t === 'light') document.documentElement.setAttribute('data-theme', 'light');
    })();
  </script>
  <!-- Meta description SEO (155 chars cible) :
       inclut "CS2" + "Aim Trainer" + axe progression + CTA explicite
       "Inscris-toi gratuitement". Aucun chiffre fabriqué (joueurs/coachs)
       qui pourrait être remis en cause. -->
  <meta name="description" content="Aim Trainer CS2 et plateforme de coaching pro pour faire progresser ton aim. Spray, peek, réaction, crosshair lab. Forge ta méthode. Inscris-toi gratuitement." />

  <!-- ─── Favicon : setup exhaustif + cache-buster ────────────────
       Le query ?v=20260610a force un re-fetch côté browsers ET pousse
       Google à re-crawler le favicon au prochain passage (sinon il garde
       en cache l'ancienne version pendant des semaines).

       Ordre de fallback observé par Google : SVG → PNG sized → ICO.
       Apple-touch-icon requis pour iOS Safari add-to-homescreen. -->
  <link rel="icon"             type="image/svg+xml" href="/favicon.svg?v=20260610a" />
  <link rel="icon"             type="image/png" sizes="32x32"   href="/favicon-32x32.png?v=20260610a" />
  <link rel="icon"             type="image/png" sizes="16x16"   href="/favicon-16x16.png?v=20260610a" />
  <link rel="icon"             type="image/png" sizes="128x128" href="/favicon-128x128.png?v=20260610a" />
  <link rel="icon"             type="image/png" sizes="256x256" href="/favicon-256x256.png?v=20260610a" />
  <link rel="apple-touch-icon"                  sizes="180x180" href="/favicon-256x256.png?v=20260610a" />
  <link rel="shortcut icon"    type="image/x-icon"              href="/favicon.ico?v=20260610a" />
  <link rel="manifest"         href="/manifest.json?v=20260610a" />

  <!-- Fonts self-hostees via @fontsource → bundlees par Vite dans dist/assets/.
       Plus de preconnect Google Fonts ni de stylesheet cross-origin :
       SRI implicite (same-origin), CSP plus strict, zero tracking Google. -->

  <!-- Origins critiques de l'app : worker (API REST + image beacons),
       Supabase (auth + DB direct), Steam CDN (icônes skins).
       preconnect = DNS + TCP + TLS handshake declenches au parse du HTML
       au lieu d'attendre le 1er fetch JS → gain ~150-300ms sur le LCP
       quand l'inventaire/coachs/articles arrive. crossorigin obligatoire
       pour les origines qui retournent du JSON/binaire (CORS preflight). -->
  <link rel="preconnect" href="https://api.fpsforge.pro" crossorigin />
  <link rel="preconnect" href="https://zotxikpfnwmuihwajmwi.supabase.co" crossorigin />
  <link rel="preconnect" href="https://community.cloudflare.steamstatic.com" crossorigin />
  <!-- Fallback dns-prefetch pour les vieux navigateurs qui ignorent preconnect.
       Bénéfique aussi si le browser limite les preconnect (Chrome cap a 6). -->
  <link rel="dns-prefetch" href="https://api.fpsforge.pro" />
  <link rel="dns-prefetch" href="https://zotxikpfnwmuihwajmwi.supabase.co" />
  <link rel="dns-prefetch" href="https://community.cloudflare.steamstatic.com" />

  <!-- Fonts (Inter + Barlow Condensed + JetBrains Mono) sont importees dans
       src/main.jsx via @fontsource → bundle Vite, asset same-origin avec
       hash de cache + SRI implicite. -->


  <!-- Analytics produit : PostHog (EU), initialisé dans src/main.jsx via
       src/lib/analytics.js. Couvre pageviews + events produit. Aucun script
       analytics tiers ici. -->

  <title>FPS Forge | Aim Trainer CS2 & Plateforme de Coaching</title>

  <!-- Canonical URL : signale a Google que fpsforge.pro est le domaine
       canonique meme si on est servi via fpsforge.pages.dev (preview deploys
       Cloudflare) ou un alias. Evite la duplication d'index. -->
  <link rel="canonical" href="https://fpsforge.pro/" />

  <!-- Open Graph + Twitter card pour previews des partages (Discord, Twitter,
       LinkedIn, etc.). og:image doit etre absolu (les bots ne resolvent pas
       les paths relatifs). 1200x630 ratio recommande pour Facebook/LinkedIn,
       compatible Twitter summary_large_image. -->
  <meta property="og:type"        content="website" />
  <meta property="og:site_name"   content="FPS Forge" />
  <meta property="og:title"       content="FPS Forge | Aim Trainer CS2 & Plateforme de Coaching" />
  <meta property="og:description" content="Aim Trainer CS2 et plateforme de coaching pro pour faire progresser ton aim. Spray, peek, réaction, crosshair lab." />
  <meta property="og:url"         content="https://fpsforge.pro" />
  <meta property="og:image"       content="https://fpsforge.pro/og-image.png" />
  <meta property="og:image:width"  content="1200" />
  <meta property="og:image:height" content="630" />
  <meta property="og:image:alt"    content="FPS Forge — Aim Trainer CS2 et plateforme de coaching" />
  <meta property="og:locale"      content="fr_FR" />
  <meta name="twitter:card"        content="summary_large_image" />
  <meta name="twitter:title"       content="FPS Forge | Aim Trainer CS2" />
  <meta name="twitter:description" content="Aim Trainer CS2 + plateforme coaching pro. Forge ta méthode." />
  <meta name="twitter:image"       content="https://fpsforge.pro/og-image.png" />
  <meta name="twitter:image:alt"   content="FPS Forge — Aim Trainer CS2 et plateforme de coaching" />

  <!-- Données structurées Schema.org (JSON-LD) — type SoftwareApplication.
       Pas d'aggregateRating ni review : on ne fabrique pas de note pour
       les Rich Results Google (risque de pénalité si les avis sont fakés).
       offers price=0 EUR signale clairement l'inscription gratuite à Google.
       Le bot lit ce script directement → aucun rendu côté user impacté. -->
  <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "SoftwareApplication",
    "name": "FPS Forge",
    "url": "https://fpsforge.pro",
    "description": "Aim Trainer CS2 et plateforme de coaching pro pour faire progresser ton aim. Spray, peek, réaction, crosshair lab.",
    "applicationCategory": "GameApplication",
    "operatingSystem": "WebBrowser",
    "offers": {
      "@type": "Offer",
      "price": "0",
      "priceCurrency": "EUR"
    }
  }
  </script>

  <!-- Skeleton du hero (perf P1) : peint le H1 = élément LCP en HTML STATIQUE,
       avant le téléchargement des ~282 Ko de JS critique sur réseau lent.
       Overlay plein écran HORS #root (sinon React l'efface au mount et on voit
       le spinner). Retiré par HomeHero quand le vrai hero est prêt, + filet de
       sécurité timeout + retrait immédiat hors route "/". LCP mesuré : 4,4 s → cible ~1 s. -->
  <style>
    #hero-skeleton{position:fixed;inset:0;z-index:9998;display:flex;flex-direction:column;
      align-items:center;justify-content:center;text-align:center;background:#0a0a0a;color:#fff;
      padding:0 20px;font-family:Inter,system-ui,Arial,sans-serif}
    #hero-skeleton .skk{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:11px;
      letter-spacing:.2em;text-transform:uppercase;color:#8e8e96;margin-bottom:14px}
    #hero-skeleton .skk b{color:#E24B4A;font-weight:400}
    /* font-size = MÊME formule que le vrai H1 (mobile clamp 58/17vw/96, desktop 128)
       → le skeleton H1 est ≥ au vrai H1, donc IL est l'élément LCP (peint tôt) et
       le vrai H1 révélé ensuite (taille égale/moindre) ne le supplante pas. */
    #hero-skeleton h1{font-family:'Barlow Condensed','Arial Narrow',sans-serif;
      font-weight:900;text-transform:uppercase;line-height:.9;letter-spacing:-.01em;
      font-size:clamp(58px,17vw,128px);margin:0 0 24px}
    #hero-skeleton h1 .r{color:#E24B4A}
    #hero-skeleton .skcta{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:13px;
      letter-spacing:.06em;text-transform:uppercase;background:#E24B4A;color:#fff;padding:15px 26px;border-radius:4px}
  </style>
  <script type="module" crossorigin src="/assets/index-Bh4M8xnI.js"></script>
  <link rel="modulepreload" crossorigin href="/assets/supabase-DvKtIBDb.js">
  <link rel="stylesheet" crossorigin href="/assets/index-w3A8WUE_.css">
  <link rel="preload" as="font" type="font/woff2" crossorigin href="/assets/barlow-condensed-latin-900-normal-SFh9ViAc.woff2" />
  <link rel="preload" as="font" type="font/woff2" crossorigin href="/assets/inter-latin-800-normal-BYj_oED-.woff2" />
  <link rel="preload" as="font" type="font/woff2" crossorigin href="/assets/inter-latin-700-normal-Yt3aPRUw.woff2" />
</head>
<body>
  <div id="hero-skeleton" aria-hidden="true">
    <div class="skk"><b>●</b> LE HUB CS2 · GRATUIT</div>
    <h1>MAÎTRISE TON<br><span class="r">CROSSHAIR.</span></h1>
    <div class="skcta">ESSAYER SANS COMPTE →</div>
  </div>
  <div id="root"></div>
  <script>
    /* skeleton uniquement sur la home ; ailleurs on le retire avant le paint.
       Filet de sécurité : retrait après 8 s si HomeHero ne l'a pas fait (erreur de chunk). */
    (function () {
      var sk = document.getElementById('hero-skeleton');
      if (!sk) return;
      if (location.pathname !== '/') { sk.remove(); return; }
      setTimeout(function () { try { sk.remove(); } catch (e) {} }, 8000);
    })();
  </script>
<!-- Cloudflare Pages Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "b7c2fa569abf4172a10ac946adf38084"}'></script><!-- Cloudflare Pages Analytics --></body>
</html>
