/* La Tournée — site : compte (Supabase) + abonnement (Stripe). Contenu Premium servi par API. */
const { useState, useEffect, useRef } = React;


/* ============================================================
   PARDY — jeu de soirée
   3 niveaux (Soft / Hot / Extrême) sur Action ou Vérité, Je n'ai jamais,
   Tu préfères. PMU & Imposteur restent en version unique.
   Hot + Extrême = contenu premium (paywall).
   ============================================================ */

const C = {
  bg: "#0A0418", bg2: "#140A24", surface: "#1C0F30", surface2: "#271542",
  line: "#34204C", text: "#F5EFE8", muted: "#A99CBC",
  pink: "#FF3D8E", green: "#2FD673", cyan: "#37C3FF", purple: "#9A5BFF", amber: "#FF9F1C",
  hot: "#FF2E83", extreme: "#E11D48",
};
const DISPLAY = "'Syne', sans-serif";
const BODY = "'Outfit', sans-serif";

let LANG = "fr";
const t = (fr, en) => (LANG === "en" ? en : fr);
const GAME_I18N = {
  av: { name: "Truth or Dare", tag: "The classic that escalates" },
  tp: { name: "Would You Rather", tag: "The dilemma that divides" },
  jnj: { name: "Never Have I Ever", tag: "Confessions come out" },
  qp: { name: "Who's Most Likely To", tag: "Most pointed-at takes a penalty" },
  pmu: { name: "Horse Race", tag: "The PMU race" },
  riv: { name: "The River", tag: "Higher, lower, red or black" },
  imp: { name: "Impostor", tag: "A liar among you" },
};
const CONTACT_EMAIL = "support.pardy@gmail.com";
const mailto = (subject, body) => { window.location.href = "mailto:" + CONTACT_EMAIL + "?subject=" + encodeURIComponent(subject) + "&body=" + encodeURIComponent(body); };

const LEVELS = {
  soft: { label: "Soft", badge: null, color: C.text },
  hot: { label: "Hot", badge: "HOT", color: C.hot },
  extreme: { label: "Extrême", badge: "EXTRÊME", color: C.extreme },
};
// jeux concernés par les niveaux
const LEVELLED = ["av", "jnj", "tp", "qp"];

const GAMES = [
  { id: "av", name: "Action ou Vérité", tag: "Le classique qui dérape", emoji: "🎯", color: C.pink, levelled: true, img: "assets/images/jeu-action-ou-verite.png" },
  { id: "tp", name: "Tu préfères", tag: "Le dilemme qui divise", emoji: "⚖️", color: C.amber, levelled: true, img: "assets/images/jeu-tu-preferes.png" },
  { id: "jnj", name: "Je n'ai jamais", tag: "Les confessions tombent", emoji: "🙊", color: C.cyan, levelled: true, img: "assets/images/jeu-je-nai-jamais.png" },
  { id: "qp", name: "Qui pourrait", tag: "Le plus désigné prend une pénalité", emoji: "👉", color: "#FF6B4A", levelled: true, img: "assets/images/jeu-qui-pourrait.png" },
  { id: "pmu", name: "PMU", tag: "La course de chevaux", emoji: "🐎", color: C.green, levelled: false, img: "assets/images/jeu-pmu.png" },
  { id: "riv", name: "Rivière", tag: "Plus, moins, rouge ou noir", emoji: "🌊", color: "#17C3B2", levelled: false, img: "assets/images/jeu-riviere.png" },
  { id: "imp", name: "Imposteur", tag: "Un menteur parmi vous", emoji: "🕵️", color: C.purple, levelled: false, img: "assets/images/jeu-imposteur.png" },
];

function Ic({ name, size = 20, color = "currentColor", sw = 1.8, fill = "none", style }) {
  const P = {
    flame: <path d="M12 3c.6 2.6-1.6 3.6-1.6 5.6A2.4 2.4 0 0 0 13 11c.3-1 .2-2 .2-2 1.3 1 2.4 2.7 2.4 4.6a5.6 5.6 0 1 1-11.2 0c0-2.3 1.3-4 2.7-5.2C8.8 6.8 10.6 5.4 12 3Z" />,
    burst: <g><circle cx="12" cy="12" r="2.6" /><path d="M12 2v3.2M12 18.8V22M2 12h3.2M18.8 12H22M4.9 4.9l2.3 2.3M16.8 16.8l2.3 2.3M19.1 4.9l-2.3 2.3M7.2 16.8l-2.3 2.3" /></g>,
    lock: <g><rect x="5" y="11" width="14" height="9" rx="2" /><path d="M8 11V7.5a4 4 0 0 1 8 0V11" /></g>,
    bolt: <path d="M13 2 4.6 13.4H11l-1 8.6L19.4 10H13z" />,
    chat: <g><path d="M4 5.5h16a1.5 1.5 0 0 1 1.5 1.5v8.5a1.5 1.5 0 0 1-1.5 1.5H9.5L5 21v-3.5H4a1.5 1.5 0 0 1-1.5-1.5V7A1.5 1.5 0 0 1 4 5.5Z" /><circle cx="8.5" cy="11.2" r=".7" /><circle cx="12" cy="11.2" r=".7" /><circle cx="15.5" cy="11.2" r=".7" /></g>,
    globe: <g><circle cx="12" cy="12" r="9" /><path d="M3 12h18M12 3c2.6 2.7 2.6 15.3 0 18M12 3c-2.6 2.7-2.6 15.3 0 18" /></g>,
    gem: <g><path d="M5 4h14l3 5-10 12L2 9z" /><path d="M2 9h20M9 4l-2.5 5L12 21M15 4l2.5 5L12 21" /></g>,
    restore: <g><path d="M20.5 12a8.5 8.5 0 1 1-2.7-6.2" /><path d="M20.5 4v5h-5" /></g>,
    star: <path d="M12 3.2l2.6 5.5 5.9.8-4.3 4.1 1.1 5.9L12 17.7 6.7 19.5l1.1-5.9L3.5 9.5l5.9-.8z" />,
    bulb: <g><path d="M9.5 18h5M10.5 21h3" /><path d="M12 3a6 6 0 0 0-4 10.5c.7.7 1 1.3 1 2.5h6c0-1.2.3-1.8 1-2.5A6 6 0 0 0 12 3Z" /></g>,
    mail: <g><rect x="3" y="5" width="18" height="14" rx="2" /><path d="M3.5 6.5 12 13l8.5-6.5" /></g>,
    user: <g><circle cx="12" cy="8" r="3.5" /><path d="M5 20a7 7 0 0 1 14 0" /></g>,
  };
  return <svg viewBox="0 0 24 24" width={size} height={size} fill={fill} stroke={color} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round" style={style}>{P[name]}</svg>;
}

/* ====================== CONTENUS ====================== */

/* ---------- ACTION OU VÉRITÉ ---------- */
const AV = {
  soft: {
    verites: [
      "Quelle est la dernière chose un peu honteuse que tu as faite ?",
      "Quel est le plus gros mensonge que tu as raconté à tes parents ?",
      "Quelle appli tu caches en premier quand on regarde ton téléphone ?",
      "Quel est ton talent le plus inutile ?",
      "Quelle est la chose la plus chère achetée sur un coup de tête ?",
      "Quel surnom détestes-tu qu'on te donne ?",
      "Quelle est ta plus grosse honte au lycée ?",
      "Quel est le dernier truc bizarre que tu as cherché sur internet ?",
      "Combien de temps tu tiens sans ton téléphone, vraiment ?",
      "Quelle est la rumeur la plus folle qui a couru sur toi ?",
      "Quel est ton pire souvenir de soirée ?",
      "Quelle habitude bizarre tu as quand tu es seul ?",
      "Quel est le plus gros bobard dit pour impressionner quelqu'un ?",
      "Quelle est la chose la plus enfantine que tu fais encore ?",
      "Quel est ton plaisir coupable musical ?",
      "As-tu déjà fait semblant d'être malade, et pourquoi ?",
      "C'est quoi la dernière fois où tu as pleuré, et pourquoi ?",
      "Quel est le truc le plus radin que tu aies fait ?",
      "Quelle est ta plus grande peur irrationnelle ?",
      "Quel compliment t'a le plus marqué dans ta vie ?",
      "Qui est la dernière personne que tu as stalkée en ligne ?",
      "Quel est ton pire rendez-vous galant ?",
      "Quelle est la chose la plus folle sur ta liste de rêves ?",
      "Quel mensonge tu répètes le plus souvent ?",
      "Quelle est la dernière fois où tu as eu honte en public ?",
      "Si tu pouvais effacer un souvenir, lequel ?",
      "Quel défaut tu assumes le moins ?",
      "Quelle est la chose la plus impulsive que tu aies faite ?",
      "Quel est ton souvenir le plus gênant d'école ?",
      "Quelle est la dépense la plus inutile de ton mois ?",
      "Quel est le pire cadeau que tu aies reçu ?",
      "Quelle est ta plus grande fierté secrète ?",
    ],
    actions: [
      "Imite ton prof le plus relou.",
      "Fais deviner un animal en le mimant, interdiction de parler.",
      "Parle uniquement en chantant jusqu'à ton prochain tour.",
      "Fais l'imitation la plus convaincante d'un autre joueur.",
      "Raconte une blague : si personne ne rit, prends une pénalité.",
      "Mime ton réveil un lundi matin.",
      "Fais 10 secondes de ta meilleure danse ridicule.",
      "Prends l'accent de ton choix jusqu'à ton prochain tour.",
      "Fais un compliment sincère à chaque personne du cercle.",
      "Imite un influenceur connu pendant 15 secondes.",
      "Mime un sport sans dire lequel, le groupe devine.",
      "Invente un slogan de pub pour la personne à ta droite.",
      "Fais semblant d'être un présentateur météo en pleine tempête.",
      "Parle comme un robot jusqu'à ton prochain tour.",
      "Fais le bruitage d'un film d'action pendant 15 secondes.",
      "Goûte un aliment choisi par le groupe les yeux fermés et devine ce que c'est.",
      "Fais ta plus belle grimace et tiens-la 10 secondes.",
      "Imite la démarche de quelqu'un du groupe, on doit deviner qui.",
      "Chante Joyeux anniversaire façon chanteur d'opéra.",
      "Raconte ta journée comme si c'était un film d'horreur.",
      "Fais semblant de gagner un award et remercie tout le monde en pleurant.",
      "Tente de lécher ton coude, oui essaie vraiment.",
      "Traverse la pièce en marche arrière en te commentant comme un GPS.",
      "Fais une pub télé pour un objet posé devant toi.",
    ],
  },
  hot: { verites: [], actions: [] },
  extreme: { verites: [], actions: [] },
};

/* ---------- JE N'AI JAMAIS ---------- */
const JNJ_POOLS = {
  soft: [
    "séché un cours pour dormir.",
    "envoyé un message à la mauvaise personne.",
    "fait semblant d'être malade pour éviter un truc.",
    "pleuré devant un film d'animation.",
    "chanté à tue-tête sous la douche.",
    "stalké un ex sur les réseaux.",
    "menti sur mon âge.",
    "mangé un truc tombé par terre.",
    "oublié le prénom de quelqu'un en pleine conversation.",
    "fait semblant de connaître une chanson.",
    "dormi pendant un film au cinéma.",
    "ri à un moment totalement inapproprié.",
    "fait semblant de répondre au téléphone pour éviter quelqu'un.",
    "oublié l'anniversaire d'un proche.",
    "gardé un objet emprunté beaucoup trop longtemps.",
    "fait croire que j'avais lu un livre.",
    "pris un selfie plus de vingt fois pour LE bon.",
    "fait semblant d'aimer un cadeau.",
    "ri tout seul en repensant à un truc en public.",
    "porté un vêtement deux jours de suite sans le laver.",
    "menti pour ne pas aller à une soirée.",
    "fait semblant de comprendre une blague.",
    "googlé mon propre nom.",
    "mangé le dernier truc en cachette.",
    "regardé une série entière en une nuit.",
    "perdu mes clés ou mon téléphone en soirée.",
    "liké une vieille photo par accident.",
    "raconté une histoire en l'exagérant énormément.",
    "fait un détour pour éviter quelqu'un.",
    "fait semblant de bosser quand le chef passait.",
    "dansé seul dans ma chambre.",
    "promis que j'arrivais sans même être prêt.",
    "envoyé un vocal de cinq minutes que personne n'a écouté.",
    "oublié où j'avais garé.",
    "ri d'une blague que je n'avais pas comprise.",
    "abandonné une série en plein milieu.",
    "zappé tous les snooze de mon réveil.",
    "mangé au lit.",
    "parlé tout seul à voix haute.",
    "cherché mon téléphone alors qu'il était dans ma main.",
    "fait semblant d'écouter en pensant à autre chose.",
    "recraché discrètement un truc pas bon dans une serviette.",
    "fait semblant d'avoir vu un film célèbre.",
    "applaudi au mauvais moment.",
    "trébuché en pensant que personne ne regardait.",
    "oublié de répondre à un message pendant des jours.",
    "chanté faux exprès pour faire rire.",
    "fait la sieste au lieu de réviser.",
    "menti sur le fait d'avoir fini un travail.",
    "mis un like puis regretté direct.",
    "fait semblant d'aimer un plat pour ne pas vexer.",
    "évité quelqu'un en faisant semblant de téléphoner.",
  ],
  hot: [],
  extreme: [],
};

/* ---------- TU PRÉFÈRES ---------- */
const TP = {
  soft: [
      { a: "Pouvoir voler", b: "Être invisible" },
      { a: "Vivre sans musique", b: "Vivre sans films" },
      { a: "Avoir toujours trop chaud", b: "Avoir toujours trop froid" },
      { a: "Ne plus jamais manger de fromage", b: "Ne plus jamais manger de chocolat" },
      { a: "Une semaine sans téléphone", b: "Un mois sans télé" },
      { a: "Gagner au loto mais perdre tes amis", b: "Rester comme aujourd'hui" },
      { a: "Parler toutes les langues", b: "Parler à tous les animaux" },
      { a: "Être célèbre mais détesté", b: "Inconnu mais adoré" },
      { a: "Manger seulement salé à vie", b: "Manger seulement sucré à vie" },
      { a: "Voyager dans le passé", b: "Voyager dans le futur" },
      { a: "Ne plus jamais mentir", b: "Ne plus jamais jurer" },
      { a: "Une mémoire parfaite", b: "Un sommeil parfait" },
      { a: "Vivre à la montagne", b: "Vivre au bord de la mer" },
      { a: "Travailler la nuit", b: "Te lever à 5h chaque jour" },
      { a: "Lire dans les pensées", b: "Voir l'avenir" },
      { a: "Ne plus jamais tomber malade", b: "Ne plus jamais te blesser" },
      { a: "Un million tout de suite", b: "Cinq mille par mois à vie" },
      { a: "Être le plus drôle de la pièce", b: "Être le plus intelligent" },
      { a: "Perdre la vue un jour", b: "Perdre l'ouïe une semaine" },
      { a: "Ton plat préféré tous les jours", b: "Ne jamais remanger le même plat" },
      { a: "Vivre sans réseaux sociaux", b: "Vivre sans café ni thé" },
      { a: "Pouvoir te téléporter", b: "Pouvoir arrêter le temps" },
      { a: "Être toujours en retard", b: "Être toujours trop en avance" },
      { a: "Ne plus jamais faire la vaisselle", b: "Ne plus jamais faire ton lit" },
      { a: "Tout savoir sans rien pouvoir dire", b: "Ne rien savoir mais être heureux" },
      { a: "Vacances illimitées sans argent", b: "Beaucoup d'argent sans vacances" },
      { a: "Bloqué 2h dans un ascenseur", b: "Marcher 2h sous la pluie" },
      { a: "Ne plus jamais avoir mal aux pieds", b: "Ne plus jamais avoir faim" },
      { a: "Vivre dans une grande ville", b: "Vivre à la campagne" },
      { a: "Connaître la date de ta mort", b: "Ne jamais rien savoir" },
      { a: "Un robot qui fait tout", b: "Un clone de toi" },
      { a: "Ne plus jamais te perdre", b: "Ne plus jamais oublier un prénom" },
      { a: "Toujours bien coiffé", b: "Toujours des habits impeccables" },
      { a: "Manger épicé à chaque repas", b: "Manger fade à chaque repas" },
      { a: "Respirer sous l'eau", b: "Voler une minute par jour" },
      { a: "Ne plus jamais faire la queue", b: "Ne plus jamais être en retard" },
      { a: "Un animal qui parle", b: "Une plante magique" },
      { a: "Vivre 200 ans en forme", b: "Vivre 80 ans parfaitement heureux" },
      { a: "Très riche mais ennuyeux", b: "Fauché mais passionnant" },
      { a: "Plus jamais de bouchons", b: "Toujours une place de parking" },
      { a: "Tout réussir sans effort", b: "Galérer mais être fier" },
      { a: "Le dernier téléphone à vie", b: "Des voyages gratuits à vie" },
      { a: "Ne plus jamais transpirer", b: "Ne plus jamais avoir froid" },
      { a: "Ami avec une star", b: "En couple avec quelqu'un de parfait mais lambda" },
      { a: "Manger sans grossir", b: "Dormir sans jamais être fatigué" },
      { a: "Une aventure folle par an", b: "Une vie tranquille et sûre" },
      { a: "Plus jamais de pub", b: "Plus jamais de spam" },
      { a: "Une voiture de rêve", b: "Une maison de rêve" },
      { a: "Toujours de bonne humeur", b: "Toujours en pleine forme" },
      { a: "Manger gratuitement partout", b: "Voyager gratuitement partout" },
      { a: "Avoir un super pouvoir au hasard", b: "Choisir un pouvoir nul mais utile" },
      { a: "Refaire ta journée d'hier", b: "Sauter directement à demain" },
    ],
  hot: [],
  extreme: [],
};

/* ---------- IMPOSTEUR (version unique) ---------- */
const IMP_CATS = {
  "Lieux": ["la plage", "l'aéroport", "l'hôpital", "le supermarché", "la salle de sport", "la piscine", "le cinéma", "le château", "le métro", "la bibliothèque", "le camping", "la boîte de nuit"],
  "Nourriture": ["la pizza", "les sushis", "le burger", "la raclette", "les pâtes", "le kebab", "la crêpe", "le couscous", "la tarte", "les frites", "la soupe", "le croissant"],
  "Films & séries": ["Harry Potter", "Titanic", "Star Wars", "Le Roi Lion", "Friends", "Game of Thrones", "Spider-Man", "La Casa de Papel", "Avatar", "Intouchables", "Squid Game", "Le Seigneur des Anneaux"],
  "Sport": ["le football", "le tennis", "la natation", "le basket", "la boxe", "le ski", "le rugby", "l'escalade", "le golf", "le judo", "le surf", "le cyclisme"],
  "Animaux": ["le pingouin", "le requin", "le kangourou", "le hérisson", "le dauphin", "le caméléon", "la chauve-souris", "le paresseux", "le flamant rose", "le loup", "la pieuvre", "le panda"],
  "Métiers": ["le pompier", "le boulanger", "le pilote", "le dentiste", "le journaliste", "le jardinier", "le coiffeur", "l'astronaute", "le serveur", "le vétérinaire", "le DJ", "le facteur"],
  "Objets": ["le parapluie", "la télécommande", "la bougie", "le tournevis", "l'aspirateur", "le miroir", "la valise", "le réveil", "la guitare", "le casque", "le ballon", "la lampe"],
};

/* ====================== UTILS ====================== */
const shuffle = (a) => { const r = [...a]; for (let i = r.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [r[i], r[j]] = [r[j], r[i]]; } return r; };
const pick = (a) => a[Math.floor(Math.random() * a.length)];

/* ====================== UI ====================== */
function Btn({ children, onClick, color = C.text, bg = C.surface, full, style, disabled }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      fontFamily: BODY, fontWeight: 600, fontSize: 16, color, background: bg, border: "none", borderRadius: 16,
      padding: "16px 20px", cursor: disabled ? "default" : "pointer", width: full ? "100%" : "auto",
      opacity: disabled ? 0.4 : 1, transition: "transform .12s ease", WebkitTapHighlightColor: "transparent", ...style,
    }}
      onPointerDown={(e) => !disabled && (e.currentTarget.style.transform = "scale(.96)")}
      onPointerUp={(e) => (e.currentTarget.style.transform = "scale(1)")}
      onPointerLeave={(e) => (e.currentTarget.style.transform = "scale(1)")}
    >{children}</button>
  );
}
function TopBar({ title, color, onBack, level }) {
  const lv = LEVELS[level];
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 22 }}>
      <button onClick={onBack} aria-label="Retour" style={{ background: C.surface, border: "none", color: C.text, width: 42, height: 42, borderRadius: 13, fontSize: 20, cursor: "pointer", flexShrink: 0, WebkitTapHighlightColor: "transparent" }}>←</button>
      <h2 style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 22, margin: 0, color }}>{title}</h2>
      {lv && lv.badge && <span style={{ fontFamily: BODY, fontWeight: 700, fontSize: 12, color: lv.color, border: `1px solid ${lv.color}`, padding: "3px 8px", borderRadius: 20 }}>{lv.badge}</span>}
    </div>
  );
}
const cardChoice = (color) => ({ display: "flex", flexDirection: "column", alignItems: "center", gap: 8, background: C.surface, border: `1.5px solid ${color}`, borderRadius: 22, padding: "30px 20px", color: C.text, cursor: "pointer", WebkitTapHighlightColor: "transparent" });

/* ====================== ACTION OU VÉRITÉ ====================== */
const AV_EN = {
  soft: {
    verites: [
      "What's the last slightly embarrassing thing you did?",
      "What's the biggest lie you ever told your parents?",
      "Which app do you hide first when someone looks at your phone?",
      "What's your most useless talent?",
      "What's the most expensive thing you bought on impulse?",
      "What nickname do you hate being called?",
      "What's your biggest embarrassment from high school?",
      "What's the last weird thing you searched online?",
      "How long can you really go without your phone?",
      "What's the wildest rumor that ever spread about you?",
      "What's your worst party memory?",
      "What's a weird habit you have when you're alone?",
      "What's the biggest lie you told to impress someone?",
      "What's the most childish thing you still do?",
      "What's your guilty pleasure song?",
      "Have you ever faked being sick, and why?",
      "When's the last time you cried, and why?",
      "What's the cheapest thing you've ever done?",
      "What's your biggest irrational fear?",
      "What compliment has stuck with you the most?",
      "Who's the last person you stalked online?",
      "What's your worst date ever?",
      "What's the craziest thing on your bucket list?",
      "What's the lie you tell most often?",
      "When's the last time you embarrassed yourself in public?",
      "If you could erase one memory, which one?",
      "What flaw do you accept the least?",
      "What's the most impulsive thing you've done?",
      "What's your most embarrassing school memory?",
      "What's the most useless purchase of your month?",
      "What's the worst gift you've ever received?",
      "What's your secret source of pride?",
    ],
    actions: [
      "Imitate your most annoying teacher.",
      "Mime an animal for the group to guess, no talking.",
      "Only speak by singing until your next turn.",
      "Do your most convincing impression of another player.",
      "Tell a joke: if nobody laughs, take a penalty.",
      "Mime waking up on a Monday morning.",
      "Do 10 seconds of your most ridiculous dance.",
      "Pick an accent and keep it until your next turn.",
      "Give a sincere compliment to everyone in the circle.",
      "Imitate a famous influencer for 15 seconds.",
      "Mime a sport without naming it, the group guesses.",
      "Invent an ad slogan for the person on your right.",
      "Pretend to be a weather presenter during a huge storm.",
      "Talk like a robot until your next turn.",
      "Do the sound effects of an action movie for 15 seconds.",
      "Taste a food chosen by the group with your eyes closed and guess it.",
      "Make your best silly face and hold it for 10 seconds.",
      "Copy the walk of someone in the group, others guess who.",
      "Sing Happy Birthday like an opera singer.",
      "Narrate your day as if it were a horror movie.",
      "Pretend to win an award and tearfully thank everyone.",
      "Try to lick your own elbow, yes really try.",
      "Walk backwards across the room narrating yourself like a GPS.",
      "Do a TV commercial for an object in front of you.",
    ],
  },
  hot: { verites: [], actions: [] },
  extreme: { verites: [], actions: [] },
};
const TP_EN = {
  soft: [
      { a: "never use social media again", b: "never watch series or movies again" },
      { a: "be able to fly", b: "be invisible" },
      { a: "always be 10 minutes late", b: "always be 20 minutes early" },
      { a: "have free travel for life", b: "have free food for life" },
      { a: "read minds", b: "see one week into the future" },
      { a: "live without music", b: "live without video" },
      { a: "be a famous actor", b: "be a famous singer" },
      { a: "never feel cold again", b: "never feel too hot again" },
      { a: "only whisper", b: "only shout" },
      { a: "lose all your photos", b: "lose all your messages" },
      { a: "speak every language", b: "play every instrument" },
      { a: "have a rewind button for life", b: "have a pause button for life" },
      { a: "always tell the truth", b: "always have to lie" },
      { a: "live by the sea", b: "live in the mountains" },
      { a: "never wait in line again", b: "never hit traffic again" },
      { a: "have a personal chef", b: "have a personal driver" },
      { a: "be the funniest in the room", b: "be the smartest in the room" },
      { a: "only eat sweet food", b: "only eat salty food" },
      { a: "teleport anywhere", b: "time travel" },
      { a: "have super strength", b: "have super speed" },
      { a: "never have homework or chores", b: "never have to sleep" },
      { a: "win the lottery once", b: "get a smaller bonus every month for life" },
      { a: "be famous", b: "be rich but unknown" },
      { a: "control fire", b: "control water" },
      { a: "always know when someone lies", b: "always get away with your own lies" },
      { a: "have a dog that talks", b: "have a cat that does your taxes" },
      { a: "relive your best day", b: "skip your worst day" },
      { a: "never use a phone again", b: "never use a computer again" },
      { a: "be able to talk to animals", b: "speak every human language" },
      { a: "have unlimited books", b: "have unlimited games" },
      { a: "eat only pizza for a year", b: "eat only sushi for a year" },
      { a: "be the hero of a movie", b: "be the villain of a movie" },
      { a: "always have perfect hair", b: "always have perfect skin" },
      { a: "live in the past", b: "live in the future" },
      { a: "never lose your keys again", b: "never lose your phone again" },
      { a: "be amazing at sports", b: "be amazing at music" },
      { a: "have a year off with pay", b: "retire five years early" },
      { a: "only travel by plane", b: "only travel by boat" },
      { a: "never be bored again", b: "never be tired again" },
      { a: "have a photographic memory", b: "be able to forget on command" },
      { a: "be slightly famous forever", b: "be very famous for one year" },
      { a: "live without coffee", b: "live without dessert" },
      { a: "always know the right thing to say", b: "always know what people are thinking" },
      { a: "be able to breathe underwater", b: "be able to survive in space" },
      { a: "have a personal stylist", b: "have a personal trainer" },
      { a: "win every argument", b: "never argue again" },
      { a: "have free concert tickets for life", b: "have free plane tickets for life" },
      { a: "be able to heal others", b: "be able to heal yourself instantly" },
      { a: "live one big adventure", b: "live a thousand small good days" },
      { a: "always have a clean house", b: "always have a full fridge" },
      { a: "be the best cook among friends", b: "be the best dancer among friends" },
      { a: "know your future", b: "change one thing in your past" },
    ],
  hot: [],
  extreme: [],
};
const JNJ_EN = {
  soft: [
      "skipped school or work to do nothing",
      "lied about my age",
      "fallen asleep in a movie theater",
      "sent a text to the wrong person",
      "forgotten someone's name right after meeting them",
      "binged a whole series in one day",
      "eaten food off the floor",
      "pretended to be sick to avoid plans",
      "sung karaoke completely sober",
      "cried at a cartoon",
      "lost a silly bet",
      "gone a full day without my phone",
      "talked to myself out loud in public",
      "tripped in front of a crowd",
      "laughed at the worst possible moment",
      "stalked someone online for an hour",
      "kept a borrowed book way too long",
      "danced when no one was watching",
      "eaten dessert before dinner",
      "ignored an alarm and overslept",
      "gotten lost in my own city",
      "forgotten my own password",
      "worn the same outfit two days in a row",
      "pretended to understand something I didn't",
      "lied about reading a book",
      "fallen for an obvious prank",
      "made a playlist for someone",
      "reread my own old messages",
      "googled my own name",
      "laughed so hard I snorted",
      "faked a phone call to avoid someone",
      "eaten an entire pizza alone",
      "cried over a song",
      "stayed up all night for no reason",
      "gotten a nickname I hated",
      "embarrassed myself at a party",
      "forgotten a friend's birthday",
      "practiced what to say before a call",
      "won an argument I was actually wrong about",
      "pretended to like a gift",
      "gotten caught talking about someone",
      "failed a viral dance challenge",
      "fallen asleep on public transport",
      "spent too much on something useless",
      "laughed at my own joke before finishing it",
      "worn my clothes inside out all day",
      "lied about my plans just to stay home",
      "gotten a song stuck in my head for days",
      "taken a nap I didn't mean to take",
      "said 'you too' at the wrong time",
      "replied to the wrong group chat",
      "ghosted a conversation out of laziness",
    ],
  hot: [],
  extreme: [],
};
const QP_EN = {
  soft: [
      "fall asleep first at a party",
      "text back the slowest",
      "lose their phone tonight",
      "start a dance floor",
      "cry at a movie",
      "forget a name two seconds after meeting someone",
      "show up late to everything",
      "take the most photos tonight",
      "eat the last slice without asking",
      "tell the same story twice",
      "get lost even with GPS",
      "win a trivia game",
      "laugh at the wrong moment",
      "start a group chat no one asked for",
      "spend all their cash on snacks",
      "fall for an obvious prank",
      "talk their way out of a ticket",
      "become famous one day",
      "adopt ten pets",
      "move abroad on a whim",
      "sing in the shower the loudest",
      "binge a whole series overnight",
      "forget their own birthday",
      "trip on a flat surface",
      "become a millionaire",
      "give the best advice",
      "start an argument over nothing",
      "reply to a text three days later",
      "plan the best trip",
      "get caught daydreaming",
      "always be the designated driver",
      "take the longest to get ready",
      "send a meme at 3am",
      "be the first to say they're hungry",
      "last the longest without their phone",
      "befriend a stranger instantly",
      "overpack for a weekend trip",
      "lose every game tonight",
      "be the mom of the friend group",
      "start a business someday",
      "get emotional over a song",
      "be the last to leave the party",
      "forget where they parked",
      "pick the worst movie to watch",
      "always be down for food",
      "take the best selfies",
      "fall asleep during a meeting",
      "be the funniest in the room",
      "keep a secret the best",
      "get distracted mid-sentence",
      "accidentally like an old photo while scrolling",
      "talk to pets like they understand",
    ],
  hot: [],
  extreme: [],
};
function poolEN(en, fr, level) { const e = en[level]; if (LANG === "en" && e && e.length) return e; return fr[level]; }
function bankAV(level) { const e = AV_EN[level]; if (LANG === "en" && e && e.verites && e.verites.length) return e; return AV[level]; }

function LevelSelector({ level, premium, onChoose }) {
  const modes = [
    { k: "soft", label: t("Soft","Soft"), ic: null, on: C.text, fg: C.bg },
    { k: "hot", label: t("Hot","Hot"), ic: "flame", on: C.hot, fg: "#fff" },
    { k: "extreme", label: t("Extrême","Extreme"), ic: "burst", on: C.extreme, fg: "#fff" },
  ];
  return (
    <div style={{ marginBottom: 16 }}>
      <div style={{ display: "flex", gap: 6, background: C.surface, borderRadius: 14, padding: 5 }}>
        {modes.map((m) => {
          const locked = m.k !== "soft" && !premium;
          const on = level === m.k;
          return (
            <button key={m.k} onClick={() => onChoose(m.k)} style={{ flex: 1, padding: "10px 0", borderRadius: 11, border: "none", cursor: "pointer", fontFamily: BODY, fontWeight: 700, fontSize: 13.5, background: on ? m.on : "transparent", color: on ? m.fg : C.muted, WebkitTapHighlightColor: "transparent", display: "flex", alignItems: "center", justifyContent: "center", gap: 5 }}>
              {m.ic && <Ic name={m.ic} size={15} color={on ? m.fg : C.muted} />}<span>{m.label}</span>{locked && <Ic name="lock" size={13} color={on ? m.fg : C.muted} />}
            </button>
          );
        })}
      </div>
      {level !== "soft" && <p style={{ fontFamily: BODY, color: level === "extreme" ? C.extreme : C.hot, fontSize: 12, margin: "8px 2px 0" }}>{t("Réservé aux adultes (18+). Contenu flirt, drague et sexe, entre adultes consentants.","Adults only (18+). Flirty and sexual content, between consenting adults.")}</p>}
    </div>
  );
}

function ActionVerite({ players, level, premium, onChooseLevel, onBack }) {
  const bank = bankAV(level);
  const [queues, setQueues] = useState(() => ({ verites: shuffle(bank.verites), actions: shuffle(bank.actions) }));
  const [turn, setTurn] = useState(0);
  const [mode, setMode] = useState(null);
  const [prompt, setPrompt] = useState(null);
  const hasP = players.length > 0;
  const current = hasP ? players[turn % players.length] : null;
  useEffect(() => { setQueues({ verites: shuffle(bank.verites), actions: shuffle(bank.actions) }); setMode(null); setPrompt(null); }, [level]);
  const choose = (m) => {
    const key = m === "action" ? "actions" : "verites";
    const arr = queues[key].length ? queues[key] : shuffle(bank[key]);
    const picked = arr[0];
    let rest = arr.slice(1);
    if (rest.length === 0) rest = shuffle(bank[key]); // tour complet fait : on remélange
    setMode(m); setPrompt(picked);
    setQueues((q) => ({ ...q, [key]: rest }));
  };
  const next = () => { setMode(null); setPrompt(null); if (hasP) setTurn((t) => t + 1); };
  return (
    <div>
      <TopBar title={t("Action ou Vérité","Truth or Dare")} color={C.pink} onBack={onBack} level={level} />
      <LevelSelector level={level} premium={premium} onChoose={onChooseLevel} />
      {hasP && <p style={{ fontFamily: BODY, color: C.muted, margin: "0 0 16px", fontSize: 15 }}>{t("Au tour de","Turn:")} <span style={{ color: C.text, fontWeight: 700 }}>{current}</span></p>}
      {!prompt ? (
        <div style={{ display: "grid", gap: 14 }}>
          <button onClick={() => choose("action")} style={cardChoice(C.pink)}><Ic name="bolt" size={32} color={C.pink} sw={1.7} /><span style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 22 }}>{t("ACTION","DARE")}</span></button>
          <button onClick={() => choose("verite")} style={cardChoice("#7C5CFF")}><Ic name="chat" size={32} color="#9A5BFF" sw={1.7} /><span style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 22 }}>{t("VÉRITÉ","TRUTH")}</span></button>
        </div>
      ) : (
        <div style={{ background: mode === "action" ? "linear-gradient(160deg,#FF4D79,#B81E50)" : "linear-gradient(160deg,#7C5CFF,#4327A8)", borderRadius: 24, padding: "40px 26px", minHeight: 220, display: "flex", flexDirection: "column", justifyContent: "center" }}>
          <span style={{ fontFamily: DISPLAY, fontWeight: 700, fontSize: 13, letterSpacing: 2, opacity: 0.8 }}>{mode === "action" ? t("ACTION","DARE") : t("VÉRITÉ","TRUTH")}</span>
          <p style={{ fontFamily: BODY, fontWeight: 600, fontSize: 24, lineHeight: 1.25, margin: "14px 0 0", color: "#fff" }}>{prompt}</p>
        </div>
      )}
      {prompt && <div style={{ marginTop: 18, display: "grid", gap: 10 }}><Btn full bg={C.pink} color="#1a0a10" onClick={next}>{t("Tour suivant →","Next turn →")}</Btn><Btn full bg={C.surface} color={C.muted} onClick={() => choose(mode)}>{t("Une autre","Another one")}</Btn></div>}
    </div>
  );
}

/* ====================== TU PRÉFÈRES ====================== */
function TuPrefere({ level, premium, onChooseLevel, onBack }) {
  const [order, setOrder] = useState(() => shuffle(poolEN(TP_EN, TP, level)));
  const [i, setI] = useState(0);
  const [chosen, setChosen] = useState(null);
  useEffect(() => { setOrder(shuffle(poolEN(TP_EN, TP, level))); setI(0); setChosen(null); }, [level]);
  const q = order[i];
  const next = () => { setChosen(null); setI((x) => (x + 1) % order.length); };
  const Card = (side, grad) => (
    <button onClick={() => setChosen(side)} style={{
      width: "100%", borderRadius: 20, border: chosen === side ? "2px solid #fff" : "2px solid transparent", cursor: "pointer",
      background: grad, padding: "26px 22px", textAlign: "left", color: "#fff", WebkitTapHighlightColor: "transparent",
      opacity: chosen && chosen !== side ? 0.5 : 1, transition: "opacity .2s ease",
    }}>
      <div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 13, opacity: 0.85, marginBottom: 6 }}>{side === "a" ? t("OPTION A","OPTION A") : t("OPTION B","OPTION B")}</div>
      <div style={{ fontFamily: BODY, fontWeight: 600, fontSize: 21, lineHeight: 1.2 }}>{q[side]}</div>
    </button>
  );
  return (
    <div>
      <TopBar title={t("Tu préfères","Would You Rather")} color={C.amber} onBack={onBack} level={level} />
      <LevelSelector level={level} premium={premium} onChoose={onChooseLevel} />
      <p style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 18, color: C.text, margin: "0 0 14px" }}>{t("Tu préfères...","Would you rather...")}</p>
      <div style={{ display: "grid", gap: 12 }}>
        {Card("a", "linear-gradient(160deg,#FF9F1C,#C9690A)")}
        <div style={{ textAlign: "center", fontFamily: DISPLAY, fontWeight: 800, color: C.muted, fontSize: 14 }}>{t("OU","OR")}</div>
        {Card("b", "linear-gradient(160deg,#9B5DE5,#5B2A9E)")}
      </div>
      <p style={{ textAlign: "center", fontFamily: BODY, color: C.muted, fontSize: 13, margin: "16px 0 14px" }}>{t("Chacun défend son choix","Everyone defends their pick")} · {i + 1}/{order.length}</p>
      <Btn full bg={C.amber} color="#2a1600" onClick={next}>{t("Question suivante →","Next question →")}</Btn>
    </div>
  );
}

/* ====================== JE N'AI JAMAIS ====================== */
function JeNaiJamais({ level, premium, onChooseLevel, onBack }) {
  const pool = poolEN(JNJ_EN, JNJ_POOLS, level);
  const [order, setOrder] = useState(() => shuffle(pool));
  const [i, setI] = useState(0);
  useEffect(() => { setOrder(shuffle(pool)); setI(0); }, [level]);
  const next = () => setI((x) => (x + 1) % order.length);
  const prev = () => setI((x) => (x - 1 + order.length) % order.length);
  const reshuffle = () => { setOrder(shuffle(pool)); setI(0); };
  return (
    <div>
      <TopBar title={t("Je n'ai jamais","Never Have I Ever")} color={C.cyan} onBack={onBack} level={level} />
      <LevelSelector level={level} premium={premium} onChoose={onChooseLevel} />
      <div style={{ background: "linear-gradient(160deg,#37C3FF,#1763A8)", borderRadius: 24, padding: "40px 26px", minHeight: 230, display: "flex", flexDirection: "column", justifyContent: "center" }}>
        <span style={{ fontFamily: DISPLAY, fontWeight: 700, fontSize: 13, letterSpacing: 2, color: "#fff", opacity: 0.85 }}>{t("JE N'AI JAMAIS...","I HAVE NEVER...")}</span>
        <p style={{ fontFamily: BODY, fontWeight: 600, fontSize: 26, lineHeight: 1.25, margin: "14px 0 0", color: "#fff" }}>{order[i]}</p>
      </div>
      <p style={{ textAlign: "center", fontFamily: BODY, color: C.muted, fontSize: 14, margin: "14px 0 18px" }}>{t("Si tu l'as déjà fait, tu prends une pénalité","If you have, take a penalty")} · {i + 1}/{order.length}</p>
      <div style={{ display: "grid", gap: 10 }}>
        <Btn full bg={C.cyan} color="#04243a" onClick={next}>{t("Suivant →","Next →")}</Btn>
        <div style={{ display: "flex", gap: 10 }}><Btn bg={C.surface} color={C.muted} onClick={prev} style={{ flex: 1 }}>{t("← Précédent","← Previous")}</Btn><Btn bg={C.surface} color={C.muted} onClick={reshuffle} style={{ flex: 1 }}>{t("🔀 Mélanger","🔀 Shuffle")}</Btn></div>
      </div>
    </div>
  );
}

/* ---------- QUI POURRAIT ---------- */
const QP_HOT = [];
const QP_EXTREME = [];
const QP_POOLS = {
  soft: [
    "prendre une douche à 4h du matin sans raison.",
    "oublier son propre anniversaire.",
    "manger une pizza entière tout seul.",
    "se perdre dans sa propre ville.",
    "tomber amoureux en vacances.",
    "envoyer un message à son ex à 3h du matin.",
    "devenir célèbre sur les réseaux.",
    "pleurer devant une publicité.",
    "oublier où il a garé la voiture.",
    "danser sur une table en soirée.",
    "parler à un inconnu dans la rue.",
    "abandonner après cinq minutes de sport.",
    "finir la soirée en kebab.",
    "dormir pendant un concert.",
    "perdre son téléphone ce soir.",
    "se mettre à chanter sans prévenir.",
    "rater son réveil demain matin.",
    "raconter sa vie à un chauffeur de taxi.",
    "adopter dix chats.",
    "se disputer pour le choix d'une série.",
    "oublier de répondre pendant trois jours.",
    "rougir pour un rien.",
    "prendre le micro au karaoké en premier.",
    "casser quelque chose ce soir.",
    "commander le plat le plus bizarre du menu.",
    "se faire avoir par une arnaque.",
    "tomber en marchant tout droit.",
    "rester scotché à son téléphone toute la soirée.",
    "organiser un voyage sur un coup de tête.",
    "rire au pire moment.",
    "oublier un prénom juste après l'avoir entendu.",
    "faire la sieste n'importe où.",
    "se vexer pour une blague.",
    "finir par payer pour tout le groupe.",
    "se relever la nuit pour manger.",
    "raconter trois fois la même histoire.",
    "pleurer de rire sans pouvoir s'arrêter.",
    "perdre un pari ridicule.",
    "se mettre en retard pour un selfie.",
    "croire à un poisson d'avril énorme.",
    "tout oublier après deux verres.",
    "draguer le distributeur de billets.",
    "chanter sous la douche à plein volume.",
    "se filmer en train de danser seul.",
    "oublier ses clés à l'intérieur.",
    "parler tout seul dans la rue.",
    "manger le dernier morceau sans demander.",
    "s'endormir devant un film d'action.",
    "envoyer un vocal interminable.",
    "refaire toute la déco un dimanche soir.",
    "se perdre dans un supermarché.",
    "rire à sa propre blague avant de la finir.",
  ],
  hot: QP_HOT,
  extreme: QP_EXTREME,
};

function QuiPourrait({ level, premium, onChooseLevel, onBack }) {
  const pool = poolEN(QP_EN, QP_POOLS, level);
  const [order, setOrder] = useState(() => shuffle(pool));
  const [i, setI] = useState(0);
  useEffect(() => { setOrder(shuffle(pool)); setI(0); }, [level]);
  const next = () => setI((x) => (x + 1) % order.length);
  const prev = () => setI((x) => (x - 1 + order.length) % order.length);
  const reshuffle = () => { setOrder(shuffle(pool)); setI(0); };
  return (
    <div>
      <TopBar title={t("Qui pourrait","Who's Most Likely To")} color="#FF6B4A" onBack={onBack} level={level} />
      <LevelSelector level={level} premium={premium} onChoose={onChooseLevel} />
      <div style={{ background: "linear-gradient(160deg,#FF6B4A,#B3360F)", borderRadius: 24, padding: "40px 26px", minHeight: 230, display: "flex", flexDirection: "column", justifyContent: "center" }}>
        <span style={{ fontFamily: DISPLAY, fontWeight: 700, fontSize: 13, letterSpacing: 2, color: "#fff", opacity: 0.85 }}>{t("QUI POURRAIT...","WHO'S MOST LIKELY TO...")}</span>
        <p style={{ fontFamily: BODY, fontWeight: 600, fontSize: 26, lineHeight: 1.25, margin: "14px 0 0", color: "#fff" }}>{order[i]}</p>
      </div>
      <p style={{ textAlign: "center", fontFamily: BODY, color: C.muted, fontSize: 14, margin: "14px 0 18px" }}>{t("À 3, tout le monde pointe du doigt. La personne la plus désignée prend une pénalité","On 3, everyone points. The most pointed-at takes a penalty")} · {i + 1}/{order.length}</p>
      <div style={{ display: "grid", gap: 10 }}>
        <Btn full bg="#FF6B4A" color="#2a0d04" onClick={next}>{t("Suivant →","Next →")}</Btn>
        <div style={{ display: "flex", gap: 10 }}><Btn bg={C.surface} color={C.muted} onClick={prev} style={{ flex: 1 }}>{t("← Précédent","← Previous")}</Btn><Btn bg={C.surface} color={C.muted} onClick={reshuffle} style={{ flex: 1 }}>{t("🔀 Mélanger","🔀 Shuffle")}</Btn></div>
      </div>
    </div>
  );
}

/* ====================== PMU (version unique) ====================== */
const SUITS = [
  { k: "h", sym: "♥", name: "Cœur de Pirate", color: "#FF5C7A" },
  { k: "d", sym: "♦", name: "Carreau Express", color: "#FFC247" },
  { k: "c", sym: "♣", name: "Trèfle Chanceux", color: "#4FD1A5" },
  { k: "s", sym: "♠", name: "Pique Sauvage", color: "#6AA8FF" },
];
const L = 7;
function buildDeck() { let c = []; SUITS.forEach((s) => { for (let i = 0; i < 12; i++) c.push(s.k); }); return shuffle(c); }
function PMU({ players, onBack }) {
  const [phase, setPhase] = useState("bet");
  const [bets, setBets] = useState({}); // name -> { suit, mise }
  const [race, setRace] = useState(null);
  const [auto, setAuto] = useState(false);
  const autoRef = useRef(null);
  const stepBtn = { width: 30, height: 30, borderRadius: 9, border: "none", background: C.bg2, color: C.text, fontSize: 18, cursor: "pointer", WebkitTapHighlightColor: "transparent" };
  const TOLL_AT = 4; // péage à la case 4

  const finalize = (r) => ({ ...r, done: true, cross: [], recule: null, order: [...r.finishOrder, ...SUITS.map((s) => s.k).filter((k) => !r.finishOrder.includes(k)).sort((a, b) => r.pos[b] - r.pos[a])] });
  const startRace = () => { const tf = (k) => pick(["h", "d", "c", "s"].filter((x) => x !== k)); setRace({ pos: { h: 0, d: 0, c: 0, s: 0 }, deck: buildDeck(), finishOrder: [], toll: { h: tf("h"), d: tf("d"), c: tf("c"), s: tf("s") }, last: null, cross: [], recule: null, done: false, order: null }); setAuto(false); setPhase("race"); };

  const flip = () => {
    setRace((r) => {
      if (!r || r.done) return r;
      const deck = r.deck.length ? r.deck : buildDeck();
      const card = deck[0]; // couleur piochée
      const pos = { ...r.pos };
      const cross = [];
      // tout cheval posté au péage dont la couleur de péage = la couleur piochée franchit
      SUITS.forEach((s) => { if (pos[s.k] === TOLL_AT && r.toll[s.k] === card) { pos[s.k] = Math.min(L, TOLL_AT + 1); cross.push(s.k); } });
      // le cheval de la couleur piochée : bloqué au péage -> recule ; sinon il avance
      let recule = null;
      if (pos[card] === TOLL_AT) { pos[card] = Math.max(0, TOLL_AT - 1); recule = card; }
      else pos[card] = Math.min(L, pos[card] + 1);
      const finishOrder = [...r.finishOrder];
      SUITS.forEach((s) => { if (pos[s.k] >= L && !finishOrder.includes(s.k)) finishOrder.push(s.k); });
      let nr = { ...r, pos, deck: deck.slice(1), finishOrder, last: card, cross, recule };
      if (finishOrder.length >= 3) nr = finalize(nr);
      return nr;
    });
  };
  useEffect(() => { if (auto && phase === "race" && race && !race.done) autoRef.current = setTimeout(flip, 2000); return () => clearTimeout(autoRef.current); }, [auto, phase, race]);

  const setSuit = (name, suit) => setBets((b) => ({ ...b, [name]: { suit, mise: (b[name] && b[name].mise) || 2 } }));
  const setMise = (name, delta) => setBets((b) => { const cur = b[name] || { suit: null, mise: 2 }; const mise = Math.max(1, Math.min(10, cur.mise + delta)); return { ...b, [name]: { ...cur, mise } }; });

  if (phase === "bet") {
    return (
      <div>
        <TopBar title={t("PMU","Horse Race")} color={C.green} onBack={onBack} level="soft" />
        <p style={{ fontFamily: BODY, color: C.muted, margin: "0 0 16px", fontSize: 14.5, lineHeight: 1.5 }}>{t("Chaque joueur mise des pénalités sur un cheval, puis valide sa mise. À la case 4, chaque cheval a une couleur de péage tirée au hasard (différente de la sienne). Quand une couleur est piochée, son cheval avance et tout cheval bloqué au péage dont le péage est cette couleur le franchit. Un cheval bloqué au péage qui pioche sa propre couleur recule d'une case, et ses parieurs prennent 1 pénalité. La course va jusqu'à l'arrivée des 3 premiers. 1er : distribue le double, 2e : distribue sa mise, 3e : prend sa mise, 4e : prend le double.","Each player bets penalties on a horse, then confirms their bet. At space 4, each horse gets a random toll color (different from its own). When a color is drawn, its horse moves forward and any horse stuck at the toll whose toll is that color clears it. A horse stuck at the toll that draws its own color moves back one space, and its bettors take 1 penalty. The race runs until the first 3 finish. 1st: hands out double, 2nd: hands out their bet, 3rd: takes their bet, 4th: takes double.")}</p>
        {players.length === 0 ? (
          <div style={{ background: C.surface, borderRadius: 18, padding: 20, marginBottom: 16 }}><p style={{ fontFamily: BODY, color: C.muted, margin: 0, fontSize: 14 }}>{t("Aucun joueur ajouté. Partie rapide : chacun choisit son cheval et sa mise à voix haute.","No players added. Quick game: everyone picks their horse and bet out loud.")}</p></div>
        ) : (
          <div style={{ display: "grid", gap: 12, marginBottom: 18 }}>
            {players.map((p) => {
              const b = bets[p] || { suit: null, mise: 2 };
              return (
                <div key={p} style={{ background: C.surface, borderRadius: 16, padding: "12px 14px" }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
                    <span style={{ fontFamily: BODY, fontWeight: 700, color: C.text }}>{p}</span>
                    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                      <span style={{ fontFamily: BODY, fontSize: 12, color: C.muted }}>{t("Mise","Bet")}</span>
                      <button onClick={() => setMise(p, -1)} style={stepBtn}>−</button>
                      <span style={{ fontFamily: DISPLAY, fontWeight: 800, color: C.green, minWidth: 20, textAlign: "center" }}>{b.mise}</span>
                      <button onClick={() => setMise(p, 1)} style={stepBtn}>+</button>
                    </div>
                  </div>
                  <div style={{ display: "flex", gap: 8 }}>{SUITS.map((s) => (<button key={s.k} onClick={() => setSuit(p, s.k)} style={{ flex: 1, padding: "10px 0", borderRadius: 11, cursor: "pointer", border: b.suit === s.k ? `2px solid ${s.color}` : "2px solid transparent", background: b.suit === s.k ? s.color + "22" : C.bg2, color: s.color, fontSize: 22, WebkitTapHighlightColor: "transparent" }}>{s.sym}</button>))}</div>
                </div>
              );
            })}
            <div style={{ fontFamily: BODY, fontSize: 13, color: C.green, textAlign: "center" }}>{t("🎯 Chacun valide sa mise en pénalités maintenant","🎯 Everyone confirms their penalty bet now")}</div>
          </div>
        )}
        <Btn full bg={C.green} color="#062012" onClick={startRace}>{players.length ? t("Lancer la course","Start the race") : t("Partie rapide","Quick game")} 🏁</Btn>
      </div>
    );
  }

  const r = race;
  const winner = r.order ? r.order[0] : null;
  return (
    <div>
      <TopBar title={t("PMU","Horse Race")} color={C.green} onBack={onBack} level="soft" />
      <div style={{ background: C.surface, borderRadius: 20, padding: "16px 14px", marginBottom: 16 }}>
        {SUITS.map((s) => {
          const finishRank = r.finishOrder.indexOf(s.k);
          return (
            <div key={s.k} style={{ marginBottom: 14 }}>
              <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 4 }}>
                <span style={{ fontFamily: BODY, fontSize: 12, color: s.color, fontWeight: 700 }}>{s.sym} {s.name}</span>
                {finishRank >= 0 && <span style={{ fontFamily: BODY, fontSize: 11, color: C.green, fontWeight: 700 }}>{["1er", "2e", "3e"][finishRank]} 🏁</span>}
              </div>
              <div style={{ position: "relative", height: 34, background: C.bg2, borderRadius: 8 }}>
                <div style={{ position: "absolute", left: `${(TOLL_AT / L) * 100}%`, top: 0, bottom: 0, width: 3, background: "#FFC247", opacity: 0.7, transform: "translateX(-1px)" }} title={t("Péage","Toll")} />
                <div style={{ position: "absolute", left: `${(TOLL_AT / L) * 100}%`, top: -3, transform: "translateX(-50%)", fontSize: 12, fontWeight: 800, color: SUITS.find((x) => x.k === r.toll[s.k]).color }}>{SUITS.find((x) => x.k === r.toll[s.k]).sym}</div>
                <div style={{ position: "absolute", right: 4, top: 0, bottom: 0, width: 2, background: "repeating-linear-gradient(45deg,#fff,#fff 3px,transparent 3px,transparent 6px)", opacity: 0.4 }} />
                <div style={{ position: "absolute", top: 2, left: `${(r.pos[s.k] / L) * 100}%`, transform: "translateX(-50%)", transition: "left .4s cubic-bezier(.34,1.4,.5,1)", filter: winner === s.k ? "drop-shadow(0 0 7px " + s.color + ")" : "none" }}><RivCard faceUp card={{ l: "A", s: s.sym, c: (s.k === "h" || s.k === "d") ? "red" : "black" }} w={24} h={32} /></div>
              </div>
            </div>
          );
        })}
        <div style={{ fontFamily: BODY, fontSize: 11, color: C.muted, textAlign: "center", marginTop: 4 }}>⛽ Péage case {TOLL_AT} · chaque cheval doit tirer la couleur affichée au-dessus de sa ligne</div>
      </div>
      {r.last && !r.done && (
        <div style={{ textAlign: "center", marginBottom: 12 }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 10, marginBottom: 8 }}><span style={{ fontFamily: BODY, color: C.muted }}>{t("Carte tirée :","Card drawn:")}</span><RivCard faceUp card={{ l: "", s: SUITS.find((x) => x.k === r.last).sym, c: (r.last === "h" || r.last === "d") ? "red" : "black" }} w={40} h={56} /></div>
          {r.cross && r.cross.length > 0 && (
            <div style={{ background: "#16402E", borderRadius: 14, padding: "10px 14px", marginBottom: r.recule ? 8 : 0 }}>
              <div style={{ fontFamily: DISPLAY, fontWeight: 800, color: C.green, fontSize: 14 }}>{t("⛽ Péage franchi !","⛽ Toll cleared!")}</div>
              <div style={{ fontFamily: BODY, color: C.text, fontSize: 14, marginTop: 2 }}>{r.cross.map((k) => SUITS.find((s) => s.k === k).sym).join(" ")} {r.cross.length > 1 ? "passent" : "passe"} le péage grâce au {SUITS.find((x) => x.k === r.last).sym}.</div>
            </div>
          )}
          {r.recule && (
            <div style={{ background: "#3A2A52", borderRadius: 14, padding: "10px 14px" }}>
              <div style={{ fontFamily: DISPLAY, fontWeight: 800, color: "#FFC247", fontSize: 14 }}>{t("⛔ Bloqué au péage","⛔ Stuck at the toll")}</div>
              <div style={{ fontFamily: BODY, color: C.text, fontSize: 14, marginTop: 2 }}>{SUITS.find((x) => x.k === r.recule).sym} {t("recule (il lui faut","backs up (needs")} {SUITS.find((x) => x.k === r.toll[r.recule]).sym}). {(() => { const bt = players.filter((p) => bets[p] && bets[p].suit === r.recule); return bt.length ? bt.join(", ") + " " + (bt.length > 1 ? t("prennent","take") : t("prend","takes")) + t(" 1 pénalité."," 1 penalty.") : t("Les parieurs de ","Bettors of ") + SUITS.find((x) => x.k === r.recule).sym + t(" prennent 1 pénalité."," take 1 penalty."); })()}</div>
            </div>
          )}
        </div>
      )}
      {r.done ? (
        <div>
          <div style={{ background: "linear-gradient(160deg,#2FD673,#157a42)", borderRadius: 20, padding: "22px 20px", textAlign: "center", marginBottom: 16 }}><div style={{ fontSize: 40 }}>🏆</div><div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 22, color: "#fff", marginTop: 4 }}>{SUITS.find((x) => x.k === winner).sym} {SUITS.find((x) => x.k === winner).name} gagne !</div></div>
          <ResultPMU players={players} bets={bets} order={r.order} />
          <Btn full bg={C.green} color="#062012" onClick={startRace} style={{ marginTop: 14 }}>{t("Rejouer 🔁","Play again 🔁")}</Btn>
        </div>
      ) : (
        <div style={{ display: "grid", gap: 10 }}><Btn full bg={C.green} color="#062012" onClick={flip} disabled={auto}>{t("Carte suivante","Next card")}</Btn><Btn full bg={C.surface} color={auto ? C.green : C.muted} onClick={() => setAuto((a) => !a)}>{auto ? t("⏸ Pause auto","⏸ Auto-pause") : t("▶ Lecture auto","▶ Auto-play")}</Btn></div>
      )}
    </div>
  );
}
function ResultPMU({ players, bets, order }) {
  const place = ["1er", "2e", "3e", "4e"];
  if (players.length === 0) {
    const w = SUITS.find((x) => x.k === order[0]);
    return <div style={{ background: C.surface, borderRadius: 16, padding: 16, fontFamily: BODY, color: C.text, fontSize: 14.5, lineHeight: 1.5 }}>Classement : {order.map((k, i) => place[i] + " " + SUITS.find((s) => s.k === k).sym).join(" · ")}. Le 1er distribue le double de sa mise, le 2e distribue sa mise, le 3e prend sa mise, le dernier prend le double.</div>;
  }
  const lines = players.filter((p) => bets[p] && bets[p].suit).map((p) => {
    const b = bets[p]; const rk = order.indexOf(b.suit); const su = SUITS.find((s) => s.k === b.suit);
    const n = rk === 0 ? 2 * b.mise : rk === 1 ? b.mise : rk === 2 ? b.mise : 2 * b.mise;
    const give = rk <= 1;
    return { p, su, rk, n, give };
  }).sort((a, b) => a.rk - b.rk);
  const noBet = players.filter((p) => !bets[p] || !bets[p].suit);
  return (
    <div style={{ background: C.surface, borderRadius: 16, padding: 16, display: "grid", gap: 9 }}>
      {lines.map(({ p, su, rk, n, give }) => (
        <div key={p} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", fontFamily: BODY, fontSize: 15 }}>
          <span style={{ color: C.text }}>{p} <span style={{ color: su.color }}>{su.sym}</span> <span style={{ color: C.muted, fontSize: 12 }}>{place[rk]}</span></span>
          <span style={{ color: give ? C.green : C.pink, fontWeight: 700 }}>{give ? "🎁 Distribue " : "🎯 Prends "}{n} pénalité{n > 1 ? "s" : ""}</span>
        </div>
      ))}
      {noBet.length > 0 && <div style={{ fontFamily: BODY, color: C.muted, fontSize: 13 }}>Sans pari : {noBet.join(", ")}</div>}
    </div>
  );
}

/* ====================== IMPOSTEUR (version unique) ====================== */
function Imposteur({ players, onBack, openPlayers }) {
  const cats = IMP_CATS;
  const [phase, setPhase] = useState("setup"); // setup | reveal | round | vote | elim
  const [nbImp, setNbImp] = useState(1);
  const [roles, setRoles] = useState([]); // { name, isImp, word, alive }
  const [cat, setCat] = useState("Aléatoire");
  const [step, setStep] = useState(0);
  const [shown, setShown] = useState(false);
  const [secret, setSecret] = useState({ cat: "", word: "", decoy: "" });
  const [order, setOrder] = useState([]);
  const [speaker, setSpeaker] = useState(0);
  const [votes, setVotes] = useState({});
  const [secondsLeft, setSecondsLeft] = useState(120);
  const [elim, setElim] = useState(null); // { name, isImp } | { tie:true }
  const [winner, setWinner] = useState(null); // 'civils' | 'imposteurs' | null
  const [manche, setManche] = useState(1);

  const alive = roles.filter((r) => r.alive);

  const deal = () => {
    const ck = cat === "Aléatoire" ? pick(Object.keys(cats)) : cat;
    const words = cats[ck];
    const word = pick(words);
    const decoy = pick(words.filter((w) => w !== word));
    setSecret({ cat: ck, word, decoy });
    const idx = shuffle(players.map((_, i) => i)).slice(0, nbImp);
    setRoles(players.map((name, i) => ({ name, isImp: idx.includes(i), word: idx.includes(i) ? decoy : word, alive: true })));
    setOrder(shuffle(players)); setStep(0); setShown(false); setElim(null); setWinner(null); setManche(1); setPhase("reveal");
  };
  const startRound = (rs) => { const list = (rs || roles).filter((r) => r.alive).map((r) => r.name); setOrder(shuffle(list)); setSpeaker(0); setElim(null); setPhase("round"); };
  const startVote = () => { setVotes({}); setSecondsLeft(120); setPhase("vote"); };

  useEffect(() => {
    if (phase !== "vote") return;
    if (secondsLeft <= 0) { tally(); return; }
    const t = setTimeout(() => setSecondsLeft((s) => s - 1), 1000);
    return () => clearTimeout(t);
  }, [phase, secondsLeft]);

  const tally = () => {
    const entries = alive.map((r) => [r.name, votes[r.name] || 0]);
    const max = Math.max(0, ...entries.map((e) => e[1]));
    const top = entries.filter((e) => e[1] === max && max > 0).map((e) => e[0]);
    if (top.length !== 1) { setElim({ tie: true }); setPhase("elim"); return; }
    const name = top[0];
    const r = roles.find((x) => x.name === name);
    const newRoles = roles.map((x) => (x.name === name ? { ...x, alive: false } : x));
    const al = newRoles.filter((x) => x.alive);
    const imp = al.filter((x) => x.isImp).length;
    const civ = al.length - imp;
    let win = null;
    if (imp === 0) win = "civils";
    else if (civ <= imp) win = "imposteurs";
    setRoles(newRoles); setElim({ name, isImp: r.isImp }); setWinner(win); setPhase("elim");
  };

  const fmt = (s) => Math.floor(s / 60) + ":" + String(s % 60).padStart(2, "0");

  if (phase === "setup") {
    const enough = players.length >= 3;
    return (
      <div>
        <TopBar title={t("Imposteur","Impostor")} color={C.purple} onBack={onBack} level="soft" />
        <p style={{ fontFamily: BODY, color: C.muted, margin: "0 0 18px", fontSize: 14.5, lineHeight: 1.5 }}>{t("Chacun reçoit un mot ; l'imposteur en a un voisin du même thème (ex. arbre / fleur). À chaque manche, tout le monde donne un mot lié au sien, puis on vote. L'éliminé est révélé. Les imposteurs gagnent dès que les civils sont en nombre égal ou inférieur aux imposteurs.","Everyone gets a word; the impostor gets a neighboring word from the same theme (e.g. tree / flower). Each round, everyone says a word linked to theirs, then you vote. The eliminated player is revealed. The impostors win as soon as the civilians are equal to or fewer than the impostors.")}</p>
        {!enough ? (
          <div style={{ background: C.surface, borderRadius: 18, padding: 20 }}><p style={{ fontFamily: BODY, color: C.text, margin: "0 0 14px", fontSize: 15 }}>{t("Il faut au moins","You need at least")} <b>{t("3 joueurs","3 players")}</b> ({players.length} {t("pour l'instant).","so far).")}</p><Btn full bg={C.purple} color="#150826" onClick={openPlayers}>{t("Ajouter des joueurs","Add players")}</Btn></div>
        ) : (
          <>
            <div style={{ background: C.surface, borderRadius: 16, padding: 16, marginBottom: 14 }}>
              <div style={{ fontFamily: BODY, fontWeight: 700, color: C.text, marginBottom: 10, fontSize: 14 }}>{t("Catégorie","Category")}</div>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>{["Aléatoire", ...Object.keys(cats)].map((k) => (<button key={k} onClick={() => setCat(k)} style={{ fontFamily: BODY, fontSize: 13, padding: "8px 12px", borderRadius: 20, cursor: "pointer", border: cat === k ? `1.5px solid ${C.purple}` : "1.5px solid transparent", background: cat === k ? C.purple + "26" : C.bg2, color: cat === k ? C.purple : C.muted, WebkitTapHighlightColor: "transparent" }}>{k}</button>))}</div>
            </div>
            <div style={{ background: C.surface, borderRadius: 16, padding: 16, marginBottom: 18, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
              <span style={{ fontFamily: BODY, fontWeight: 700, color: C.text, fontSize: 14 }}>{t("Nombre d'imposteurs","Number of impostors")}</span>
              <div style={{ display: "flex", gap: 8 }}>{[1, 2].map((n) => (<button key={n} disabled={n === 2 && players.length < 6} onClick={() => setNbImp(n)} style={{ width: 40, height: 40, borderRadius: 12, cursor: n === 2 && players.length < 6 ? "default" : "pointer", border: nbImp === n ? `1.5px solid ${C.purple}` : "1.5px solid transparent", background: nbImp === n ? C.purple + "26" : C.bg2, color: nbImp === n ? C.purple : C.muted, fontFamily: BODY, fontWeight: 700, opacity: n === 2 && players.length < 6 ? 0.35 : 1 }}>{n}</button>))}</div>
            </div>
            <Btn full bg={C.purple} color="#150826" onClick={deal}>{t("Distribuer les mots 🎭","Deal the words 🎭")}</Btn>
          </>
        )}
      </div>
    );
  }

  if (phase === "reveal") {
    const rl = roles[step]; const isLast = step === roles.length - 1;
    return (
      <div>
        <TopBar title={t("Imposteur","Impostor")} color={C.purple} onBack={onBack} level="soft" />
        <p style={{ fontFamily: BODY, color: C.muted, margin: "0 0 18px", fontSize: 15 }}>{t("Passe le téléphone à","Pass the phone to")} <span style={{ color: C.text, fontWeight: 700 }}>{rl.name}</span></p>
        <button onClick={() => setShown((s) => !s)} style={{ width: "100%", minHeight: 260, borderRadius: 24, border: "none", cursor: "pointer", background: shown ? "linear-gradient(160deg,#A06BFF,#5026a0)" : C.surface, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 10, WebkitTapHighlightColor: "transparent", padding: 24 }}>
          {!shown ? (<><span style={{ fontSize: 44 }}>👆</span><span style={{ fontFamily: BODY, fontWeight: 600, color: C.muted }}>{t("Touche pour voir ton mot","Tap to see your word")}</span></>) : (<><span style={{ fontFamily: BODY, fontSize: 13, color: "#fff", opacity: 0.8, letterSpacing: 1 }}>{secret.cat.toUpperCase()}</span><span style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 30, color: "#fff" }}>{rl.word}</span><span style={{ fontFamily: BODY, fontSize: 12.5, color: "#fff", opacity: 0.7, textAlign: "center" }}>{t("Mémorise-le. Un joueur a un mot différent.","Memorize it. One player has a different word.")}</span></>)}
        </button>
        {shown && <Btn full bg={C.purple} color="#150826" style={{ marginTop: 16 }} onClick={() => { if (isLast) startRound(); else { setStep((s) => s + 1); setShown(false); } }}>{isLast ? t("Tout le monde a vu →","Everyone has seen →") : t("J'ai vu, masquer","Seen it, hide")}</Btn>}
      </div>
    );
  }

  if (phase === "round") {
    const last = speaker >= order.length - 1;
    return (
      <div>
        <TopBar title={t("Imposteur","Impostor")} color={C.purple} onBack={onBack} level="soft" />
        <p style={{ fontFamily: BODY, color: C.muted, margin: "0 0 14px", fontSize: 14 }}>Manche {manche} · {alive.length} joueurs en jeu</p>
        <div style={{ background: C.surface, borderRadius: 20, padding: 18, marginBottom: 14 }}>
          <div style={{ fontFamily: BODY, fontWeight: 700, color: C.purple, fontSize: 13, marginBottom: 10 }}>{t("ORDRE DE PASSAGE","SPEAKING ORDER")}</div>
          <div style={{ display: "grid", gap: 7 }}>
            {order.map((name, i) => (
              <div key={name} style={{ display: "flex", alignItems: "center", gap: 10, fontFamily: BODY, fontSize: 15, color: i === speaker ? C.text : C.muted, fontWeight: i === speaker ? 700 : 400 }}>
                <span style={{ width: 24, height: 24, borderRadius: 7, background: i === speaker ? C.purple : C.bg2, color: i === speaker ? "#150826" : C.purple, fontWeight: 800, fontSize: 13, display: "flex", alignItems: "center", justifyContent: "center" }}>{i + 1}</span>
                {name}{i === speaker && <span style={{ fontSize: 12, color: C.purple }}>{t("à toi de donner un mot","your turn to give a word")}</span>}{i < speaker && <span style={{ fontSize: 12, color: C.muted }}>✓</span>}
              </div>
            ))}
          </div>
        </div>
        {!last ? (
          <Btn full bg={C.purple} color="#150826" onClick={() => setSpeaker((s) => s + 1)}>{t("Joueur suivant →","Next player →")}</Btn>
        ) : (
          <Btn full bg={C.purple} color="#150826" onClick={startVote}>{t("Tout le monde a parlé · Voter ⏱","Everyone has spoken · Vote ⏱")}</Btn>
        )}
      </div>
    );
  }

  if (phase === "vote") {
    const low = secondsLeft <= 20;
    return (
      <div>
        <TopBar title={t("Imposteur","Impostor")} color={C.purple} onBack={onBack} level="soft" />
        <div style={{ textAlign: "center", marginBottom: 16 }}>
          <div style={{ fontFamily: BODY, fontSize: 13, color: C.muted }}>{t("Temps pour voter","Time to vote")}</div>
          <div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 44, color: low ? C.pink : C.text, lineHeight: 1 }}>{fmt(secondsLeft)}</div>
        </div>
        <p style={{ fontFamily: BODY, color: C.muted, fontSize: 13.5, margin: "0 0 12px", textAlign: "center" }}>{t("Ajoutez une voix par joueur. Le plus voté est éliminé.","Add one voice per player. The most-voted is eliminated.")}</p>
        <div style={{ display: "grid", gap: 8, marginBottom: 16 }}>
          {alive.map((r) => (
            <div key={r.name} style={{ background: C.surface, borderRadius: 14, padding: "10px 12px", display: "flex", alignItems: "center", justifyContent: "space-between" }}>
              <span style={{ fontFamily: BODY, fontWeight: 600, color: C.text }}>{r.name}</span>
              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                <button onClick={() => setVotes((v) => ({ ...v, [r.name]: Math.max(0, (v[r.name] || 0) - 1) }))} style={{ width: 30, height: 30, borderRadius: 9, border: "none", background: C.bg2, color: C.text, fontSize: 18, cursor: "pointer" }}>−</button>
                <span style={{ fontFamily: DISPLAY, fontWeight: 800, color: C.purple, minWidth: 18, textAlign: "center" }}>{votes[r.name] || 0}</span>
                <button onClick={() => setVotes((v) => ({ ...v, [r.name]: (v[r.name] || 0) + 1 }))} style={{ width: 30, height: 30, borderRadius: 9, border: "none", background: C.purple + "33", color: C.purple, fontSize: 18, cursor: "pointer" }}>+</button>
              </div>
            </div>
          ))}
        </div>
        <Btn full bg={C.purple} color="#150826" onClick={tally}>{t("Valider les votes","Confirm votes")}</Btn>
      </div>
    );
  }

  // phase === "elim"
  if (elim && elim.tie) {
    return (
      <div>
        <TopBar title={t("Imposteur","Impostor")} color={C.purple} onBack={onBack} level="soft" />
        <div style={{ background: C.surface, borderRadius: 20, padding: "24px 20px", textAlign: "center", marginBottom: 16 }}>
          <div style={{ fontSize: 38 }}>🤝</div>
          <div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 20, color: C.text, marginTop: 4 }}>{t("Égalité","Tie")}</div>
          <div style={{ fontFamily: BODY, fontSize: 14.5, color: C.muted, marginTop: 4 }}>{t("Personne n'est éliminé ce tour.","No one is eliminated this round.")}</div>
        </div>
        <Btn full bg={C.purple} color="#150826" onClick={() => { setManche((m) => m + 1); startRound(); }}>{t("Manche suivante →","Next round →")}</Btn>
        <Btn full bg={C.surface} color={C.muted} style={{ marginTop: 10 }} onClick={startVote}>{t("Revoter","Vote again")}</Btn>
      </div>
    );
  }
  const imps = roles.filter((r) => r.isImp);
  return (
    <div>
      <TopBar title={t("Imposteur","Impostor")} color={C.purple} onBack={onBack} level="soft" />
      <div style={{ background: elim.isImp ? "linear-gradient(160deg,#2FD673,#157a42)" : "linear-gradient(160deg,#FF4D79,#7a1538)", borderRadius: 20, padding: "22px 20px", textAlign: "center", marginBottom: 16 }}>
        <div style={{ fontFamily: BODY, fontSize: 14, color: "#fff", opacity: 0.9 }}>{t("Éliminé","Eliminated")}</div>
        <div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 24, color: "#fff", marginTop: 2 }}>{elim.name}</div>
        <div style={{ fontFamily: BODY, fontSize: 15, color: "#fff", marginTop: 6 }}>{elim.isImp ? t("C'était un imposteur 🕵️","That was an impostor 🕵️") : t("C'était un civil 😬","That was a civilian 😬")}</div>
      </div>
      {winner ? (
        <div>
          <div style={{ background: "linear-gradient(160deg,#A06BFF,#5026a0)", borderRadius: 20, padding: "22px 20px", textAlign: "center", marginBottom: 16 }}>
            <div style={{ fontSize: 38 }}>{winner === "civils" ? "🎉" : "🕵️"}</div>
            <div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 22, color: "#fff", marginTop: 4 }}>{winner === "civils" ? t("Les civils gagnent !","The civilians win!") : t("Les imposteurs gagnent !","The impostors win!")}</div>
            <div style={{ fontFamily: BODY, fontSize: 14, color: "#fff", opacity: 0.9, marginTop: 10 }}>{imps.length > 1 ? t("Imposteurs : ","Impostors: ") : t("Imposteur : ","Impostor: ")}{imps.map((r) => r.name).join(", ")}</div>
            <div style={{ fontFamily: BODY, fontSize: 14, color: "#fff", opacity: 0.9, marginTop: 4 }}>Mot : {secret.word} · Mot imposteur : {secret.decoy}</div>
          </div>
          <Btn full bg={C.purple} color="#150826" onClick={deal}>{t("Rejouer 🔁","Play again 🔁")}</Btn>
          <Btn full bg={C.surface} color={C.muted} style={{ marginTop: 10 }} onClick={() => setPhase("setup")}>{t("Réglages","Settings")}</Btn>
        </div>
      ) : (
        <Btn full bg={C.purple} color="#150826" onClick={() => { setManche((m) => m + 1); startRound(); }}>{t("Manche suivante →","Next round →")}</Btn>
      )}
    </div>
  );
}

/* ====================== RIVIÈRE ====================== */
const RIV_TEAL = "#17C3B2";
function rivDeck() {
  const suits = [{ s: "♥", c: "red" }, { s: "♦", c: "red" }, { s: "♣", c: "black" }, { s: "♠", c: "black" }];
  const ranks = [{ r: 2, l: "2" }, { r: 3, l: "3" }, { r: 4, l: "4" }, { r: 5, l: "5" }, { r: 6, l: "6" }, { r: 7, l: "7" }, { r: 8, l: "8" }, { r: 9, l: "9" }, { r: 10, l: "10" }, { r: 11, l: "J" }, { r: 12, l: "Q" }, { r: 13, l: "K" }, { r: 14, l: "A" }];
  const d = [];
  suits.forEach((su) => ranks.forEach((ra) => d.push({ r: ra.r, l: ra.l, s: su.s, c: su.c })));
  return shuffle(d).slice(0, 6);
}
const RIV_STEPS = ["hl", "hl", "hl", "color", "hl"]; // cartes 2..6 (la 6e = plus/moins)

function RivCard({ card, faceUp, highlight, w = 46, h = 64 }) {
  const br = Math.max(6, Math.round(w * 0.14));
  if (!faceUp) {
    return (
      <div style={{ width: w, height: h, borderRadius: br, flexShrink: 0, position: "relative", background: "linear-gradient(135deg,#2A1A4A,#160C2C)", border: highlight ? `2px solid ${RIV_TEAL}` : "1px solid #3A2560", boxShadow: highlight ? `0 0 10px ${RIV_TEAL}` : "0 4px 10px rgba(0,0,0,.35)" }}>
        <div style={{ position: "absolute", inset: 4, borderRadius: Math.max(3, br - 3), border: "1.5px solid rgba(255,61,142,.45)", display: "flex", alignItems: "center", justifyContent: "center" }}>
          <Ic name="star" size={Math.round(w * 0.42)} color={C.pink} fill={C.pink} />
        </div>
      </div>
    );
  }
  const col = card.c === "red" ? "#D4163C" : "#17101F";
  const rk = Math.round(w * 0.3), pip = Math.round(w * 0.46), pad = Math.round(w * 0.1);
  return (
    <div style={{ width: w, height: h, borderRadius: br, flexShrink: 0, position: "relative", background: "#FCFAF5", border: highlight ? `2px solid ${RIV_TEAL}` : "1px solid #E4DCCE", boxShadow: highlight ? `0 0 10px ${RIV_TEAL}` : "0 4px 10px rgba(0,0,0,.35)", color: col }}>
      {card.l ? <span style={{ position: "absolute", top: pad, left: pad + 1, fontFamily: DISPLAY, fontWeight: 800, fontSize: rk, lineHeight: 1 }}>{card.l}</span> : null}
      <span style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontSize: pip, lineHeight: 1 }}>{card.s}</span>
      {card.l ? <span style={{ position: "absolute", bottom: pad, right: pad + 1, fontFamily: DISPLAY, fontWeight: 800, fontSize: rk, lineHeight: 1, transform: "rotate(180deg)" }}>{card.l}</span> : null}
    </div>
  );
}

function Riviere({ players, onBack }) {
  const [deck, setDeck] = useState(() => rivDeck());
  const [step, setStep] = useState(0);
  const [revealed, setRevealed] = useState(1);
  const [status, setStatus] = useState("play");
  const [drink, setDrink] = useState(0);
  const [peek, setPeek] = useState(false);

  const restart = () => { setDeck(rivDeck()); setStep(0); setRevealed(1); setStatus("play"); setDrink(0); setPeek(false); };
  const type = RIV_STEPS[step];
  const target = step + 1;
  const prev = deck[target - 1];

  const guess = (choice) => {
    const card = deck[target];
    let ok;
    if (type === "hl") {
      const rel = card.r > prev.r ? "plus" : card.r < prev.r ? "moins" : "egal";
      ok = choice === rel;
    } else ok = choice === "rouge" ? card.c === "red" : card.c === "black";
    const nr = target + 1;
    setRevealed(nr);
    if (!ok) { setStatus("lost"); setDrink(nr); }
    else if (step === 4) setStatus("won");
    else setStep(step + 1);
  };

  return (
    <div>
      <TopBar title={t("Rivière","The River")} color={RIV_TEAL} onBack={onBack} level="soft" />
      <p style={{ fontFamily: BODY, color: C.muted, margin: "0 0 16px", fontSize: 14.5, lineHeight: 1.5 }}>{t("Le meneur tient le téléphone et peut voir les cartes en secret pour bluffer. Qui se trompe prend autant de pénalités que de cartes retournées.","The leader holds the phone and can secretly see the cards to bluff. Whoever is wrong takes as many penalties as cards flipped.")}</p>

      <div style={{ display: "flex", gap: 6, justifyContent: "center", marginBottom: 18 }}>
        {deck.map((c, i) => (<RivCard key={i} card={c} faceUp={i < revealed} highlight={status === "play" && i === target} />))}
      </div>

      {status === "play" && (
        <div>
          <div style={{ background: C.surface, borderRadius: 16, padding: 16, marginBottom: 14, textAlign: "center" }}>
            <div style={{ fontFamily: BODY, fontSize: 13, color: C.muted, marginBottom: 2 }}>Carte {target + 1} sur 6</div>
            <div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 19, color: C.text }}>{type === "hl" ? `${t("Plus, égal ou moins que","Higher, equal or lower than")} ${prev.l} ${prev.s} ?` : t("Rouge ou Noir ?","Red or Black?")}</div>
          </div>
          <div style={{ display: "flex", gap: 10, marginBottom: 10 }}>
            {type === "hl" ? (<>
              <Btn bg={RIV_TEAL} color="#04241F" onClick={() => guess("plus")} style={{ flex: 1, padding: "16px 6px" }}>{t("⬆ Plus","⬆ Higher")}</Btn>
              <Btn bg={C.surface2} color={C.text} onClick={() => guess("egal")} style={{ flex: 1, padding: "16px 6px" }}>{t("= Égal","= Equal")}</Btn>
              <Btn bg={C.surface2} color={C.text} onClick={() => guess("moins")} style={{ flex: 1, padding: "16px 6px" }}>{t("⬇ Moins","⬇ Lower")}</Btn>
            </>) : (<>
              <Btn bg="#E0245E" color="#fff" onClick={() => guess("rouge")} style={{ flex: 1 }}>{t("● Rouge","● Red")}</Btn>
              <Btn bg="#1B1228" color="#fff" onClick={() => guess("noir")} style={{ flex: 1, border: `1px solid ${C.line}` }}>{t("● Noir","● Black")}</Btn>
            </>)}
          </div>
          <button onPointerDown={() => setPeek(true)} onPointerUp={() => setPeek(false)} onPointerLeave={() => setPeek(false)}
            style={{ width: "100%", fontFamily: BODY, fontWeight: 600, fontSize: 15, color: C.muted, background: C.surface, border: `1px dashed ${C.line}`, borderRadius: 14, padding: "13px 0", cursor: "pointer", WebkitTapHighlightColor: "transparent" }}>
            👁 Maintenir pour voir en secret (meneur)
          </button>
        </div>
      )}

      {status === "lost" && (
        <div>
          <div style={{ background: "linear-gradient(160deg,#E0245E,#8a1238)", borderRadius: 20, padding: "24px 20px", textAlign: "center", marginBottom: 16 }}>
            <div style={{ fontSize: 38 }}>🎯</div>
            <div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 22, color: "#fff", marginTop: 4 }}>{t("Raté !","Wrong!")}</div>
            <div style={{ fontFamily: BODY, fontSize: 16, color: "#fff", opacity: 0.9, marginTop: 4 }}>Tu prends {drink} pénalité{drink > 1 ? "s" : ""}</div>
          </div>
          <Btn full bg={RIV_TEAL} color="#04241F" onClick={restart}>{t("Nouvelle rivière 🔁","New river 🔁")}</Btn>
        </div>
      )}

      {status === "won" && (
        <div>
          <div style={{ background: "linear-gradient(160deg,#17C3B2,#0B6E64)", borderRadius: 20, padding: "24px 20px", textAlign: "center", marginBottom: 16 }}>
            <div style={{ fontSize: 38 }}>🎉</div>
            <div style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 22, color: "#fff", marginTop: 4 }}>{t("Rivière franchie !","River cleared!")}</div>
            <div style={{ fontFamily: BODY, fontSize: 16, color: "#fff", opacity: 0.9, marginTop: 4 }}>{t("Distribue 6 pénalités à qui tu veux","Hand out 6 penalties to whoever you want")}</div>
          </div>
          <Btn full bg={RIV_TEAL} color="#04241F" onClick={restart}>{t("Nouvelle rivière 🔁","New river 🔁")}</Btn>
        </div>
      )}

      {peek && (
        <div onPointerUp={() => setPeek(false)} style={{ position: "fixed", inset: 0, background: "rgba(8,5,14,.96)", zIndex: 70, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 20, padding: 20 }}>
          <div style={{ fontFamily: BODY, color: C.muted, fontSize: 14 }}>{t("Vue meneur — relâche pour cacher","Leader view, release to hide")}</div>
          <div style={{ display: "flex", gap: 8, justifyContent: "center", flexWrap: "wrap" }}>
            {deck.map((c, i) => <RivCard key={i} card={c} faceUp w={52} h={74} />)}
          </div>
        </div>
      )}
    </div>
  );
}

/* ====================== JOUEURS ====================== */
function PlayersSheet({ players, setPlayers, onClose }) {
  const [name, setName] = useState("");
  const add = () => { const n = name.trim(); if (n && !players.includes(n)) { setPlayers([...players, n]); setName(""); } };
  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,.6)", display: "flex", alignItems: "flex-end", justifyContent: "center", zIndex: 50 }} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()} style={{ background: C.bg2, width: "100%", maxWidth: 460, borderRadius: "24px 24px 0 0", padding: "22px 20px 30px", borderTop: `1px solid ${C.line}` }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 18 }}><h3 style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 20, margin: 0, color: C.text }}>{t("Joueurs","Players")}</h3><button onClick={onClose} style={{ background: "none", border: "none", color: C.muted, fontSize: 24, cursor: "pointer" }}>✕</button></div>
        <p style={{ fontFamily: BODY, color: C.muted, fontSize: 13, margin: "0 0 14px" }}>{t("Ajoute au moins 2 joueurs pour lancer un jeu.","Add at least 2 players to start a game.")}</p>
        <div style={{ display: "flex", gap: 8, marginBottom: 16 }}><input value={name} onChange={(e) => setName(e.target.value)} onKeyDown={(e) => e.key === "Enter" && add()} placeholder={t("Prénom","First name")} style={{ flex: 1, fontFamily: BODY, fontSize: 16, padding: "13px 14px", borderRadius: 13, border: `1px solid ${C.line}`, background: C.surface, color: C.text, outline: "none" }} /><Btn bg={C.text} color={C.bg} onClick={add}>{t("Ajouter","Add")}</Btn></div>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 8, minHeight: 40 }}>{players.length === 0 && <span style={{ fontFamily: BODY, color: C.muted, fontSize: 14 }}>{t("Aucun joueur pour l'instant.","No players yet.")}</span>}{players.map((p) => (<div key={p} style={{ display: "flex", alignItems: "center", gap: 8, background: C.surface, borderRadius: 20, padding: "8px 8px 8px 14px", fontFamily: BODY, color: C.text, fontSize: 14 }}>{p}<button onClick={() => setPlayers(players.filter((x) => x !== p))} style={{ background: C.line, border: "none", color: C.text, width: 22, height: 22, borderRadius: "50%", cursor: "pointer", fontSize: 12 }}>✕</button></div>))}</div>
      </div>
    </div>
  );
}

/* ====================== PAYWALL ====================== */
function Menu({ lang, onLang, premium, loggedIn, userEmail, onSubscribe, onRestore, onLogin, onLogout, onClose }) {
  const [view, setView] = useState("home");
  const [rating, setRating] = useState(0);
  const [msg, setMsg] = useState("");
  const [from, setFrom] = useState("");
  const [sent, setSent] = useState(false);
  const field = { width: "100%", boxSizing: "border-box", fontFamily: BODY, fontSize: 15, padding: "12px 14px", borderRadius: 13, border: `1px solid ${C.line}`, background: C.surface, color: C.text, outline: "none", marginBottom: 12, resize: "vertical" };
  const send = (subject, body) => { mailto(subject, body); setSent(true); };
  const row = (icon, label, onClick) => (
    <button key={label} onClick={onClick} style={{ width: "100%", textAlign: "left", background: C.surface, border: `1px solid ${C.line}`, borderRadius: 14, padding: "15px 16px", cursor: "pointer", display: "flex", alignItems: "center", gap: 12, color: C.text, fontFamily: BODY, fontSize: 15.5, fontWeight: 600, WebkitTapHighlightColor: "transparent" }}>
      <span style={{ display: "flex", alignItems: "center", width: 22 }}>{icon}</span><span style={{ flex: 1 }}>{label}</span><span style={{ color: C.muted }}>{"\u203a"}</span>
    </button>
  );
  const titles = { home: t("Menu","Menu"), lang: t("Langue","Language"), sub: t("Gérer mon abonnement","Manage subscription"), restore: t("Restaurer / résilier","Restore / cancel"), rate: t("Évaluer Pardy","Rate Pardy"), propose: t("Proposer un jeu ou des questions","Suggest a game or questions"), contact: t("Nous contacter","Contact us") };
  const done = <p style={{ fontFamily: BODY, color: C.green, fontSize: 15 }}>{t("Merci ! Ton e-mail est prêt à être envoyé.","Thanks! Your email is ready to send.")}</p>;
  let content;
  if (view === "home") {
    content = (
      <div style={{ display: "grid", gap: 10 }}>
        {false && (loggedIn
          ? <div style={{ background: C.surface, borderRadius: 14, padding: "13px 16px", display: "flex", justifyContent: "space-between", alignItems: "center" }}><span style={{ fontFamily: BODY, color: C.text, fontSize: 14 }}>{userEmail}{premium ? " · Premium" : ""}</span><button onClick={onLogout} style={{ background: "none", border: "none", color: C.muted, fontFamily: BODY, fontSize: 13, cursor: "pointer" }}>{t("Déconnexion","Log out")}</button></div>
          : row(<Ic name="user" size={19} color={C.pink} />, t("Se connecter","Sign in"), onLogin))}
        {row(<Ic name="globe" size={19} color={C.pink} />, titles.lang, () => setView("lang"))}
        {row(<Ic name="gem" size={19} color={C.pink} />, titles.sub, () => setView("sub"))}
        {row(<Ic name="restore" size={19} color={C.pink} />, titles.restore, () => setView("restore"))}
        {row(<Ic name="star" size={19} color={C.pink} />, titles.rate, () => { setSent(false); setView("rate"); })}
        {row(<Ic name="bulb" size={19} color={C.pink} />, titles.propose, () => { setSent(false); setView("propose"); })}
        {row(<Ic name="mail" size={19} color={C.pink} />, titles.contact, () => { setSent(false); setView("contact"); })}
      </div>
    );
  } else if (view === "lang") {
    const opt = (code, label) => <button key={code} onClick={() => onLang(code)} style={{ width: "100%", textAlign: "left", background: lang === code ? C.purple + "22" : C.surface, border: lang === code ? `2px solid ${C.purple}` : `1px solid ${C.line}`, borderRadius: 14, padding: "15px 16px", cursor: "pointer", color: C.text, fontFamily: BODY, fontSize: 16, fontWeight: 600, marginBottom: 10 }}>{label}{lang === code ? " ✓" : ""}</button>;
    content = <div>{opt("fr","🇫🇷 Français")}{opt("en","🇬🇧 English")}<p style={{ fontFamily: BODY, color: C.muted, fontSize: 12, marginTop: 4 }}>{t("La traduction complète des questions arrive progressivement.","Full question translation is being rolled out.")}</p></div>;
  } else if (view === "sub") {
    content = premium
      ? <div><p style={{ fontFamily: BODY, color: C.green, fontSize: 15, marginBottom: 14 }}>{t("Ton abonnement Premium est actif.","Your Premium subscription is active.")}</p><Btn full bg={C.surface} color={C.muted} onClick={() => setView("restore")}>{t("Gérer / résilier","Manage / cancel")}</Btn></div>
      : <div><Btn full bg={C.hot} color="#fff" onClick={() => onSubscribe("annual")} style={{ marginBottom: 10 }}>{t("Annuel · 34,80 €/an (−35 %)","Yearly · €34.80/yr (−35%)")}</Btn><Btn full bg={C.surface2} color={C.text} onClick={() => onSubscribe("monthly")}>{t("Mensuel · 4,49 €/mois","Monthly · €4.49/mo")}</Btn><p style={{ fontFamily: BODY, color: C.muted, fontSize: 11, textAlign: "center", marginTop: 12, opacity: 0.7 }}>{t("Paiement géré par VitrinePro33.","Payment handled by VitrinePro33.")}</p></div>;
  } else if (view === "restore") {
    content = <div>
      <Btn full bg={C.surface2} color={C.text} onClick={onRestore} style={{ marginBottom: 12 }}>{t("Restaurer mes achats","Restore my purchases")}</Btn>
      <p style={{ fontFamily: BODY, color: C.muted, fontSize: 13, marginBottom: 14 }}>{t("Pour résilier ton abonnement, écris-nous et on s'occupe de tout.","To cancel your subscription, send us a message and we'll handle it.")}</p>
      {sent ? done : <Btn full bg={C.surface} color={C.muted} onClick={() => send("Pardy — " + t("Résiliation abonnement","Subscription cancellation"), t("Bonjour, je souhaite résilier mon abonnement Pardy.","Hello, I would like to cancel my Pardy subscription.") + "\n\nEmail: " + (userEmail || ""))}>{t("Demander la résiliation","Request cancellation")}</Btn>}
    </div>;
  } else if (view === "rate") {
    content = sent ? done : <div>
      <div style={{ display: "flex", gap: 8, justifyContent: "center", marginBottom: 16 }}>{[1,2,3,4,5].map((n) => <button key={n} onClick={() => setRating(n)} style={{ background: "none", border: "none", cursor: "pointer", padding: 0, lineHeight: 0 }}><Ic name="star" size={32} sw={1.6} color={n <= rating ? "#FFB23D" : C.muted} fill={n <= rating ? "#FFB23D" : "none"} /></button>)}</div>
      <textarea value={msg} onChange={(e) => setMsg(e.target.value)} placeholder={t("Ton avis (optionnel)","Your feedback (optional)")} rows={4} style={field} />
      <Btn full bg={C.hot} color="#fff" onClick={() => send("Pardy — " + t("Évaluation","Rating") + " " + rating + "/5", t("Note","Rating") + ": " + rating + "/5\n\n" + msg)}>{t("Envoyer","Send")}</Btn>
    </div>;
  } else if (view === "propose") {
    content = sent ? done : <div>
      <textarea value={msg} onChange={(e) => setMsg(e.target.value)} placeholder={t("Ton idée de jeu ou de questions...","Your game or question idea...")} rows={5} style={field} />
      <input value={from} onChange={(e) => setFrom(e.target.value)} placeholder={t("Ton e-mail (optionnel)","Your email (optional)")} style={field} />
      <Btn full bg={C.hot} color="#fff" onClick={() => send("Pardy — " + t("Proposition de jeu ou de questions","Game or question suggestion"), msg + "\n\n" + t("De","From") + ": " + from)}>{t("Envoyer","Send")}</Btn>
    </div>;
  } else {
    content = sent ? done : <div>
      <textarea value={msg} onChange={(e) => setMsg(e.target.value)} placeholder={t("Ton message...","Your message...")} rows={5} style={field} />
      <input value={from} onChange={(e) => setFrom(e.target.value)} placeholder={t("Ton e-mail","Your email")} style={field} />
      <Btn full bg={C.hot} color="#fff" onClick={() => send("Pardy — Contact", msg + "\n\n" + t("De","From") + ": " + from)}>{t("Envoyer","Send")}</Btn>
      <p style={{ fontFamily: BODY, color: C.muted, fontSize: 12, marginTop: 12, textAlign: "center" }}>support.pardy@gmail.com</p>
    </div>;
  }
  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,.7)", display: "flex", alignItems: "flex-end", justifyContent: "center", zIndex: 70 }} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()} style={{ background: C.bg2, width: "100%", maxWidth: 460, borderRadius: "24px 24px 0 0", padding: "22px 22px 32px", borderTop: `1px solid ${C.line}`, maxHeight: "85vh", overflowY: "auto" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 18 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            {view !== "home" ? <button onClick={() => { setView("home"); setSent(false); }} style={{ background: "none", border: "none", color: C.muted, fontSize: 22, cursor: "pointer" }}>←</button> : null}
            <h3 style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 20, margin: 0, color: C.text }}>{titles[view]}</h3>
          </div>
          <button onClick={onClose} style={{ background: "none", border: "none", color: C.muted, fontSize: 24, cursor: "pointer" }}>✕</button>
        </div>
        {content}
      </div>
    </div>
  );
}

function Intro({ onClose, onSubscribe }) {
  const IC = {
    flame: <path d="M12 3c.6 2.6-1.6 3.6-1.6 5.6A2.4 2.4 0 0 0 13 11c.3-1 .2-2 .2-2 1.3 1 2.4 2.7 2.4 4.6a5.6 5.6 0 1 1-11.2 0c0-2.3 1.3-4 2.7-5.2C8.8 6.8 10.6 5.4 12 3Z" />,
    grid: <g><rect x="3.5" y="3.5" width="7" height="7" rx="1.6" /><rect x="13.5" y="3.5" width="7" height="7" rx="1.6" /><rect x="3.5" y="13.5" width="7" height="7" rx="1.6" /><rect x="13.5" y="13.5" width="7" height="7" rx="1.6" /></g>,
    refresh: <g><path d="M20.5 12a8.5 8.5 0 1 1-2.7-6.2" /><path d="M20.5 4v5h-5" /></g>,
    check: <g><circle cx="12" cy="12" r="8.6" /><path d="M8.3 12.4l2.6 2.6 4.8-5.4" /></g>,
  };
  const feats = [
    ["flame", t("736 questions Hot & Extr\u00eame d\u00e9verrouill\u00e9es", "736 Hot & Extreme questions unlocked")],
    ["grid", t("Tous les jeux et tous les niveaux", "Every game and every level")],
    ["refresh", t("De nouvelles mises \u00e0 jour r\u00e9guli\u00e8rement", "New updates regularly")],
    ["check", t("Sans engagement, r\u00e9siliable \u00e0 tout moment", "No commitment, cancel anytime")],
  ];
  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 80, background: C.bg, maxWidth: 460, margin: "0 auto", display: "flex", flexDirection: "column", padding: "18px 22px calc(26px + env(safe-area-inset-bottom))", boxSizing: "border-box", overflowY: "auto" }}>
      <div style={{ display: "flex", justifyContent: "flex-end" }}>
        <button onClick={onClose} aria-label="Fermer" style={{ background: "none", border: "none", color: C.muted, fontSize: 28, cursor: "pointer", lineHeight: 1, padding: 4 }}>✕</button>
      </div>
      <div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center" }}>
        <img src="assets/images/pardy-logo.png" alt="Pardy" style={{ width: "58%", maxWidth: 210, margin: "0 auto 14px", display: "block" }} onError={(e) => { e.currentTarget.style.display = "none"; if (e.currentTarget.nextSibling) e.currentTarget.nextSibling.style.display = "block"; }} />
        <div style={{ display: "none", textAlign: "center" }}><h1 style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 46, margin: "0 0 8px", background: "linear-gradient(100deg,#FF3D8E,#9A5BFF 55%,#FF9F1C)", WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", backgroundClip: "text" }}>PARDY</h1></div>
        <p style={{ textAlign: "center", fontFamily: DISPLAY, fontWeight: 800, letterSpacing: 3, fontSize: 12, margin: "0 0 18px", background: "linear-gradient(100deg,#9A5BFF,#FF3D8E 55%,#FF9F1C)", WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", backgroundClip: "text" }}>PREMIUM</p>
        <div style={{ background: C.surface, border: "1px solid " + C.line, borderRadius: 20, padding: "20px 18px", display: "grid", gap: 16, maxWidth: 360, margin: "0 auto", width: "100%" }}>
          {feats.map((ft) => (
            <div key={ft[1]} style={{ display: "flex", gap: 14, alignItems: "center" }}>
              <span style={{ flex: "0 0 38px", height: 38, borderRadius: 12, display: "flex", alignItems: "center", justifyContent: "center", background: C.hot + "1f", border: "1px solid " + C.hot + "47" }}>
                <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke={C.hot} strokeWidth={1.8} strokeLinecap="round" strokeLinejoin="round">{IC[ft[0]]}</svg>
              </span>
              <span style={{ fontFamily: BODY, fontWeight: 600, fontSize: 15.5, lineHeight: 1.3, color: C.text }}>{ft[1]}</span>
            </div>
          ))}
        </div>
      </div>
      <div style={{ marginTop: 18 }}>
        <p style={{ textAlign: "center", fontFamily: BODY, color: C.muted, fontSize: 15, margin: "0 0 12px" }}><b style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 26, color: C.text }}>{t("4,49 \u20ac", "\u20ac4.49")}</b> {t("/ mois", "/ month")}</p>
        <Btn full bg={C.hot} color="#fff" onClick={onSubscribe} style={{ fontSize: 18, padding: "16px 0" }}>{t("Commencer", "Get started")}</Btn>
        <button onClick={onClose} style={{ width: "100%", background: "none", border: "none", color: C.muted, fontFamily: BODY, fontSize: 13.5, marginTop: 14, cursor: "pointer" }}>{t("Continuer sans Premium", "Continue without Premium")}</button>
        <p style={{ textAlign: "center", fontFamily: BODY, color: C.muted, fontSize: 11, margin: "12px 0 0", opacity: 0.7 }}>{t("Confidentialit\u00e9 \u00b7 Conditions d'utilisation \u00b7 Restaurer l'achat", "Privacy \u00b7 Terms of use \u00b7 Restore purchase")}</p>
        <p style={{ textAlign: "center", fontFamily: BODY, color: C.muted, fontSize: 10, margin: "8px 0 0", opacity: 0.6 }}>{t("Paiement g\u00e9r\u00e9 par VitrinePro33, \u00e9diteur de l'app.", "Payment handled by VitrinePro33, app publisher.")}</p>
      </div>
    </div>
  );
}

function Paywall({ onClose, onUnlock, onRestore }) {
  const [plan, setPlan] = useState("annual");
  const plans = {
    annual: { title: "Annuel", price: "34,80 €", per: "/an", sub: "soit 2,90 €/mois", badge: "−35 %" },
    monthly: { title: "Mensuel", price: "4,49 €", per: "/mois", sub: null, badge: null },
  };
  const card = (k) => {
    const p = plans[k]; const on = plan === k;
    return (
      <button onClick={() => setPlan(k)} style={{ width: "100%", textAlign: "left", cursor: "pointer", background: on ? C.hot + "1f" : C.surface, border: on ? `2px solid ${C.hot}` : `2px solid ${C.line}`, borderRadius: 16, padding: "14px 16px", marginBottom: 10, WebkitTapHighlightColor: "transparent" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <span style={{ fontFamily: BODY, fontWeight: 700, color: C.text, fontSize: 15 }}>{p.title}{p.badge && <span style={{ marginLeft: 8, fontFamily: BODY, fontWeight: 700, fontSize: 11, color: "#fff", background: C.hot, padding: "2px 7px", borderRadius: 20 }}>{p.badge}</span>}</span>
          <span style={{ fontFamily: DISPLAY, fontWeight: 800, color: C.text, fontSize: 18 }}>{p.price}<span style={{ fontFamily: BODY, fontWeight: 500, fontSize: 13, color: C.muted }}>{p.per}</span></span>
        </div>
        {p.sub && <div style={{ fontFamily: BODY, fontSize: 12.5, color: C.green, marginTop: 2 }}>{p.sub}</div>}
      </button>
    );
  };
  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,.7)", display: "flex", alignItems: "flex-end", justifyContent: "center", zIndex: 60 }} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()} style={{ background: C.bg2, width: "100%", maxWidth: 460, borderRadius: "24px 24px 0 0", padding: "26px 22px 32px", borderTop: `1px solid ${C.hot}` }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 8 }}>
          <div style={{ width: 46, height: 46, borderRadius: 13, display: "flex", alignItems: "center", justifyContent: "center", background: C.hot + "1f", border: "1px solid " + C.hot + "47" }}><Ic name="flame" size={24} color={C.hot} /></div>
          <button onClick={onClose} style={{ background: "none", border: "none", color: C.muted, fontSize: 24, cursor: "pointer" }}>✕</button>
        </div>
        <h3 style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 24, margin: "0 0 6px", color: C.text }}>Passe en Premium</h3>
        <p style={{ fontFamily: BODY, color: C.muted, fontSize: 15, margin: "0 0 16px", lineHeight: 1.5 }}>Accès aux niveaux <b style={{ color: C.hot }}><Ic name="flame" size={15} color={C.hot} style={{ verticalAlign: -2, marginRight: 2 }} />Hot</b> et <b style={{ color: C.extreme }}><Ic name="burst" size={15} color={C.extreme} style={{ verticalAlign: -2, marginRight: 2 }} />Extrême</b> sur Action ou Vérité, Tu préfères et Je n'ai jamais. 736 questions pour adultes.</p>
        {card("annual")}
        {card("monthly")}
        <Btn full bg={C.hot} color="#fff" onClick={() => onUnlock(plan)} style={{ fontSize: 17, marginTop: 6 }}>S'abonner · {plans[plan].price}{plans[plan].per}</Btn>
        <p style={{ fontFamily: BODY, color: C.muted, fontSize: 11, textAlign: "center", margin: "10px 0 0", lineHeight: 1.5 }}>{t("En continuant, tu acceptes nos ","By continuing, you accept our ")}<a href="cgv.html" target="_blank" rel="noopener" style={{ color: C.muted, textDecoration: "underline" }}>{t("CGV","Terms")}</a>{t(" et nos "," and ")}<a href="mentions-legales.html" target="_blank" rel="noopener" style={{ color: C.muted, textDecoration: "underline" }}>{t("mentions légales","legal notice")}</a>.</p>
        <p style={{ fontFamily: BODY, color: C.muted, fontSize: 11.5, textAlign: "center", margin: "12px 0 0", lineHeight: 1.5 }}>Sans engagement, résiliable à tout moment. La formule annuelle revient à 2,90 €/mois, soit 35 % de moins que le mensuel.</p>
        <p style={{ fontFamily: BODY, color: C.muted, fontSize: 10, textAlign: "center", margin: "8px 0 0", opacity: 0.65 }}>Paiement sécurisé géré par VitrinePro33, éditeur de l'app.</p>
        {onRestore && <button onClick={onRestore} style={{ width: "100%", background: "none", border: "none", color: C.text, fontFamily: BODY, fontSize: 13, marginTop: 16, cursor: "pointer", textDecoration: "underline", WebkitTapHighlightColor: "transparent" }}>{t("J'ai déjà payé · Restaurer mon accès", "Already paid · Restore my access")}</button>}
      </div>
    </div>
  );
}

/* ====================== APP ====================== */
function App() {
  const [screen, setScreen] = useState("home");
  const [players, setPlayers] = useState([]);
  const [sheet, setSheet] = useState(false);
  const [paywall, setPaywall] = useState(false);
  const [level, setLevel] = useState("soft");
  const [intro, setIntro] = useState(true);
  const [menu, setMenu] = useState(false);
  const [lang, setLang] = useState("fr");
  const changeLang = (l) => { LANG = l; setLang(l); };
  const [premium, setPremium] = useState(false);
  const PREMIUM_KEY = "pardy_premium_sub";
  const applyContent = (d) => {
    if (!d) return;
    AV.hot = d.av.hot; AV.extreme = d.av.extreme;
    if (d.av_en) { AV_EN.hot = d.av_en.hot; AV_EN.extreme = d.av_en.extreme; }
    if (d.tp_en) { TP_EN.hot = d.tp_en.hot; TP_EN.extreme = d.tp_en.extreme; }
    if (d.jnj_en) { JNJ_EN.hot = d.jnj_en.hot; JNJ_EN.extreme = d.jnj_en.extreme; }
    if (d.qp_en) { QP_EN.hot = d.qp_en.hot; QP_EN.extreme = d.qp_en.extreme; }
    JNJ_POOLS.hot = d.jnj.hot; JNJ_POOLS.extreme = d.jnj.extreme;
    TP.hot = d.tp.hot; TP.extreme = d.tp.extreme;
    QP_POOLS.hot = d.qp.hot; QP_POOLS.extreme = d.qp.extreme;
    window.__premiumLoaded = true;
  };
  const loadFrom = async (opts) => {
    if (!window.CONTENT_URL) return false;
    try {
      const headers = { "Content-Type": "application/json" };
      const _key = opts.auth || window.SUPABASE_ANON_KEY || "";
      if (_key) headers["Authorization"] = "Bearer " + _key;
      if (window.SUPABASE_ANON_KEY) headers["apikey"] = window.SUPABASE_ANON_KEY;
      const res = await fetch(window.CONTENT_URL, { method: "POST", headers, body: JSON.stringify(opts.body || {}) });
      if (!res.ok) return false;
      const d = await res.json();
      if (!d || !d.ok) return false;
      if (d.sub_id) { try { localStorage.setItem(PREMIUM_KEY, d.sub_id); } catch (e) {} }
      applyContent(d.content);
      setPremium(true);
      return true;
    } catch (e) { return false; }
  };
  const verifyAndLoad = async (payload) => loadFrom({ body: payload });
  const loadWithSession = async () => {
    if (!window.sb) return false;
    try { const { data } = await window.sb.auth.getSession(); const s = data && data.session; if (!s) return false; return await loadFrom({ auth: s.access_token }); } catch (e) { return false; }
  };
  const startCheckout = (plan) => {
    const link = plan === "monthly" ? window.STRIPE_LINK_MONTHLY : window.STRIPE_LINK_ANNUAL;
    if (!link) { alert(t("Paiement non configuré (config.js).", "Payment not configured (config.js).")); return; }
    window.location.href = link;
  };
  const restoreAccess = async () => {
    if (!window.sb) { alert(t("Restauration indisponible (config.js).", "Restore unavailable (config.js).")); return; }
    let email = "";
    try { email = window.prompt(t("Entre l'e-mail utilisé lors du paiement :", "Enter the email used at payment:")) || ""; } catch (e) {}
    email = email.trim();
    if (!email) return;
    try {
      const { error } = await window.sb.auth.signInWithOtp({ email, options: { emailRedirectTo: window.location.origin + window.location.pathname } });
      alert(error ? (error.message || t("Envoi impossible.", "Could not send.")) : t("Lien envoyé ! Ouvre ta boîte mail et clique sur le lien pour débloquer ton accès.", "Link sent! Open your inbox and click the link to unlock your access."));
    } catch (e) { alert(t("Envoi impossible pour le moment.", "Could not send right now.")); }
  };
  useEffect(() => {
    if (typeof window === "undefined") return;
    let params; try { params = new URLSearchParams(window.location.search); } catch (e) { params = null; }
    const sid = params ? params.get("session_id") : null;
    if (sid) {
      verifyAndLoad({ session_id: sid }).finally(() => {
        try { params.delete("session_id"); params.delete("paid"); const q = params.toString(); window.history.replaceState({}, "", window.location.pathname + (q ? "?" + q : "")); } catch (e) {}
      });
      return;
    }
    let stored = null; try { stored = localStorage.getItem(PREMIUM_KEY); } catch (e) {}
    if (stored) { verifyAndLoad({ sub_id: stored }); return; }
    if (window.sb) {
      loadWithSession();
      try { window.sb.auth.onAuthStateChange((_e, session) => { if (session) loadWithSession(); }); } catch (e) {}
    }
  }, []);

  useEffect(() => {
    const l = document.createElement("link"); l.rel = "stylesheet";
    l.href = "https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&family=Outfit:wght@300;400;500;600;700&display=swap";
    document.head.appendChild(l);
    return () => { try { document.head.removeChild(l); } catch (e) {} };
  }, []);
  const back = () => { setLevel("soft"); setScreen("home"); };
  const chooseLevel = async (lv) => {
    if (lv !== "soft" && !premium) { setPaywall(true); return; }
    if (lv !== "soft" && !window.__premiumLoaded) {
      let stored = null; try { stored = localStorage.getItem("pardy_premium_sub"); } catch (e) {}
      const ok = stored ? await verifyAndLoad({ sub_id: stored }) : false;
      if (!ok) { alert(t("Contenu Premium indisponible pour le moment.","Premium content unavailable right now.")); return; }
    }
    setLevel(lv);
  };
  // niveau effectif d'un jeu : soft si jeu non concerné
  const gl = (id) => (LEVELLED.includes(id) ? level : "soft");
  const openGame = (id) => { if (players.length < 2) { setSheet(true); return; } setScreen(id); };
  const handleSubscribe = (plan) => { setMenu(false); startCheckout(plan); };
  const handleRestore = () => { setMenu(false); restoreAccess(); };
  const demoLogin = () => { setMenu(false); };
  const demoLogout = () => { setMenu(false); };

  return (
    <div style={{ minHeight: "100vh", background: C.bg, color: C.text, fontFamily: BODY }}>
      <div style={{ maxWidth: 460, margin: "0 auto", padding: "26px 20px 60px", minHeight: "100vh", boxSizing: "border-box" }}>
        {screen === "home" && <Home players={players} level={level} premium={premium} onPremium={() => setPaywall(true)} onOpen={openGame} onPlayers={() => setSheet(true)} onMenu={() => setMenu(true)} />}
        {screen === "av" && <ActionVerite players={players} level={gl("av")} premium={premium} onChooseLevel={chooseLevel} onBack={back} />}
        {screen === "tp" && <TuPrefere level={gl("tp")} premium={premium} onChooseLevel={chooseLevel} onBack={back} />}
        {screen === "jnj" && <JeNaiJamais level={gl("jnj")} premium={premium} onChooseLevel={chooseLevel} onBack={back} />}
        {screen === "qp" && <QuiPourrait level={gl("qp")} premium={premium} onChooseLevel={chooseLevel} onBack={back} />}
        {screen === "pmu" && <PMU players={players} onBack={back} />}
        {screen === "riv" && <Riviere players={players} onBack={back} />}
        {screen === "imp" && <Imposteur players={players} onBack={back} openPlayers={() => setSheet(true)} />}
      </div>
      {sheet && <PlayersSheet players={players} setPlayers={setPlayers} onClose={() => setSheet(false)} />}
      {paywall && <Paywall onClose={() => setPaywall(false)} onUnlock={startCheckout} onRestore={restoreAccess} />}
      {intro && !premium && <Intro onClose={() => setIntro(false)} onSubscribe={() => { setIntro(false); startCheckout("monthly"); }} />}
      {menu && <Menu lang={lang} onLang={changeLang} premium={premium} loggedIn={false} userEmail={null} onSubscribe={handleSubscribe} onRestore={handleRestore} onLogin={demoLogin} onLogout={demoLogout} onClose={() => setMenu(false)} />}
    </div>
  );
}

function Home({ players, level, premium, onPremium, onOpen, onPlayers, onMenu }) {
  const isHot = level !== "soft";
  return (
    <div>
      <div style={{ display: "flex", justifyContent: "flex-end", alignItems: "center", gap: 12 }}>
        <button onClick={onMenu} aria-label="Menu" style={{ background: C.surface, border: `1px solid ${C.line}`, borderRadius: 12, width: 42, height: 42, color: C.text, fontSize: 18, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", WebkitTapHighlightColor: "transparent" }}>☰</button>
      </div>
      <div style={{ textAlign: "center", margin: "2px 0 6px" }}>
        <img src="assets/images/pardy-logo.png" alt="Pardy — Let's get Pardy !" style={{ width: "80%", maxWidth: 300, margin: "0 auto", display: "block" }} onError={(e) => { e.currentTarget.style.display = "none"; if (e.currentTarget.nextSibling) e.currentTarget.nextSibling.style.display = "block"; }} />
        <div style={{ display: "none" }}>
          <h1 style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 56, margin: 0, lineHeight: 0.92, background: "linear-gradient(100deg,#FF3D8E,#9A5BFF 55%,#37C3FF)", WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", backgroundClip: "text" }}>PARDY</h1>
          <div style={{ fontFamily: DISPLAY, fontStyle: "italic", fontWeight: 700, fontSize: 18, marginTop: 4, background: "linear-gradient(100deg,#9A5BFF,#FF3D8E 55%,#FF9F1C)", WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", backgroundClip: "text" }}>Let's get Pardy !</div>
        </div>
      </div>

      {!premium && (
        <button onClick={onPremium} style={{ marginTop: 22, width: "100%", border: "none", cursor: "pointer", borderRadius: 18, padding: "13px 15px", background: "linear-gradient(100deg," + C.hot + "," + C.purple + ")", WebkitTapHighlightColor: "transparent", display: "flex", alignItems: "center", gap: 13, textAlign: "left", boxShadow: "0 10px 26px rgba(154,91,255,.30)", position: "relative", overflow: "hidden" }}>
          <span style={{ position: "absolute", inset: 0, background: "linear-gradient(180deg,rgba(255,255,255,.18),transparent 42%)", pointerEvents: "none" }} />
          <span style={{ flex: "0 0 40px", height: 40, borderRadius: 12, display: "flex", alignItems: "center", justifyContent: "center", background: "rgba(255,255,255,.18)", position: "relative" }}>
            <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#fff" strokeWidth={1.7} strokeLinecap="round" strokeLinejoin="round"><path d="M5 4h14l3 5-10 12L2 9z" /><path d="M2 9h20M9 4l-2.5 5L12 21M15 4l2.5 5L12 21" /></svg>
          </span>
          <span style={{ flex: 1, display: "flex", flexDirection: "column", position: "relative" }}>
            <span style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 16.5, color: "#fff", lineHeight: 1.1 }}>{t("Passer au Premium","Go Premium")}</span>
            <span style={{ fontFamily: BODY, fontWeight: 500, fontSize: 12.5, color: "rgba(255,255,255,.85)", marginTop: 3 }}>{t("Hot, Extrême et tous les niveaux · dès 4,49 €","Hot, Extreme and all levels · from €4.49")}</span>
          </span>
          <span style={{ position: "relative", color: "rgba(255,255,255,.92)", fontSize: 24, fontWeight: 300 }}>{"\u203a"}</span>
        </button>
      )}

      <button onClick={onPlayers} style={{ marginTop: 16, marginBottom: 22, width: "100%", textAlign: "left", background: C.surface, border: `1px solid ${C.line}`, borderRadius: 16, padding: "14px 16px", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", WebkitTapHighlightColor: "transparent" }}>
        <span style={{ fontFamily: BODY, color: C.text, fontWeight: 600, display: "flex", alignItems: "center", gap: 9 }}><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke={C.pink} strokeWidth={1.7} strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}><circle cx="9" cy="8" r="3.2" /><path d="M3.5 19a5.5 5.5 0 0 1 11 0" /><path d="M16 5.5a3.2 3.2 0 0 1 0 6.2" /><path d="M17 14.2A5.5 5.5 0 0 1 20.5 19" /></svg><span>{t("Joueurs","Players")} {players.length > 0 && <span style={{ color: C.muted, fontWeight: 400 }}>· {players.join(", ")}</span>}</span></span>
        <span style={{ fontFamily: BODY, color: C.muted, fontSize: 14 }}>{players.length === 0 ? t("Ajouter","Add") : t("Modifier","Edit")}</span>
      </button>

      <div style={{ display: "grid", gap: 14 }}>
        {GAMES.map((g) => {
          const showsLevel = g.levelled && isHot;
          const lv = LEVELS[level];
          return (
            <button key={g.id} onClick={() => onOpen(g.id)} style={{ position: "relative", overflow: "hidden", textAlign: "left", cursor: "pointer", background: C.surface, border: "none", borderRadius: 22, padding: "22px 20px", display: "flex", alignItems: "center", gap: 16, WebkitTapHighlightColor: "transparent", transition: "transform .12s ease" }}
              onPointerDown={(e) => (e.currentTarget.style.transform = "scale(.985)")} onPointerUp={(e) => (e.currentTarget.style.transform = "scale(1)")} onPointerLeave={(e) => (e.currentTarget.style.transform = "scale(1)")}>
              <div style={{ position: "absolute", right: -30, top: "50%", transform: "translateY(-50%)", width: 130, height: 130, borderRadius: "50%", background: g.color, opacity: 0.16, filter: "blur(6px)" }} />
              <div style={{ position: "relative", width: 54, height: 54, flexShrink: 0 }}>
                <div style={{ position: "absolute", inset: 0, borderRadius: 16, fontSize: 28, display: "flex", alignItems: "center", justifyContent: "center", background: g.color + "26", border: `1.5px solid ${g.color}` }}>{g.emoji}</div>
                {g.img && <img src={g.img} alt="" style={{ position: "absolute", inset: 0, width: 54, height: 54, borderRadius: 16, objectFit: "cover", border: `1.5px solid ${g.color}` }} onError={(e) => (e.currentTarget.style.display = "none")} />}
              </div>
              <div style={{ position: "relative", flex: 1 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <span style={{ fontFamily: DISPLAY, fontWeight: 800, fontSize: 20, color: C.text }}>{LANG === "en" ? GAME_I18N[g.id].name : g.name}</span>
                  {showsLevel && <span style={{ fontFamily: BODY, fontWeight: 700, fontSize: 10.5, color: lv.color, border: `1px solid ${lv.color}`, padding: "1px 6px", borderRadius: 20 }}>{lv.badge}</span>}
                </div>
                <div style={{ fontFamily: BODY, fontSize: 13, color: C.muted, marginTop: 2 }}>{LANG === "en" ? GAME_I18N[g.id].tag : g.tag}</div>
              </div>
            </button>
          );
        })}
      </div>
      <p style={{ textAlign: "center", fontFamily: BODY, color: C.muted, fontSize: 12, marginTop: 26 }}>{t("Réservé aux adultes · 18+","Adults only · 18+")}</p>
      <div style={{ textAlign: "center", marginTop: 14, paddingBottom: 8 }}>
        <a href="mentions-legales.html" target="_blank" rel="noopener" style={{ fontFamily: BODY, color: C.muted, fontSize: 11.5, textDecoration: "none", opacity: 0.8 }}>{t("Mentions légales","Legal notice")}</a>
        <span style={{ color: C.muted, fontSize: 11.5, opacity: 0.5, margin: "0 8px" }}>·</span>
        <a href="cgv.html" target="_blank" rel="noopener" style={{ fontFamily: BODY, color: C.muted, fontSize: 11.5, textDecoration: "none", opacity: 0.8 }}>{t("CGV","Terms")}</a>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
