Torn Poker Helper

Clean and simple poker helper for Torn City

当前为 2025-06-06 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Torn Poker Helper
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Clean and simple poker helper for Torn City
// @author       JESUUS [2353554]
// @match        https://www.torn.com/*
// @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",
							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",
							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",
							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",
							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) => {
				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')}
							<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) => `
				<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')}
					
					<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 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 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');
				}
			}
			if (main.length >= 2) {
				const toutesCartes = [...main, ...board];
				const evaluation = evaluerMain(toutesCartes, true);
				const position = detecterPosition();
				const nbJoueurs = compterJoueursActifs();
				
				let outs = null;
				if (evaluation.tirage && main.length >= 2 && board.length >= 3) {
					outs = calculerOuts(main, board);
				}

							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 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() {
			const joueurs = document.querySelectorAll('.playerStatus___hZ2fu');
			return Array.from(joueurs).filter(j => !j.textContent.includes('Fold')).length;
		}

		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) => b - a);
			let straightFound = false;
			let straightHighCard = 0;

			for (let i = 0; i <= uniqueRanks.length - 5; i++) {
				const seq = uniqueRanks.slice(i, i + 5).sort((a, b) => a - b);
				if (seq[4] - seq[0] === 4) {
					straightFound = true;
					straightHighCard = seq[4];
					break;
				}
			}

			if (!straightFound) {
				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 = [];
			const outDetails = [];

			const allRanks = "23456789TJQKA".split('');
			const allSuits = ['♠', '♥', '♦', '♣'];

			const toutesCartesPossibles = [];
			allRanks.forEach(rank => {
				allSuits.forEach(suit => {
					toutesCartesPossibles.push(`${rank}${suit}`);
				});
			});

			const meilleureMainActuelle = trouverMeilleureMain(toutesCartes);

			toutesCartesPossibles.forEach(carte => {
				if (cartesUtilisees.has(carte)) {
					return;
				}

				const mainTest = [...toutesCartes, carte];
				const meilleureMainTest = trouverMeilleureMain(mainTest);

				if (comparerMains(meilleureMainTest.evaluation, meilleureMainActuelle.evaluation) > 0) {
					outs.push(carte);
					outDetails.push(`${carte} → ${meilleureMainTest.evaluation.nom}`);
				}
			});

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

		function calculerProbabilite(outs, boardSize) {
			if (boardSize === 0) {
				return 1 - Math.pow((52 - outs - 2) / (52 - 2), 3);
			} else if (boardSize === 3) {
				return 1 - Math.pow((52 - outs - 5) / (52 - 5), 2);
			} else if (boardSize === 4) {
				return outs / (52 - 6);
			}
			return 0;
		}

		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;
			}

			// Si c'est le message d'attente, on le retourne tel quel
			if (conseil === t('waiting')) {
				return conseil;
			}

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

			if (conseil.includes("tirage")) {
				if (bonneProba) {
					return t('weakHandDrawTemplate', {
						probability: Math.round(outs.probability*100),
						position: estEnPosition ? t('inPosition') : t('outOfPosition')
					});
				}
				return t('weakHandFollow');
			}
			if (conseil.includes("All-in") || conseil.includes("RAISE fort")) {
				return t('allIn');
			}
			if (conseil.includes("RAISE")) {
				return estEnPosition ? t('raiseStrong') : t('raiseNormal');
			}
			if (conseil.includes("Call")) {
				return peuJoueurs && estEnPosition ? t('callOrRaise') : t('callOnly');
			}
			if (conseil.includes("Check")) {
				return position ? t('checkInPosition') : t('foldOrCheck');
			}
			return t('fold');
		}

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

			let result;
			if (toutesCartes.length < 5) {
				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 = {
					7: "All-in",
					5: "RAISE fort", 
					3: "RAISE",
					2: "Call",
					1: "Check / Call",
					0: "Fold"
				};

				let conseil = "Fold";
				for (const [minForce, conseilText] of Object.entries(conseilMap)) {
					if (evaluation.force >= parseInt(minForce)) {
						conseil = conseilText;
						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 = {
				7: { accent: '#dc2626', fond: 'rgba(127, 29, 29, 0.95)', bordure: '#dc2626' },
				5: { accent: '#ea580c', fond: 'rgba(124, 45, 18, 0.95)', bordure: '#ea580c' },
				3: { accent: '#ca8a04', fond: 'rgba(113, 63, 18, 0.95)', bordure: '#ca8a04' },
				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 gameStateKey = `${main.join(',')}-${board.join(',')}-${currentLang}-${isMobileMode}-${isMinimized}-${mobilePosition}`;
			
			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;

			const evaluation = main.length < 2 
				? { nom: "", conseil: t('waiting'), tirage: false, force: 0 }
				: evaluerMain([...main, ...board], true);

			const outs = evaluation.tirage && main.length >= 2 && board.length >= 3 
				? calculerOuts(main, board) 
				: null;

			const nomFinal = expertMode ? evaluation.nom : simplifierMain(evaluation.nom);
			const conseilFinal = simplifierConseil(
				evaluation.conseil, 
				detecterPosition(), 
				compterJoueursActifs(), 
				evaluation.tirage, 
				outs
			);

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

					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
				);
					} else {
			box.innerHTML = htmlTemplates.generateDesktopInterface(
				couleurAccent, main, board, nomFinal, conseilFinal, outs, nbJoueurs
			);
							}

			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';
			}

			rendreModaleDraggable(box);
			setTimeout(() => eventHandlers.setupUIEvents(box), 100);
		}

		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) => {
				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);
				}
			},

			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) => {
				langButton.addEventListener('click', (e) => {
					e.stopPropagation();
					const isDisplayed = langOptions.style.display === 'block';
					langOptions.style.display = isDisplayed ? 'none' : 'block';
				});

				document.addEventListener('click', (e) => {
					if (!e.target.closest('#langSelector')) {
						langOptions.style.display = 'none';
					}
				});

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

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

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

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

			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,

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

				gameLoop.intervalId = setInterval(() => {
					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);
	})();