Torn Poker Helper

Clean and simple poker helper for Torn City

// ==UserScript==
// @name         Torn Poker Helper
// @namespace    http://tampermonkey.net/
// @version      1.4.2
// @description  Clean and simple poker helper for Torn City
// @author       JESUUS [2353554]
// @match        https://www.torn.com/page.php?sid=holdem*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    const ranks = '23456789TJQKA'.split('');
    const expertMode = false;
    const showProbabilities = true;
    const cache = new Map();
    let lastGameState = null;

    const translations = {
        en: {
            yourCards: 'Your cards',
            board: 'Board',
            combination: 'Combination',
            advice: 'Advice',
            draws: 'Draws',
            activePlayers: 'Active players',
            waiting: 'Waiting...',
            empty: 'Empty',
            analyzing: 'Analyzing...',
            outOf: 'outs •',
            chanceOf: '% chance',
            highCard: 'High Card',
            onePair: 'One Pair',
            twoPair: 'Two Pair',
            threeOfAKind: 'Three of a Kind',
            straight: 'Straight',
            flush: 'Flush',
            fullHouse: 'Full House',
            fourOfAKind: 'Four of a Kind',
            straightFlush: 'Straight Flush',
            royalFlush: 'Royal Flush',
            weakHandDrawTemplate:
                '🤔 Weak hand but possible draw ({probability}% chance). {position}',
            inPosition: 'In position, you can call or raise small',
            outOfPosition: 'Out of position, be careful',
            weakHandFollow:
                '🤔 Weak hand but possible draw. Call or check if cheap',
            allIn: '💰 You can go all-in (very strong hand)',
            raiseStrong: '🔥 You can raise big (good hand in position)',
            raiseNormal: '🔥 You can raise (good hand)',
            callOrRaise: '🙂 You can call or small raise (few opponents)',
            callOnly: '🙂 You can call',
            checkInPosition: '🤏 You can check in position',
            foldOrCheck: '🕊️ Wait and see (or fold)',
            fold: '🚫 I advise you to fold',
            winProbability: 'Win chance',
            folded: 'Folded',
            assistant: 'Poker Assistant',
            helper: 'Torn City Helper',
            language: 'Language',
            minimize: 'Minimize',
            maximize: 'Maximize',
            toggleView: 'Toggle view',
        },
        fr: {
            yourCards: 'Tes cartes',
            board: 'Plateau',
            combination: 'Combinaison',
            advice: 'Conseil',
            draws: 'Tirages',
            activePlayers: 'Joueurs actifs',
            waiting: 'En attente...',
            empty: 'Vide',
            analyzing: 'Analyse en cours...',
            outOf: 'outs •',
            chanceOf: '% de chances',
            highCard: 'Aucune combinaison',
            onePair: 'Une paire',
            twoPair: 'Deux paires',
            threeOfAKind: 'Un brelan',
            straight: 'Une suite',
            flush: 'Une couleur',
            fullHouse: 'Un full',
            fourOfAKind: 'Un carré',
            straightFlush: 'Suite couleur',
            royalFlush: 'Quinte flush royale',
            weakHandDrawTemplate:
                '🤔 Main faible mais tirage possible ({probability}% chance). {position}',
            inPosition: 'En position, tu peux suivre ou relancer petit',
            outOfPosition: 'Hors position, prudence',
            weakHandFollow:
                '🤔 Main faible mais tirage possible. Suis ou check si pas cher',
            allIn: '💰 Tu peux tout mettre (très forte main)',
            raiseStrong: '🔥 Tu peux relancer fort (bonne main en position)',
            raiseNormal: '🔥 Tu peux relancer (bonne main)',
            callOrRaise:
                "🙂 Tu peux suivre ou relancer léger (peu d'adversaires)",
            callOnly: '🙂 Tu peux suivre (call)',
            checkInPosition: '🤏 Tu peux checker en position',
            foldOrCheck: '🕊️ Attends de voir (ou couche-toi)',
            fold: '🚫 Je te conseille de te coucher',
            winProbability: 'Chance de victoire',
            folded: 'Couché',
            assistant: 'Assistant Poker',
            helper: 'Aide Torn City',
            language: 'Langue',
            minimize: 'Réduire',
            maximize: 'Agrandir',
            toggleView: 'Changer la vue',
        },
        de: {
            yourCards: 'Deine Karten',
            board: 'Board',
            combination: 'Kombination',
            advice: 'Ratschlag',
            draws: 'Draws',
            activePlayers: 'Aktive Spieler',
            waiting: 'Warten...',
            empty: 'Leer',
            analyzing: 'Analysieren...',
            outOf: 'Outs •',
            chanceOf: '% Chance',
            highCard: 'Höchste Karte',
            onePair: 'Ein Paar',
            twoPair: 'Zwei Paare',
            threeOfAKind: 'Drilling',
            straight: 'Straße',
            flush: 'Flush',
            fullHouse: 'Full House',
            fourOfAKind: 'Vierling',
            straightFlush: 'Straight Flush',
            royalFlush: 'Royal Flush',
            weakHandDrawTemplate:
                '🤔 Schwache Hand aber möglicher Draw ({probability}% Chance). {position}',
            inPosition: 'In Position, du kannst callen oder klein raisen',
            outOfPosition: 'Außerhalb der Position, sei vorsichtig',
            weakHandFollow:
                '🤔 Schwache Hand aber möglicher Draw. Calle oder checke wenn billig',
            allIn: '💰 Du kannst All-in gehen (sehr starke Hand)',
            raiseStrong: '🔥 Du kannst stark erhöhen (gute Hand in Position)',
            raiseNormal: '🔥 Du kannst erhöhen (gute Hand)',
            callOrRaise:
                '🙂 Du kannst callen oder leicht erhöhen (wenige Gegner)',
            callOnly: '🙂 Du kannst callen',
            checkInPosition: '🤏 Du kannst in Position checken',
            foldOrCheck: '🕊️ Warte ab (oder folde)',
            fold: '🚫 Ich rate dir zu folden',
            winProbability: 'Gewinnchance',
            folded: 'Gefoldet',
            assistant: 'Poker Assistent',
            helper: 'Torn City Helfer',
            language: 'Sprache',
            minimize: 'Minimieren',
            maximize: 'Maximieren',
            toggleView: 'Ansicht umschalten',
        },
        es: {
            yourCards: 'Tus cartas',
            board: 'Mesa',
            combination: 'Combinación',
            advice: 'Consejo',
            draws: 'Posibilidades',
            activePlayers: 'Jugadores activos',
            waiting: 'Esperando...',
            empty: 'Vacío',
            analyzing: 'Analizando...',
            outOf: 'outs •',
            chanceOf: '% de probabilidad',
            highCard: 'Carta alta',
            onePair: 'Una pareja',
            twoPair: 'Dos parejas',
            threeOfAKind: 'Trío',
            straight: 'Escalera',
            flush: 'Color',
            fullHouse: 'Full',
            fourOfAKind: 'Póker',
            straightFlush: 'Escalera de color',
            royalFlush: 'Escalera real',
            weakHandDrawTemplate:
                '🤔 Mano débil pero posible proyecto ({probability}% probabilidad). {position}',
            inPosition: 'En posición, puedes ver o subir poco',
            outOfPosition: 'Fuera de posición, ten cuidado',
            weakHandFollow:
                '🤔 Mano débil pero posible proyecto. Ve o pasa si es barato',
            allIn: '💰 Puedes ir all-in (mano muy fuerte)',
            raiseStrong: '🔥 Puedes subir fuerte (buena mano en posición)',
            raiseNormal: '🔥 Puedes subir (buena mano)',
            callOrRaise: '🙂 Puedes ver o subir poco (pocos oponentes)',
            callOnly: '🙂 Puedes ver',
            checkInPosition: '🤏 Puedes pasar en posición',
            foldOrCheck: '🕊️ Espera (o retírate)',
            fold: '🚫 Te aconsejo retirarte',
            winProbability: 'Probabilidad de ganar',
            folded: 'Retirado',
            assistant: 'Asistente de Póker',
            helper: 'Ayudante de Torn City',
            language: 'Idioma',
            minimize: 'Minimizar',
            maximize: 'Maximizar',
            toggleView: 'Cambiar vista',
        },
    };

    let currentLang = localStorage.getItem('tornPokerLanguage') || 'en';
    let isMinimized = localStorage.getItem('tornPokerMinimized') === 'true';
    let isMobileMode = false;
    let mobilePosition =
        localStorage.getItem('tornPokerMobilePosition') || 'bottom-right';
    function detectMobileMode() {
        isMobileMode = window.innerWidth <= 768;
        return isMobileMode;
    }

    window.addEventListener('resize', function () {
        const wasMobile = isMobileMode;
        const isMobileNow = detectMobileMode();

        if (wasMobile !== isMobileNow) {
            const main = lireCartesJoueur();
            const board = lireCartesPlateau();
            afficherInfos(main, board);
        }
    });
    function t(key, replacements = {}) {
        const text =
            translations[currentLang][key] || translations['en'][key] || key;
        return Object.entries(replacements).reduce((result, [key, value]) => {
            return result.replace(new RegExp('{' + key + '}', 'g'), value);
        }, text);
    }

    function changerLangue(lang) {
        if (translations[lang]) {
            currentLang = lang;
            localStorage.setItem('tornPokerLanguage', lang);
            const main = lireCartesJoueur();
            const board = lireCartesPlateau();
            afficherInfos(main, board);
        }
    }

    function changerPositionMobile() {
        const positions = [
            'top-left',
            'top-right',
            'bottom-right',
            'bottom-left',
        ];
        const currentIndex = positions.indexOf(mobilePosition);
        const nextIndex = (currentIndex + 1) % positions.length;
        mobilePosition = positions[nextIndex];
        localStorage.setItem('tornPokerMobilePosition', mobilePosition);

        const main = lireCartesJoueur();
        const board = lireCartesPlateau();
        afficherInfos(main, board);
    }
    function getPositionMobileStyles() {
        switch (mobilePosition) {
            case 'top-left':
                return 'top: 10px; left: 10px;';
            case 'top-right':
                return 'top: 10px; right: 10px;';
            case 'bottom-left':
                return 'bottom: 30px; left: 10px;';
            case 'bottom-right':
            default:
                return 'bottom: 30px; right: 10px;';
        }
    }

    const htmlTemplates = {
        mobileCard: (label, value, color = '#e2e8f0', dataAttr = '') => `
			<div style="
				background: rgba(255, 255, 255, 0.05);
				border-radius: 6px;
				padding: 5px 8px;
				margin-bottom: 4px;
				display: flex;
				justify-content: space-between;
				align-items: center;
			">
				<span style="font-size: 11px; color: ${color}; opacity: 0.9;">${label}</span>
				<span ${dataAttr} style="font-family: 'Courier New', monospace; font-weight: 600; color: ${color}; font-size: 12px;">
					${value}
				</span>
			</div>
		`,

        desktopCard: (
            label,
            value,
            color = '#e2e8f0',
            bgColor = 'rgba(255, 255, 255, 0.05)',
            dataAttr = ''
        ) => `
			<div style="
				background: ${bgColor};
				border-radius: 8px;
				padding: 10px 12px;
				margin-bottom: 16px;
			">
				<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;">
					<div style="width: 6px; height: 6px; background: ${color}; border-radius: 50%; box-shadow: 0 0 8px ${color}60;"></div>
					<span style="font-weight: 600; font-size: 13px; color: #e2e8f0;">${label}</span>
				</div>
				<div ${dataAttr} style="
					background: ${bgColor};
					border: 1px solid ${color}20;
					border-radius: 8px;
					padding: 10px 12px;
					font-family: 'Courier New', monospace;
					font-weight: 600;
					color: ${color};
					font-size: 15px;
				">${value}</div>
			</div>
		`,

        langOption: (code, flag, name, isActive) => `
			<div class="langOption" data-lang="${code}" style="
				display: flex;
				align-items: center;
				gap: 6px;
				padding: 6px 8px;
				color: ${isActive ? '#60a5fa' : '#e2e8f0'};
				font-weight: ${isActive ? '600' : '500'};
				font-size: 11px;
				cursor: pointer;
				transition: background 0.2s ease;
				${isActive ? 'background: rgba(59, 130, 246, 0.1);' : ''}
			">
				<span style="font-size: 12px;">${flag}</span>
				<span>${name}</span>
			</div>
		`,

        generateMobileInterface: (
            couleurAccent,
            main,
            board,
            nomFinal,
            conseilFinal,
            outs,
            nbJoueurs,
            isMinimized,
            winProbability
        ) => {
            if (isMinimized) {
                return `
					<div id="toggleMinimize" style="
						width: 40px;
						height: 40px;
						display: flex;
						align-items: center;
						justify-content: center;
						cursor: pointer;
						background: linear-gradient(135deg, ${couleurAccent}50, ${couleurAccent}30);
						border-radius: 10px;
						position: relative;
					">
						<div style="
							width: 28px;
							height: 28px;
							background: linear-gradient(135deg, ${couleurAccent}, ${couleurAccent}80);
							border-radius: 8px;
							display: flex;
							align-items: center;
							justify-content: center;
							font-size: 14px;
						">🃏</div>
						<div style="
							position: absolute;
							bottom: -1px;
							right: -1px;
							width: 10px;
							height: 10px;
							background: rgba(255, 255, 255, 0.9);
							border-radius: 50%;
							display: flex;
							align-items: center;
							justify-content: center;
							font-size: 7px;
							color: #333;
						">📍</div>
					</div>
				`;
            }

            return `
				<div style="display: flex; flex-direction: column;">
					<div style="
						display: flex;
						align-items: center;
						justify-content: space-between;
						padding: 6px 8px;
						border-bottom: 1px solid rgba(255, 255, 255, 0.1);
					">
						<div style="display: flex; align-items: center; gap: 6px;">
							<div style="
								width: 20px;
								height: 20px;
								background: linear-gradient(135deg, ${couleurAccent}, ${couleurAccent}80);
								border-radius: 5px;
								display: flex;
								align-items: center;
								justify-content: center;
								font-size: 11px;
							">🃏</div>
							<div style="font-weight: 600; font-size: 11px; color: white; opacity: 0.95;">${t(
                                'assistant'
                            )}</div>
						</div>
						<div style="display: flex; gap: 4px;">
							<div id="positionButton" style="
								width: 20px;
								height: 20px;
								display: flex;
								align-items: center;
								justify-content: center;
								background: rgba(255, 255, 255, 0.1);
								border-radius: 5px;
								cursor: pointer;
								font-size: 9px;
							">📍</div>
							<div id="langSelector" style="position: relative;">
								<div id="langButton" style="
									width: 20px;
									height: 20px;
									display: flex;
									align-items: center;
									justify-content: center;
									background: rgba(255, 255, 255, 0.1);
									border-radius: 5px;
									cursor: pointer;
									font-size: 9px;
								">${langConfig[currentLang].flag}</div>
								<div id="langOptions" style="
									display: none;
									position: absolute;
									top: 100%;
									right: 0;
									margin-top: 2px;
									background: rgba(15, 23, 42, 0.98);
									border: 1px solid rgba(255, 255, 255, 0.1);
									border-radius: 5px;
									overflow: hidden;
									box-shadow: 0 4px 12px -2px rgba(0, 0, 0, 0.8);
									width: 90px;
									z-index: 100000;
								">
									${Object.entries(langConfig)
                                        .map(
                                            ([code, { flag, name }]) => `
										<div class="langOption" data-lang="${code}" style="
											display: flex;
											align-items: center;
											gap: 5px;
											padding: 5px 8px;
											color: ${code === currentLang ? '#60a5fa' : '#e2e8f0'};
											font-weight: ${code === currentLang ? '600' : '500'};
											font-size: 9px;
											cursor: pointer;
											transition: background 0.2s ease;
											${code === currentLang ? 'background: rgba(59, 130, 246, 0.1);' : ''}
										">
											<span style="font-size: 9px;">${flag}</span>
											<span>${name}</span>
										</div>
									`
                                        )
                                        .join('')}
								</div>
							</div>
							<div id="toggleMinimize" style="
								width: 20px;
								height: 20px;
								display: flex;
								align-items: center;
								justify-content: center;
								background: rgba(255, 255, 255, 0.1);
								border-radius: 5px;
								cursor: pointer;
								font-size: 11px;
							">–</div>
						</div>
					</div>

					<div style="padding: 6px 8px;">
						${htmlTemplates.mobileCard(
                            t('yourCards'),
                            main.length ? main.join(' ') : t('waiting'),
                            'white',
                            'data-player-cards'
                        )}
						${htmlTemplates.mobileCard(
                            t('board'),
                            board.length ? board.join(' ') : t('empty'),
                            '#10b981',
                            'data-board-cards'
                        )}
						${htmlTemplates.mobileCard(
                            t('combination'),
                            nomFinal || t('analyzing'),
                            '#8b5cf6',
                            'data-combination'
                        )}
						${
                            winProbability > 0
                                ? htmlTemplates.mobileCard(
                                      t('winProbability'),
                                      `${Math.round(winProbability * 100)}%`,
                                      '#3b82f6',
                                      'data-win-probability'
                                  )
                                : ''
                        }
						<div data-advice style="
							background: linear-gradient(135deg, ${couleurAccent}30, ${couleurAccent}15);
							border: 1px solid ${couleurAccent}50;
							border-radius: 6px;
							padding: 5px 8px;
							color: white;
							font-weight: 600;
							font-size: 11px;
							line-height: 1.3;
							text-align: center;
							margin-bottom: 4px;
						">${conseilFinal}</div>
						${
                            outs && outs.nombre > 0
                                ? htmlTemplates.mobileCard(
                                      t('draws'),
                                      `${outs.nombre} ${t(
                                          'outOf'
                                      )} ${Math.round(
                                          outs.probability * 100
                                      )}${t('chanceOf')}`,
                                      '#f59e0b',
                                      'data-outs'
                                  )
                                : ''
                        }
					</div>
				</div>
			`;
        },

        generateLangSelector: (couleurAccent) => `
			<div id="langSelector" style="position: relative;">
				<div id="langButton" style="
					width: 24px;
					height: 24px;
					display: flex;
					align-items: center;
					justify-content: center;
					background: rgba(255, 255, 255, 0.1);
					border-radius: 6px;
					cursor: pointer;
					font-size: 12px;
				">${langConfig[currentLang].flag}</div>
				<div id="langOptions" style="
					display: none;
					position: absolute;
					top: 100%;
					right: 0;
					margin-top: 4px;
					background: rgba(15, 23, 42, 0.98);
					border: 1px solid rgba(255, 255, 255, 0.1);
					border-radius: 6px;
					overflow: hidden;
					box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.7);
					width: 100px;
					z-index: 100000;
				">
					${Object.entries(langConfig)
                        .map(([code, { flag, name }]) =>
                            htmlTemplates.langOption(
                                code,
                                flag,
                                name,
                                code === currentLang
                            )
                        )
                        .join('')}
				</div>
			</div>
		`,

        generateDesktopInterface: (
            couleurAccent,
            main,
            board,
            nomFinal,
            conseilFinal,
            outs,
            nbJoueurs,
            winProbability
        ) => `
			<div data-drag-handle style="
				background: linear-gradient(135deg, ${couleurAccent}20, ${couleurAccent}10);
				padding: 16px 20px;
				border-radius: 14px 14px 0 0;
				border-bottom: 1px solid ${couleurAccent}40;
				position: relative;
			">
				<div style="
					display: flex;
					align-items: center;
					gap: 12px;
					margin-bottom: 12px;
				">
					<div style="
						width: 40px;
						height: 40px;
						background: linear-gradient(135deg, ${couleurAccent}, ${couleurAccent}80);
						border-radius: 12px;
						display: flex;
						align-items: center;
						justify-content: center;
						font-size: 20px;
						box-shadow: 0 4px 12px ${couleurAccent}40;
					">🃏</div>
					<div>
						<div style="font-weight: 700; font-size: 16px; color: white;">${t(
                            'assistant'
                        )}</div>
						<div style="font-size: 12px; color: ${couleurAccent}; opacity: 0.8;">${t(
            'helper'
        )}</div>
					</div>
					${htmlTemplates.generateDesktopLangSelector(couleurAccent)}
				</div>
			</div>

			<div style="padding: 20px;">
				${htmlTemplates.desktopCard(
                    t('yourCards'),
                    main.length ? main.join(' • ') : '🎴 ' + t('waiting'),
                    'white',
                    'rgba(255, 255, 255, 0.05)',
                    'data-player-cards'
                )}
				${htmlTemplates.desktopCard(
                    t('board'),
                    board.length ? board.join(' • ') : '🟢 ' + t('empty'),
                    '#10b981',
                    'rgba(16, 185, 129, 0.1)',
                    'data-board-cards'
                )}
				${htmlTemplates.desktopCard(
                    t('combination'),
                    nomFinal || '🔍 ' + t('analyzing'),
                    '#8b5cf6',
                    'linear-gradient(135deg, rgba(139, 92, 246, 0.15), rgba(139, 92, 246, 0.05))',
                    'data-combination'
                )}
				${
                    winProbability > 0
                        ? htmlTemplates.desktopCard(
                              t('winProbability'),
                              `🎯 ${Math.round(winProbability * 100)}%`,
                              '#3b82f6',
                              'linear-gradient(135deg, rgba(59, 130, 246, 0.15), rgba(59, 130, 246, 0.05))',
                              'data-win-probability'
                          )
                        : ''
                }

				<div style="margin-bottom: ${outs ? '16px' : '0'};">
					<div style="
						display: flex;
						align-items: center;
						gap: 8px;
						margin-bottom: 8px;
					">
						<div style="
							width: 6px;
							height: 6px;
							background: ${couleurAccent};
							border-radius: 50%;
							box-shadow: 0 0 8px ${couleurAccent}60;
						"></div>
						<span style="font-weight: 600; font-size: 13px; color: #e2e8f0;">${t(
                            'advice'
                        )}</span>
					</div>
					<div data-advice style="
						background: linear-gradient(135deg, ${couleurAccent}20, ${couleurAccent}10);
						border: 1px solid ${couleurAccent}40;
						border-radius: 8px;
						padding: 12px;
						color: white;
						font-weight: 600;
						font-size: 14px;
						line-height: 1.4;
					">${conseilFinal}</div>
				</div>

				${
                    outs && outs.nombre > 0
                        ? `
				<div style="margin-bottom: 16px;">
					<div style="
						display: flex;
						align-items: center;
						gap: 8px;
						margin-bottom: 8px;
					">
						<div style="
							width: 6px;
							height: 6px;
							background: #f59e0b;
							border-radius: 50%;
							box-shadow: 0 0 8px #f59e0b60;
						"></div>
						<span style="font-weight: 600; font-size: 13px; color: #e2e8f0;">${t(
                            'draws'
                        )}</span>
					</div>
					<div data-outs style="
						background: linear-gradient(135deg, rgba(245, 158, 11, 0.15), rgba(245, 158, 11, 0.05));
						border: 1px solid rgba(245, 158, 11, 0.3);
						border-radius: 8px;
						padding: 12px;
						color: #fbbf24;
						font-weight: 600;
						font-size: 14px;
					">
						${outs.nombre} ${t('outOf')} ${Math.round(outs.probability * 100)}${t(
                              'chanceOf'
                          )}
						<div style="color: #94a3b8; font-size: 12px; line-height: 1.3; margin-top: 4px;">
							${outs.details.slice(0, 3).join(' • ')}${outs.details.length > 3 ? '...' : ''}
						</div>
					</div>
				</div>
				`
                        : ''
                }

				${
                    nbJoueurs > 0
                        ? `
				<div style="
					margin-top: 16px;
					padding-top: 16px;
					border-top: 1px solid rgba(255, 255, 255, 0.1);
				">
					<div style="
						display: flex;
						justify-content: space-between;
						align-items: center;
					">
						<div style="
							display: flex;
							align-items: center;
							gap: 8px;
						">
							<span style="font-size: 16px;">👥</span>
							<span style="color: #94a3b8; font-size: 13px;">${t('activePlayers')}</span>
						</div>
						<div data-active-players style="
							background: rgba(255, 255, 255, 0.1);
							border-radius: 12px;
							padding: 4px 12px;
							font-weight: 700;
							color: white;
							font-size: 13px;
						">${nbJoueurs}</div>
					</div>
				</div>
				`
                        : ''
                }
			</div>
		`,

        generateDesktopLangSelector: (couleurAccent) => `
			<div id="langSelector" style="
				position: absolute;
				top: 16px;
				right: 16px;
				z-index: 2;
			">
				<div id="langButton" style="
					display: flex;
					align-items: center;
					justify-content: center;
					width: 32px;
					height: 32px;
					background: rgba(255, 255, 255, 0.1);
					border-radius: 8px;
					cursor: pointer;
					user-select: none;
					transition: all 0.2s ease;
				">
					<span style="font-size: 16px;">${langConfig[currentLang].flag}</span>
				</div>
				<div id="langOptions" style="
					display: none;
					position: absolute;
					top: 100%;
					right: 0;
					margin-top: 8px;
					background: rgba(15, 23, 42, 0.95);
					backdrop-filter: blur(12px);
					border: 1px solid rgba(255, 255, 255, 0.1);
					border-radius: 8px;
					overflow: hidden;
					box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.7);
					width: 120px;
					z-index: 3;
				">
					${Object.entries(langConfig)
                        .map(
                            ([code, { flag, name }]) => `
						<div class="langOption" data-lang="${code}" style="
							display: flex;
							align-items: center;
							gap: 8px;
							padding: 10px 12px;
							color: ${code === currentLang ? '#60a5fa' : '#e2e8f0'};
							font-weight: ${code === currentLang ? '700' : '500'};
							font-size: 13px;
							cursor: pointer;
							transition: background 0.2s ease;
							${code === currentLang ? 'background: rgba(59, 130, 246, 0.1);' : ''}
						">
							<span style="font-size: 16px;">${flag}</span>
							<span>${name}</span>
						</div>
					`
                        )
                        .join('')}
				</div>
			</div>
		`,
    };

    function updateContentOnly(main, board, box) {
        const isMobile = window.innerWidth <= 768;
        const joueurAFold = detecterSiJoueurAFold();

        const playerCardsElement = box.querySelector('[data-player-cards]');
        if (playerCardsElement) {
            if (isMobile) {
                playerCardsElement.textContent = main.length
                    ? main.join(' ')
                    : t('waiting');
            } else {
                playerCardsElement.textContent = main.length
                    ? main.join(' • ')
                    : '🎴 ' + t('waiting');
            }
        }

        const boardCardsElement = box.querySelector('[data-board-cards]');
        if (boardCardsElement) {
            if (isMobile) {
                boardCardsElement.textContent = board.length
                    ? board.join(' ')
                    : t('empty');
            } else {
                boardCardsElement.textContent = board.length
                    ? board.join(' • ')
                    : '🟢 ' + t('empty');
            }
        }

        const nbJoueurs = compterJoueursActifs();
        const activePlayersElement = box.querySelector('[data-active-players]');
        if (activePlayersElement) {
            activePlayersElement.textContent = nbJoueurs;
        }

        if (joueurAFold) {
            const winProbabilityElement = box.querySelector(
                '[data-win-probability]'
            );
            if (winProbabilityElement) {
                winProbabilityElement.textContent = t('folded');
            }

            const adviceElement = box.querySelector('[data-advice]');
            if (adviceElement) {
                adviceElement.textContent = t('folded');
            }

            const combinationElement = box.querySelector('[data-combination]');
            if (combinationElement) {
                combinationElement.textContent = '';
            }
        } else if (main.length >= 2) {
            const toutesCartes = [...main, ...board];
            const evaluation = evaluerMain(toutesCartes, true);
            const position = detecterPosition();

            let outs = null;
            if (evaluation.tirage && main.length >= 2 && board.length >= 3) {
                outs = calculerOuts(main, board);
            }

            const winProbability = calculerProbabiliteVictoire(
                main,
                board,
                nbJoueurs,
                500
            );
            const nomFinal = expertMode
                ? evaluation.nom
                : simplifierMain(evaluation.nom);
            const conseilFinal = simplifierConseil(
                evaluation.conseil,
                position,
                nbJoueurs,
                evaluation.tirage,
                outs
            );

            const combinationElement = box.querySelector('[data-combination]');
            if (combinationElement) {
                if (isMobile) {
                    combinationElement.textContent = nomFinal || t('analyzing');
                } else {
                    combinationElement.textContent =
                        nomFinal || '🔍 ' + t('analyzing');
                }
            }

            const winProbabilityElement = box.querySelector(
                '[data-win-probability]'
            );
            if (winProbabilityElement) {
                if (isMobile) {
                    winProbabilityElement.textContent = `${Math.round(
                        winProbability * 100
                    )}%`;
                } else {
                    winProbabilityElement.textContent = `🎯 ${Math.round(
                        winProbability * 100
                    )}%`;
                }
            }

            const adviceElement = box.querySelector('[data-advice]');
            if (adviceElement) {
                adviceElement.textContent = conseilFinal;
            }

            const outsElement = box.querySelector('[data-outs]');
            if (outsElement && outs && outs.nombre > 0) {
                outsElement.textContent = `${outs.nombre} ${t(
                    'outOf'
                )} ${Math.round(outs.probability * 100)}${t('chanceOf')}`;
            }
        }
    }

    function extraireValeurEtCouleur(className) {
        const regex = /(clubs|spades|hearts|diamonds)-([0-9TJQKA]+)/;
        const match = className.match(regex);
        if (!match) {
            return null;
        }
        const couleurMap = {
            clubs: '♣',
            spades: '♠',
            hearts: '♥',
            diamonds: '♦',
        };
        const couleur = couleurMap[match[1]];
        const valeur = match[2].toUpperCase();
        return `${valeur}${couleur}`;
    }

    function lireCartesJoueur() {
        const cartes = document.querySelectorAll(
            '.playerMeGateway___AEI5_ .hand___aOp4l .card___t7csZ .front___osz1p > div'
        );
        return Array.from(cartes)
            .map((c) => extraireValeurEtCouleur(c.className))
            .filter(Boolean);
    }

    function lireCartesPlateau() {
        const cartes = document.querySelectorAll(
            '.communityCards___cGHD3 .front___osz1p > div'
        );
        return Array.from(cartes)
            .map((c) => extraireValeurEtCouleur(c.className))
            .filter(Boolean);
    }

    function compterJoueursActifs() {
        let joueursTable = document.querySelectorAll('[class*="opponent___"]');
        if (joueursTable.length === 0) {
            joueursTable = document.querySelectorAll('[id*="player-"]');
        }
        if (joueursTable.length === 0) {
            joueursTable = Array.from(
                document.querySelectorAll('[class*="name___"]')
            )
                .map((nom) =>
                    nom.closest(
                        'div[class*="player"], div[class*="opponent"], div'
                    )
                )
                .filter(Boolean);
        }

        let joueursActifs = 0;

        if (joueursTable.length > 0) {
            joueursTable.forEach((joueur, index) => {
                const nom = joueur.querySelector
                    ? joueur.querySelector('[class*="name___"]')
                    : null;
                const texteComplet = joueur.textContent
                    ? joueur.textContent.toLowerCase()
                    : '';

                const estInactif =
                    texteComplet.includes('sitting out') ||
                    texteComplet.includes('waiting bb') ||
                    texteComplet.includes('waiting') ||
                    texteComplet.includes('folded') ||
                    texteComplet.includes('fold');

                if (!estInactif) {
                    joueursActifs++;
                }
            });
        } else {
            const nomsJoueurs = document.querySelectorAll('[class*="name___"]');

            nomsJoueurs.forEach((nom, index) => {
                let conteneur = nom.parentElement;
                while (
                    conteneur &&
                    !conteneur.textContent.includes('Sitting out') &&
                    !conteneur.textContent.includes('Waiting') &&
                    conteneur.parentElement
                ) {
                    conteneur = conteneur.parentElement;
                }

                const texteComplet = conteneur
                    ? conteneur.textContent.toLowerCase()
                    : '';
                const estInactif =
                    texteComplet.includes('sitting out') ||
                    texteComplet.includes('waiting bb') ||
                    texteComplet.includes('waiting') ||
                    texteComplet.includes('folded') ||
                    texteComplet.includes('fold');

                if (!estInactif) {
                    joueursActifs++;
                }
            });
        }

        let votreStatut = '';

        const scriptStatus =
            document.querySelector('[data-testid="poker-assistant"]')
                ?.textContent ||
            document.querySelector('.advice')?.textContent ||
            document.querySelector('[class*="advice"]')?.textContent ||
            '';

        const votreJoueur = document.querySelector('.playerMeGateway___AEI5_');
        const playerStatus = votreJoueur
            ? votreJoueur.textContent.toLowerCase()
            : '';

        let yourSpecificStatus = '';
        if (votreJoueur) {
            const yourStatusSpan = votreJoueur.querySelector('span');
            yourSpecificStatus = yourStatusSpan
                ? yourStatusSpan.textContent.toLowerCase()
                : '';
        }

        votreStatut = (
            scriptStatus +
            ' ' +
            playerStatus +
            ' ' +
            yourSpecificStatus
        ).toLowerCase();

        const vosCartes = document.querySelectorAll(
            '.playerMeGateway___AEI5_ .hand___aOp4l .card___t7csZ'
        );
        const avezDesCartes = vosCartes.length >= 2;

        const votreZone = document.querySelector('.playerMeGateway___AEI5_');
        const votreZoneText = votreZone
            ? votreZone.textContent.toLowerCase()
            : '';

        let votreZoneComplete = votreZoneText;
        if (votreZone) {
            const spans = votreZone.querySelectorAll('span, div');
            spans.forEach((span) => {
                votreZoneComplete += ' ' + span.textContent.toLowerCase();
            });
        }

        const vousAvezFolde =
            votreZoneComplete.includes('folded') ||
            votreStatut.includes('folded') ||
            votreStatut.includes('fold');

        const vousEtesActif =
            avezDesCartes &&
            !vousAvezFolde &&
            !votreStatut.includes('waiting') &&
            !votreStatut.includes('sitting out');

        if (vousEtesActif) {
            joueursActifs++;
        }

        if (joueursActifs === 0) {
            const positionsAvecCartes = document.querySelectorAll(
                '[class*="hand___"], [class*="card___"]'
            ).length;
            const positionsAvecJetons = document.querySelectorAll(
                '[class*="bet"], [class*="chip"]'
            ).length;

            joueursActifs = Math.max(
                Math.floor(positionsAvecCartes / 2),
                Math.floor(positionsAvecJetons / 2),
                3
            );
        }

        const resultat = Math.max(joueursActifs, 2);

        if (window.lastPlayerCount !== resultat) {
            window.lastPlayerCount = resultat;
        }

        return resultat;
    }

    function detecterSiJoueurAFold() {
        const vosCartes = document.querySelectorAll(
            '.playerMeGateway___AEI5_ .hand___aOp4l .card___t7csZ'
        );
        const avezDesCartes = vosCartes.length >= 2;

        const votreZone = document.querySelector('.playerMeGateway___AEI5_');
        const votreZoneText = votreZone
            ? votreZone.textContent.toLowerCase()
            : '';

        let votreZoneComplete = votreZoneText;
        if (votreZone) {
            const spans = votreZone.querySelectorAll('span, div');
            spans.forEach((span) => {
                votreZoneComplete += ' ' + span.textContent.toLowerCase();
            });
        }

        const votreJoueur = document.querySelector('.playerMeGateway___AEI5_');
        const playerStatus = votreJoueur
            ? votreJoueur.textContent.toLowerCase()
            : '';

        const vousAvezFolde =
            votreZoneComplete.includes('folded') ||
            playerStatus.includes('folded') ||
            playerStatus.includes('fold');

        return vousAvezFolde;
    }

    function detecterPosition() {
        const bouton = document.querySelector('.yourTurn___b2sZp');
        return bouton && bouton.textContent.includes('Your turn');
    }

    function detecterPositionTable() {
        const tousJoueurs = document.querySelectorAll('.player___Z25g2');
        const monIndex = Array.from(tousJoueurs).findIndex((p) =>
            p.classList.contains('playerMeGateway___AEI5_')
        );

        if (monIndex === -1) {
            return 0;
        }

        const totalJoueurs = tousJoueurs.length;
        if (monIndex === totalJoueurs - 1) {
            return 2; // Button/Dealer
        }
        if (monIndex === 0 || monIndex === 1) {
            return 0; // SB/BB
        }
        return 1; // Position médiane
    }

    function simplifierMain(nom) {
        return t(nom.replace(/\s+/g, '').toLowerCase()) || nom;
    }

    function trouverMeilleureMain(toutesCartes) {
        if (toutesCartes.length < 5) {
            return toutesCartes;
        }

        const combinations = [];

        function getCombinations(arr, size) {
            if (size === 1) {
                return arr.map((el) => [el]);
            }
            const result = [];
            arr.forEach((el, i) => {
                const rest = arr.slice(i + 1);
                const combos = getCombinations(rest, size - 1);
                combos.forEach((combo) => {
                    result.push([el, ...combo]);
                });
            });
            return result;
        }

        const combos = getCombinations(toutesCartes, 5);
        let meilleureCombo = combos[0];
        let meilleureEval = evaluerMain5Cartes(combos[0]);

        combos.forEach((combo) => {
            const evaluate = evaluerMain5Cartes(combo);
            if (comparerMains(evaluate, meilleureEval) > 0) {
                meilleureCombo = combo;
                meilleureEval = evaluate;
            }
        });

        return { cartes: meilleureCombo, evaluation: meilleureEval };
    }

    function comparerMains(main1, main2) {
        if (main1.force !== main2.force) {
            return main1.force - main2.force;
        }

        if (main1.valeurPrincipale !== main2.valeurPrincipale) {
            return main1.valeurPrincipale - main2.valeurPrincipale;
        }

        for (
            let i = 0;
            i < Math.max(main1.kickers.length, main2.kickers.length);
            i++
        ) {
            const k1 = main1.kickers[i] || -1;
            const k2 = main2.kickers[i] || -1;
            if (k1 !== k2) {
                return k1 - k2;
            }
        }

        return 0;
    }

    function evaluerMain5Cartes(cartes5) {
        const suits = { '♠': [], '♥': [], '♦': [], '♣': [] };
        const values = {};
        const allVals = [];

        cartes5.forEach((card) => {
            const match = card.match(/^([0-9TJQKA]+)(.)$/);
            if (!match) {
                return;
            }

            const val = match[1];
            const suit = match[2];
            suits[suit].push(val);
            values[val] = (values[val] || 0) + 1;
            allVals.push(val);
        });

        const countList = Object.values(values).sort((a, b) => b - a);
        const allRanks = allVals
            .map((v) => ranks.indexOf(v))
            .sort((a, b) => b - a);

        const flushSuit = Object.entries(suits).find(
            ([_, list]) => list.length === 5
        );
        const isFlush = !!flushSuit;

        const uniqueRanks = [...new Set(allRanks)].sort((a, b) => a - b);
        let straightFound = false;
        let straightHighCard = 0;

        // Vérifier toutes les suites possibles de 5 cartes consécutives
        for (let i = 0; i <= uniqueRanks.length - 5; i++) {
            const seq = uniqueRanks.slice(i, i + 5);
            // Vérifier si c'est une suite (différence de 4 entre la première et dernière carte)
            if (seq[4] - seq[0] === 4) {
                straightFound = true;
                straightHighCard = seq[4];
                break;
            }
        }

        if (!straightFound) {
            // Vérifier la wheel (A-2-3-4-5)
            const wheelRanks = [
                ranks.indexOf('A'),
                ranks.indexOf('2'),
                ranks.indexOf('3'),
                ranks.indexOf('4'),
                ranks.indexOf('5'),
            ];
            const hasWheel = wheelRanks.every((rank) =>
                uniqueRanks.includes(rank)
            );
            if (hasWheel) {
                straightFound = true;
                straightHighCard = ranks.indexOf('5');
            }
        }

        const royalFlush =
            isFlush && straightFound && straightHighCard === ranks.indexOf('A');

        const valeurPair = Object.entries(values)
            .filter(([_, count]) => count === 2)
            .map(([val, _]) => ranks.indexOf(val))
            .sort((a, b) => b - a);

        const valeurBrelan = Object.entries(values)
            .filter(([_, count]) => count === 3)
            .map(([val, _]) => ranks.indexOf(val))[0];

        const valeurCarre = Object.entries(values)
            .filter(([_, count]) => count === 4)
            .map(([val, _]) => ranks.indexOf(val))[0];

        let kickers = [];
        let force = 0;
        let valeurPrincipale = 0;
        let nom = '';

        if (royalFlush) {
            force = 9;
            valeurPrincipale = ranks.indexOf('A');
            nom = 'Royal Flush';
            kickers = [];
        } else if (isFlush && straightFound) {
            force = 8;
            valeurPrincipale = straightHighCard;
            nom = 'Straight Flush';
            kickers = [];
        } else if (countList[0] === 4) {
            force = 7;
            valeurPrincipale = valeurCarre;
            nom = 'Four of a Kind';
            kickers = allRanks.filter((r) => r !== valeurCarre).slice(0, 1);
        } else if (countList[0] === 3 && countList[1] === 2) {
            force = 6;
            valeurPrincipale = valeurBrelan;
            nom = 'Full House';
            kickers = valeurPair.slice(0, 1);
        } else if (isFlush) {
            force = 5;
            nom = 'Flush';
            const flushCards = suits[flushSuit[0]]
                .map((v) => ranks.indexOf(v))
                .sort((a, b) => b - a);
            valeurPrincipale = flushCards[0];
            kickers = flushCards.slice(1, 5);
        } else if (straightFound) {
            force = 4;
            valeurPrincipale = straightHighCard;
            nom = 'Straight';
            kickers = [];
        } else if (countList[0] === 3) {
            force = 3;
            valeurPrincipale = valeurBrelan;
            nom = 'Three of a Kind';
            kickers = allRanks.filter((r) => r !== valeurBrelan).slice(0, 2);
        } else if (countList[0] === 2 && countList[1] === 2) {
            force = 2;
            valeurPrincipale = valeurPair[0];
            nom = 'Two Pair';
            kickers = [
                valeurPair[1],
                ...allRanks.filter((r) => !valeurPair.includes(r)).slice(0, 1),
            ];
        } else if (countList[0] === 2) {
            force = 1;
            valeurPrincipale = valeurPair[0];
            nom = 'One Pair';
            kickers = allRanks.filter((r) => r !== valeurPair[0]).slice(0, 3);
        } else {
            force = 0;
            valeurPrincipale = allRanks[0];
            nom = 'High Card';
            kickers = allRanks.slice(1, 5);
        }

        return {
            nom,
            force,
            valeurPrincipale,
            kickers,
            cartes: cartes5,
        };
    }

    function calculerOuts(main, board) {
        const toutesCartes = [...main, ...board];
        const cartesUtilisees = new Set(toutesCartes);
        const outs = new Set();
        const outDetails = [];

        // Analyser les tirages possibles
        const flushOuts = calculerFlushOuts(main, board, cartesUtilisees);
        const straightOuts = calculerStraightOuts(main, board, cartesUtilisees);

        // Ajouter les outs de flush
        flushOuts.forEach((carte) => {
            outs.add(carte);
            outDetails.push(`${carte} → Flush`);
        });

        // Ajouter les outs de suite
        straightOuts.forEach((carte) => {
            if (!outs.has(carte)) {
                outDetails.push(`${carte} → Straight`);
            }
            outs.add(carte);
        });

        return {
            nombre: outs.size,
            details: outDetails,
            probability: calculerProbabilite(outs.size, board.length),
        };
    }

    function calculerFlushOuts(main, board, cartesUtilisees) {
        const outs = [];
        const toutesCartes = [...main, ...board];

        // Compter les cartes par couleur
        const suits = { '♠': [], '♥': [], '♦': [], '♣': [] };
        toutesCartes.forEach((carte) => {
            const match = carte.match(/^([0-9TJQKA]+)(.)$/);
            if (match) {
                suits[match[2]].push(match[1]);
            }
        });

        // Chercher un tirage couleur (4 cartes de même couleur)
        Object.entries(suits).forEach(([suit, cartes]) => {
            if (cartes.length === 4) {
                // Ajouter toutes les cartes restantes de cette couleur
                const allRanks = '23456789TJQKA'.split('');
                allRanks.forEach((rank) => {
                    const carte = `${rank}${suit}`;
                    if (!cartesUtilisees.has(carte)) {
                        outs.push(carte);
                    }
                });
            }
        });

        return outs;
    }

    function calculerStraightOuts(main, board, cartesUtilisees) {
        const outs = [];
        const toutesCartes = [...main, ...board];

        // Obtenir les rangs uniques
        const rangs = new Set();
        toutesCartes.forEach((carte) => {
            const match = carte.match(/^([0-9TJQKA]+)(.)$/);
            if (match) {
                rangs.add(ranks.indexOf(match[1]));
            }
        });

        const rangsArray = Array.from(rangs).sort((a, b) => a - b);
        const allSuits = ['♠', '♥', '♦', '♣'];

        // Chercher tous les tirages de suite possibles
        // Pour chaque séquence possible de 5 cartes consécutives
        for (let start = 0; start <= ranks.length - 5; start++) {
            const sequence = [
                start,
                start + 1,
                start + 2,
                start + 3,
                start + 4,
            ];

            // Compter combien de cartes de cette séquence on a
            const cartesPresentes = sequence.filter((rang) =>
                rangsArray.includes(rang)
            );

            // Si on a exactement 4 cartes de la séquence
            if (cartesPresentes.length === 4) {
                // Trouver la carte manquante
                const carteManquante = sequence.find(
                    (rang) => !rangsArray.includes(rang)
                );

                // Ajouter toutes les variantes de couleur de cette carte
                allSuits.forEach((suit) => {
                    const carte = `${ranks[carteManquante]}${suit}`;
                    if (!cartesUtilisees.has(carte)) {
                        outs.push(carte);
                    }
                });
            }
        }

        // Cas spécial pour la wheel (A-2-3-4-5)
        const wheelSequence = [
            ranks.indexOf('A'),
            ranks.indexOf('2'),
            ranks.indexOf('3'),
            ranks.indexOf('4'),
            ranks.indexOf('5'),
        ];
        const wheelPresentes = wheelSequence.filter((rang) =>
            rangsArray.includes(rang)
        );

        if (wheelPresentes.length === 4) {
            const wheelManquante = wheelSequence.find(
                (rang) => !rangsArray.includes(rang)
            );
            allSuits.forEach((suit) => {
                const carte = `${ranks[wheelManquante]}${suit}`;
                if (!cartesUtilisees.has(carte)) {
                    outs.push(carte);
                }
            });
        }

        // Cas spécial pour la suite royale (T-J-Q-K-A)
        const royalSequence = [
            ranks.indexOf('T'),
            ranks.indexOf('J'),
            ranks.indexOf('Q'),
            ranks.indexOf('K'),
            ranks.indexOf('A'),
        ];
        const royalPresentes = royalSequence.filter((rang) =>
            rangsArray.includes(rang)
        );

        if (royalPresentes.length === 4) {
            const royalManquante = royalSequence.find(
                (rang) => !rangsArray.includes(rang)
            );
            allSuits.forEach((suit) => {
                const carte = `${ranks[royalManquante]}${suit}`;
                if (!cartesUtilisees.has(carte)) {
                    outs.push(carte);
                }
            });
        }

        return outs;
    }

    function calculerProbabilite(outs, boardSize) {
        // Formules corrigées pour les probabilités de tirage
        if (boardSize === 3) {
            // Flop vers turn et river (2 cartes restantes)
            // Formule: 1 - ((47-outs)/47) * ((46-outs)/46)
            const cartesRestantes = 52 - 5; // 47 cartes (52 - 2 du joueur - 3 du flop)
            return 1 - Math.pow((cartesRestantes - outs) / cartesRestantes, 2);
        } else if (boardSize === 4) {
            // Turn vers river (1 carte restante)
            const cartesRestantes = 52 - 6; // 46 cartes (52 - 2 du joueur - 4 du board)
            return outs / cartesRestantes;
        } else if (boardSize === 0) {
            // Preflop vers river (5 cartes à venir)
            // Approximation simplifiée pour preflop
            const cartesRestantes = 52 - 2; // 50 cartes
            return 1 - Math.pow((cartesRestantes - outs) / cartesRestantes, 5);
        }
        return 0;
    }

    function calculerProbabiliteVictoire(
        main,
        board,
        nbJoueurs = 2,
        simulations = 1000
    ) {
        if (main.length < 2) {
            return 0;
        }

        const cartesUtilisees = new Set([...main, ...board]);
        const cartesRestantes = [];

        // Créer le deck des cartes restantes
        const allRanks = '23456789TJQKA'.split('');
        const allSuits = ['♠', '♥', '♦', '♣'];

        allRanks.forEach((rank) => {
            allSuits.forEach((suit) => {
                const carte = `${rank}${suit}`;
                if (!cartesUtilisees.has(carte)) {
                    cartesRestantes.push(carte);
                }
            });
        });

        let victoires = 0;

        for (let sim = 0; sim < simulations; sim++) {
            // Mélanger les cartes restantes
            const deck = [...cartesRestantes];
            for (let i = deck.length - 1; i > 0; i--) {
                const j = Math.floor(Math.random() * (i + 1));
                [deck[i], deck[j]] = [deck[j], deck[i]];
            }

            // Calculer les cartes nécessaires pour board et adversaires
            const cartesNecessairesBoard = Math.max(0, 5 - board.length);
            const cartesNecessairesAdversaires = (nbJoueurs - 1) * 2;
            const cartesTotalesNecessaires =
                cartesNecessairesBoard + cartesNecessairesAdversaires;

            // Vérifier qu'il y a assez de cartes
            if (deck.length < cartesTotalesNecessaires) {
                continue; // Passer cette simulation
            }

            // Compléter le board si nécessaire
            const boardComplet = [...board];
            for (let i = 0; i < cartesNecessairesBoard; i++) {
                boardComplet.push(deck.pop());
            }

            // Évaluer notre main
            const notreMeilleureMain = trouverMeilleureMain([
                ...main,
                ...boardComplet,
            ]);

            // Simuler les mains des adversaires
            let gagne = true;
            let deckIndex = 0;

            for (let adversaire = 1; adversaire < nbJoueurs; adversaire++) {
                const mainAdversaire = [deck[deckIndex], deck[deckIndex + 1]];
                deckIndex += 2;

                const mainAdversaireComplete = trouverMeilleureMain([
                    ...mainAdversaire,
                    ...boardComplet,
                ]);

                if (
                    comparerMains(
                        mainAdversaireComplete.evaluation,
                        notreMeilleureMain.evaluation
                    ) > 0
                ) {
                    gagne = false;
                    break;
                }
            }

            if (gagne) {
                victoires++;
            }
        }

        return victoires / simulations;
    }

    function analyserTirages(toutesCartes) {
        const suits = { '♠': [], '♥': [], '♦': [], '♣': [] };
        const values = {};
        const allVals = [];

        toutesCartes.forEach((card) => {
            const match = card.match(/^([0-9TJQKA]+)(.)$/);
            if (!match) {
                return;
            }

            const val = match[1];
            const suit = match[2];
            suits[suit].push(val);
            values[val] = (values[val] || 0) + 1;
            allVals.push(val);
        });

        const countList = Object.values(values).sort((a, b) => b - a);
        const allRanks = allVals
            .map((v) => ranks.indexOf(v))
            .sort((a, b) => a - b);
        const uniqueRanks = [...new Set(allRanks)].sort((a, b) => a - b);

        const flushDraw = Object.values(suits).some(
            (list) => list.length === 4
        );
        const doubleTwayFlushDraw =
            Object.values(suits).filter((list) => list.length === 3).length >=
            2;

        let openEndedStraight = false;
        let gutShot = false;

        for (let i = 0; i <= uniqueRanks.length - 4; i++) {
            const seq = uniqueRanks.slice(i, i + 4);
            if (seq[3] - seq[0] === 3) {
                openEndedStraight = true;
                break;
            }
        }

        if (!openEndedStraight) {
            for (let i = 0; i <= uniqueRanks.length - 4; i++) {
                const seq = uniqueRanks.slice(i, i + 4);
                if (seq[3] - seq[0] === 4) {
                    gutShot = true;
                    break;
                }
            }
        }

        const nombrePair =
            countList[0] >= 2
                ? Object.entries(values).filter(([_, count]) => count >= 2)
                      .length
                : 0;
        const doublePair = nombrePair >= 2;

        return {
            flushDraw,
            doubleTwayFlushDraw,
            openEndedStraight,
            gutShot,
            nombrePair,
            doublePair,
            possibleStraight: openEndedStraight || gutShot,
            possibleFlush: flushDraw || doubleTwayFlushDraw,
        };
    }

    function simplifierConseil(conseil, position, joueurs, tirage, outs) {
        if (expertMode) {
            return conseil;
        }

        const positionTable = detecterPositionTable();
        const estEnPosition = positionTable === 2;
        const peuJoueurs = joueurs <= 3;
        const bonneProba = outs && outs.probability > 0.3;

        // Gestion des tirages
        if (conseil.includes('tirage')) {
            if (bonneProba) {
                return t('weakHandDrawTemplate', {
                    probability: Math.round(outs.probability * 100),
                    position: estEnPosition
                        ? t('inPosition')
                        : t('outOfPosition'),
                });
            }
            return t('weakHandFollow');
        }

        // Gestion des conseils forts
        if (conseil === 'All-in') {
            return t('allIn');
        }
        if (conseil === 'RAISE fort') {
            return estEnPosition ? t('raiseStrong') : t('raiseNormal');
        }
        if (conseil === 'RAISE') {
            return estEnPosition ? t('raiseStrong') : t('raiseNormal');
        }
        if (conseil === 'Call') {
            return peuJoueurs && estEnPosition
                ? t('callOrRaise')
                : t('callOnly');
        }
        if (conseil === 'Check / Call') {
            return position ? t('checkInPosition') : t('foldOrCheck');
        }
        if (conseil === 'Fold') {
            return t('fold');
        }

        // Si aucune condition n'est remplie, retourner le conseil traduit ou original
        return conseil;
    }

    function evaluerMainPreflop(main) {
        if (main.length !== 2) {
            return null;
        }

        // Extraire les valeurs et couleurs
        const cartes = main.map((carte) => {
            const match = carte.match(/^([0-9TJQKA]+)(.)$/);
            return {
                valeur: match[1],
                couleur: match[2],
                rang: ranks.indexOf(match[1]),
            };
        });

        const valeur1 = cartes[0].rang;
        const valeur2 = cartes[1].rang;
        const memeCouleur = cartes[0].couleur === cartes[1].couleur;

        // Paire
        if (valeur1 === valeur2) {
            const valeurPaire = Math.max(valeur1, valeur2);

            // Stratégie TAG moderne: plus agressive avec les top pairs
            if (valeurPaire >= ranks.indexOf('A')) {
                // AA
                return {
                    nom: 'One Pair',
                    conseil: 'All-in',
                    force: 8,
                    valeurPrincipale: valeurPaire,
                    tirage: false,
                    kickers: [],
                };
            } else if (valeurPaire >= ranks.indexOf('K')) {
                // KK
                return {
                    nom: 'One Pair',
                    conseil: 'RAISE fort',
                    force: 7,
                    valeurPrincipale: valeurPaire,
                    tirage: false,
                    kickers: [],
                };
            } else if (valeurPaire >= ranks.indexOf('Q')) {
                // QQ
                return {
                    nom: 'One Pair',
                    conseil: 'RAISE fort',
                    force: 6,
                    valeurPrincipale: valeurPaire,
                    tirage: false,
                    kickers: [],
                };
            } else if (valeurPaire >= ranks.indexOf('J')) {
                // JJ
                return {
                    nom: 'One Pair',
                    conseil: 'RAISE fort',
                    force: 6,
                    valeurPrincipale: valeurPaire,
                    tirage: false,
                    kickers: [],
                };
            } else if (valeurPaire >= ranks.indexOf('T')) {
                // TT
                return {
                    nom: 'One Pair',
                    conseil: 'RAISE',
                    force: 5,
                    valeurPrincipale: valeurPaire,
                    tirage: false,
                    kickers: [],
                };
            } else if (valeurPaire >= ranks.indexOf('9')) {
                // 99
                return {
                    nom: 'One Pair',
                    conseil: 'RAISE',
                    force: 4,
                    valeurPrincipale: valeurPaire,
                    tirage: false,
                    kickers: [],
                };
            } else if (valeurPaire >= ranks.indexOf('7')) {
                // 88-77
                return {
                    nom: 'One Pair',
                    conseil: 'Call', // Position dependent
                    force: 3,
                    valeurPrincipale: valeurPaire,
                    tirage: false,
                    kickers: [],
                };
            } else {
                // 66-22 - plus strict
                return {
                    nom: 'One Pair',
                    conseil: 'Call', // En position seulement
                    force: 2,
                    valeurPrincipale: valeurPaire,
                    tirage: false,
                    kickers: [],
                };
            }
        }

        // Cartes non appariées - Stratégie TAG moderne
        const hauteValeur = Math.max(valeur1, valeur2);
        const basseValeur = Math.min(valeur1, valeur2);

        // AK - Main premium absolue
        if (
            hauteValeur >= ranks.indexOf('A') &&
            basseValeur >= ranks.indexOf('K')
        ) {
            return {
                nom: 'High Card',
                conseil: 'RAISE fort',
                force: 7,
                valeurPrincipale: hauteValeur,
                tirage: false,
                kickers: [basseValeur],
            };
        }

        // AQ - Très forte mais pas premium
        if (
            hauteValeur >= ranks.indexOf('A') &&
            basseValeur >= ranks.indexOf('Q')
        ) {
            return {
                nom: 'High Card',
                conseil: 'RAISE',
                force: 5,
                valeurPrincipale: hauteValeur,
                tirage: false,
                kickers: [basseValeur],
            };
        }

        // AJ - Bonne main, position dépendante
        if (
            hauteValeur >= ranks.indexOf('A') &&
            basseValeur >= ranks.indexOf('J')
        ) {
            return {
                nom: 'High Card',
                conseil: memeCouleur ? 'RAISE' : 'Call',
                force: memeCouleur ? 4 : 3,
                valeurPrincipale: hauteValeur,
                tirage: false,
                kickers: [basseValeur],
            };
        }

        // AT - Main marginale, suited only
        if (
            hauteValeur >= ranks.indexOf('A') &&
            basseValeur >= ranks.indexOf('T')
        ) {
            return {
                nom: 'High Card',
                conseil: memeCouleur ? 'Call' : 'Fold',
                force: memeCouleur ? 2 : 0,
                valeurPrincipale: hauteValeur,
                tirage: false,
                kickers: [basseValeur],
            };
        }

        // KQ - Main solide
        if (
            hauteValeur >= ranks.indexOf('K') &&
            basseValeur >= ranks.indexOf('Q')
        ) {
            return {
                nom: 'High Card',
                conseil: memeCouleur ? 'Call' : 'Fold',
                force: memeCouleur ? 3 : 1,
                valeurPrincipale: hauteValeur,
                tirage: false,
                kickers: [basseValeur],
            };
        }

        // Connecteurs assortis 65s+ (pour le potentiel post-flop)
        if (
            memeCouleur &&
            Math.abs(hauteValeur - basseValeur) <= 4 &&
            hauteValeur >= ranks.indexOf('9') &&
            basseValeur >= ranks.indexOf('5')
        ) {
            return {
                nom: 'High Card',
                conseil: 'Call',
                force: 2,
                valeurPrincipale: hauteValeur,
                tirage: true,
                kickers: [basseValeur],
            };
        }

        // Autres mains - fold strict
        return {
            nom: 'High Card',
            conseil: 'Fold',
            force: 0,
            valeurPrincipale: hauteValeur,
            tirage: false,
            kickers: [basseValeur],
        };
    }

    function evaluerMain(toutesCartes, inclureDetails = false) {
        const cacheKey = toutesCartes.join(',');
        if (cache.has(cacheKey)) {
            return cache.get(cacheKey);
        }

        let result;
        if (toutesCartes.length < 5) {
            // Si on est preflop (exactement 2 cartes), utiliser l'évaluation preflop
            if (toutesCartes.length === 2) {
                result = evaluerMainPreflop(toutesCartes);
            } else {
                // Sinon utiliser l'analyse de tirage existante
                const tirage = analyserTirages(toutesCartes);
                const isTirage =
                    tirage.possibleFlush || tirage.possibleStraight;

                if (isTirage) {
                    let detailTirage = '';
                    if (tirage.openEndedStraight) {
                        detailTirage += 'Quinte ouverte (8 outs)';
                    }
                    if (tirage.gutShot && !tirage.openEndedStraight) {
                        detailTirage += 'Gutshot (4 outs)';
                    }
                    if (tirage.flushDraw) {
                        detailTirage +=
                            (detailTirage ? ', ' : '') +
                            'Tirage couleur (9 outs)';
                    }

                    result = {
                        nom: 'High Card',
                        conseil:
                            'Main faible avec tirage' +
                            (detailTirage ? ': ' + detailTirage : ''),
                        force: 0.5,
                        valeurPrincipale: 0,
                        tirage: true,
                        detailTirage,
                        kickers: [],
                    };
                } else {
                    result = {
                        nom: 'High Card',
                        conseil: 'Fold',
                        force: 0,
                        valeurPrincipale: 0,
                        tirage: false,
                        kickers: [],
                    };
                }
            }
        } else {
            const meilleureMain = trouverMeilleureMain(toutesCartes);
            const evaluation = meilleureMain.evaluation;

            const conseilMap = {
                9: 'All-in', // Royal Flush
                8: 'All-in', // Straight Flush
                7: 'All-in', // Four of a Kind
                6: 'RAISE fort', // Full House
                5: 'RAISE fort', // Flush
                4: 'RAISE fort', // Straight
                3: 'RAISE', // Three of a Kind
                2: 'Call', // Two Pair
                1: 'Check / Call', // One Pair
                0: 'Fold', // High Card
            };

            let conseil = 'Fold';
            const forces = Object.keys(conseilMap)
                .map((k) => parseInt(k))
                .sort((a, b) => b - a);
            for (const minForce of forces) {
                if (evaluation.force >= minForce) {
                    conseil = conseilMap[minForce];
                    break;
                }
            }

            result = {
                nom: evaluation.nom,
                conseil,
                force: evaluation.force,
                valeurPrincipale: evaluation.valeurPrincipale,
                tirage: false,
                kickers: evaluation.kickers,
            };
        }

        cache.set(cacheKey, result);
        if (cache.size > 100) {
            const firstKey = cache.keys().next().value;
            cache.delete(firstKey);
        }

        return result;
    }

    const getThemeColors = (force) => {
        const themes = {
            9: {
                accent: '#dc2626',
                fond: 'rgba(127, 29, 29, 0.95)',
                bordure: '#dc2626',
            },
            8: {
                accent: '#dc2626',
                fond: 'rgba(127, 29, 29, 0.95)',
                bordure: '#dc2626',
            },
            7: {
                accent: '#dc2626',
                fond: 'rgba(127, 29, 29, 0.95)',
                bordure: '#dc2626',
            },
            6: {
                accent: '#ea580c',
                fond: 'rgba(124, 45, 18, 0.95)',
                bordure: '#ea580c',
            },
            5: {
                accent: '#f59e0b',
                fond: 'rgba(120, 53, 15, 0.95)',
                bordure: '#f59e0b',
            },
            4: {
                accent: '#f59e0b',
                fond: 'rgba(120, 53, 15, 0.95)',
                bordure: '#f59e0b',
            },
            3: {
                accent: '#ca8a04',
                fond: 'rgba(113, 63, 18, 0.95)',
                bordure: '#ca8a04',
            },
            2: {
                accent: '#10b981',
                fond: 'rgba(6, 95, 70, 0.95)',
                bordure: '#10b981',
            },
            1: {
                accent: '#059669',
                fond: 'rgba(6, 78, 59, 0.95)',
                bordure: '#059669',
            },
            0: {
                accent: '#6b7280',
                fond: 'rgba(15, 23, 42, 0.95)',
                bordure: '#374151',
            },
        };

        for (const [minForce, theme] of Object.entries(themes)) {
            if (force >= parseInt(minForce)) {
                return theme;
            }
        }
        return themes[0];
    };

    const langConfig = {
        en: { flag: '🇬🇧', name: 'English' },
        fr: { flag: '🇫🇷', name: 'Français' },
        de: { flag: '🇩🇪', name: 'Deutsch' },
        es: { flag: '🇪🇸', name: 'Español' },
    };

    function afficherInfos(main, board) {
        const nbJoueurs = compterJoueursActifs();
        const joueurAFold = detecterSiJoueurAFold();
        const gameStateKey = `${main.join(',')}-${board.join(
            ','
        )}-${currentLang}-${isMobileMode}-${isMinimized}-${mobilePosition}-${nbJoueurs}-${joueurAFold}`;

        if (lastGameState === gameStateKey) {
            return;
        }

        let box = document.getElementById('mainPokerBox');
        if (!box) {
            box = document.createElement('div');
            box.id = 'mainPokerBox';
            document.body.appendChild(box);
        }

        const langOptions = document.getElementById('langOptions');
        const dropdownIsOpen =
            langOptions && langOptions.style.display === 'block';

        if (dropdownIsOpen && box.innerHTML) {
            updateContentOnly(main, board, box);
            return;
        }

        lastGameState = gameStateKey;

        let evaluation, winProbability, nomFinal, conseilFinal, outs;

        if (joueurAFold) {
            evaluation = {
                nom: '',
                conseil: t('folded'),
                tirage: false,
                force: 0,
            };
            winProbability = 0;
            nomFinal = '';
            conseilFinal = t('folded');
            outs = null;
        } else {
            evaluation =
                main.length < 2
                    ? {
                          nom: '',
                          conseil: t('waiting'),
                          tirage: false,
                          force: 0,
                      }
                    : evaluerMain([...main, ...board], true);

            winProbability =
                main.length >= 2
                    ? calculerProbabiliteVictoire(main, board, nbJoueurs, 500)
                    : 0;

            nomFinal = expertMode
                ? evaluation.nom
                : simplifierMain(evaluation.nom);

            // Calculer les outs AVANT simplifierConseil pour les tirages
            const outs =
                !joueurAFold &&
                evaluation.tirage &&
                main.length >= 2 &&
                board.length >= 3
                    ? calculerOuts(main, board)
                    : null;

            conseilFinal = simplifierConseil(
                evaluation.conseil,
                detecterPosition(),
                nbJoueurs,
                evaluation.tirage,
                outs
            );
        }

        const {
            accent: couleurAccent,
            fond: couleurFond,
            bordure: couleurBordure,
        } = getThemeColors(evaluation.force);

        detectMobileMode();
        box.style.cssText = `
			position: fixed;
			${
                isMobileMode
                    ? getPositionMobileStyles()
                    : `top: ${currentPosition.y}px; left: ${currentPosition.x}px;`
            }
			width: ${isMobileMode ? (isMinimized ? '40px' : '220px') : '350px'};
			background: ${couleurFond};
			backdrop-filter: blur(12px);
			border: ${isMobileMode ? '1px' : '2px'} solid ${couleurBordure};
			border-radius: ${isMobileMode ? '8px' : '16px'};
			padding: 0;
			font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif;
			font-size: ${isMobileMode ? '12px' : '14px'};
			color: white;
			z-index: 99999;
			box-shadow: 0 8px 20px -4px rgba(0, 0, 0, 0.6);
			transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
		`;

        if (isMobileMode) {
            box.innerHTML = htmlTemplates.generateMobileInterface(
                couleurAccent,
                main,
                board,
                nomFinal,
                conseilFinal,
                outs,
                nbJoueurs,
                isMinimized,
                winProbability
            );
        } else {
            box.innerHTML = htmlTemplates.generateDesktopInterface(
                couleurAccent,
                main,
                board,
                nomFinal,
                conseilFinal,
                outs,
                nbJoueurs,
                winProbability
            );
        }

        if (!box.dataset.animated) {
            box.style.transform = 'translateX(100%) scale(0.8)';
            box.style.opacity = '0';

            setTimeout(() => {
                box.style.transform = 'translateX(0) scale(1)';
                box.style.opacity = '1';
            }, 100);

            box.dataset.animated = 'true';
        }

        const activePlayersElement = box.querySelector('[data-active-players]');
        if (activePlayersElement) {
            activePlayersElement.textContent = nbJoueurs;
        }

        rendreModaleDraggable(box);
        eventHandlers.setupUIEvents(box);
    }

    let isDragging = false;
    const dragOffset = { x: 0, y: 0 };
    const currentPosition = { x: 20, y: 20 };

    let tapCount = 0;
    let tapTimer = null;

    const eventHandlers = {
        setupUIEvents: (box) => {
            setTimeout(() => {
                const elements = {
                    langButton: document.getElementById('langButton'),
                    langOptions: document.getElementById('langOptions'),
                    toggleMinimize: document.getElementById('toggleMinimize'),
                    positionButton: document.getElementById('positionButton'),
                };

                if (elements.toggleMinimize) {
                    elements.toggleMinimize.addEventListener('click', (e) => {
                        e.stopPropagation();
                        eventHandlers.handleToggleMinimize();
                    });
                }

                if (elements.positionButton && isMobileMode) {
                    elements.positionButton.addEventListener('click', (e) => {
                        e.stopPropagation();
                        changerPositionMobile();
                    });
                }

                if (elements.langButton && elements.langOptions) {
                    eventHandlers.setupLanguageSelector(
                        elements.langButton,
                        elements.langOptions
                    );
                }
            }, 100);
        },

        handleToggleMinimize: () => {
            if (isMobileMode && isMinimized) {
                tapCount++;
                if (tapCount === 1) {
                    tapTimer = setTimeout(() => {
                        isMinimized = false;
                        localStorage.setItem('tornPokerMinimized', isMinimized);
                        eventHandlers.refreshInterface();
                        tapCount = 0;
                    }, 300);
                } else if (tapCount === 2) {
                    clearTimeout(tapTimer);
                    changerPositionMobile();
                    tapCount = 0;
                }
            } else {
                isMinimized = !isMinimized;
                localStorage.setItem('tornPokerMinimized', isMinimized);
                eventHandlers.refreshInterface();
            }
        },

        setupLanguageSelector: (langButton, langOptions) => {
            const newLangButton = langButton.cloneNode(true);
            langButton.parentNode.replaceChild(newLangButton, langButton);

            newLangButton.addEventListener('click', (e) => {
                e.stopPropagation();
                const isDisplayed = langOptions.style.display === 'block';
                langOptions.style.display = isDisplayed ? 'none' : 'block';
            });

            const closeDropdown = (e) => {
                if (!e.target.closest('#langSelector')) {
                    langOptions.style.display = 'none';
                }
            };

            document.removeEventListener('click', closeDropdown);
            document.addEventListener('click', closeDropdown);

            langOptions.addEventListener('click', (e) => e.stopPropagation());

            setTimeout(() => {
                document.querySelectorAll('.langOption').forEach((option) => {
                    const newOption = option.cloneNode(true);
                    option.parentNode.replaceChild(newOption, option);

                    newOption.addEventListener('click', (e) => {
                        e.stopPropagation();
                        const lang = newOption.getAttribute('data-lang');
                        changerLangue(lang);
                        langOptions.style.display = 'none';
                    });

                    newOption.addEventListener('mouseover', () => {
                        if (
                            newOption.getAttribute('data-lang') !== currentLang
                        ) {
                            newOption.style.background =
                                'rgba(255, 255, 255, 0.05)';
                        }
                    });

                    newOption.addEventListener('mouseout', () => {
                        if (
                            newOption.getAttribute('data-lang') !== currentLang
                        ) {
                            newOption.style.background = 'transparent';
                        }
                    });
                });
            }, 50);
        },

        refreshInterface: () => {
            const main = lireCartesJoueur();
            const board = lireCartesPlateau();
            afficherInfos(main, board);
        },
    };

    function rendreModaleDraggable(box) {
        if (isMobileMode) {
            return;
        }

        const header = box.querySelector('[data-drag-handle]');
        if (!header) {
            return;
        }

        header.style.cursor = 'move';
        header.style.userSelect = 'none';

        header.addEventListener('mousedown', function (e) {
            if (
                e.target.closest('#langButton') ||
                e.target.closest('#langOptions')
            ) {
                return;
            }

            isDragging = true;
            const rect = box.getBoundingClientRect();
            dragOffset.x = e.clientX - rect.left;
            dragOffset.y = e.clientY - rect.top;

            box.style.transition = 'none';

            e.preventDefault();
        });

        document.addEventListener('mousemove', function (e) {
            if (!isDragging || isMobileMode) {
                return;
            }

            const newX = e.clientX - dragOffset.x;
            const newY = e.clientY - dragOffset.y;

            const maxX = window.innerWidth - box.offsetWidth;
            const maxY = window.innerHeight - box.offsetHeight;

            currentPosition.x = Math.max(0, Math.min(newX, maxX));
            currentPosition.y = Math.max(0, Math.min(newY, maxY));

            box.style.left = currentPosition.x + 'px';
            box.style.top = currentPosition.y + 'px';
            box.style.right = 'auto';
            box.style.bottom = 'auto';
        });

        document.addEventListener('mouseup', function () {
            if (isDragging) {
                isDragging = false;
                box.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)';
            }
        });
    }

    function ajouterStylesGlobaux() {
        if (document.getElementById('pokerHelperStyles')) {
            return;
        }

        const styles = document.createElement('style');
        styles.id = 'pokerHelperStyles';
        styles.textContent = `
			#mainPokerBox {
				transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
			}

			#mainPokerBox:hover {
				transform: translateY(-2px) !important;
			}

			#langButton:hover {
				background: rgba(255, 255, 255, 0.2) !important;
				transform: scale(1.05) !important;
			}

			.langOption:hover {
				background: rgba(255, 255, 255, 0.05) !important;
			}

			[data-drag-handle] {
				cursor: move !important;
			}

			[data-drag-handle]:active {
				cursor: grabbing !important;
			}

			@keyframes pulse {
				0%, 100% { opacity: 1; }
				50% { opacity: 0.7; }
			}

			@keyframes slideIn {
				from {
					transform: translateX(100%) scale(0.8);
					opacity: 0;
				}
				to {
					transform: translateX(0) scale(1);
					opacity: 1;
				}
			}

			@media (max-width: 768px) {
				#mainPokerBox {
                    font-size: 11px !important;
				}

				[data-drag-handle] {
					cursor: default !important;
				}
			}
		`;
        document.head.appendChild(styles);
    }

    const gameLoop = {
        isRunning: false,
        intervalId: null,
        lastPlayerCount: null,

        start: () => {
            if (gameLoop.isRunning) {
                return;
            }

            ajouterStylesGlobaux();
            detectMobileMode();
            gameLoop.isRunning = true;

            gameLoop.intervalId = setInterval(() => {
                const currentPlayerCount = compterJoueursActifs();
                if (gameLoop.lastPlayerCount !== currentPlayerCount) {
                    gameLoop.lastPlayerCount = currentPlayerCount;
                    cache.clear();
                    eventHandlers.refreshInterface();
                }

                const mainCards = document.querySelectorAll(
                    '.playerMeGateway___AEI5_ .hand___aOp4l .card___t7csZ .front___osz1p > div'
                );
                if (mainCards.length >= 2) {
                    eventHandlers.refreshInterface();
                }
            }, 1000);
        },

        stop: () => {
            if (gameLoop.intervalId) {
                clearInterval(gameLoop.intervalId);
                gameLoop.intervalId = null;
                gameLoop.isRunning = false;
            }
        },
    };

    function attendreEtExecuter() {
        gameLoop.start();
    }
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', attendreEtExecuter);
    } else {
        attendreEtExecuter();
    }

    window.addEventListener('load', attendreEtExecuter);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址