Cause : this.selectedEventCard gardait une référence DIRECTE vers un objet
Phaser (ItemBoardToken), régulièrement détruit et recréé par
_refreshEventHandAffordability()/_buildEventHand() à chaque game-state.
Cette référence devenait alors obsolète (pointant vers un objet détruit),
et l'état de verrouillage "carte en cours de jeu" était géré par deux
chemins de mutation distincts (reconstruction de la main basée sur
myEventHand seul, ET synchronisation séparée sur pendingEventPlayId) qui
pouvaient se désynchroniser selon l'ordre exact des événements réseau :
une carte déjà envoyée au serveur (play-event émis) pouvait alors
réapparaître visuellement "jouable" dans la main après une reconstruction
intermédiaire qui ignorait le verrouillage réel.
Fix : refactor complet du pilotage de la main d'événements côté GameScene :
- this.selectedEventCard (référence Phaser) remplacé par
this.selectedEventId (simple eventId, jamais périmé même après
destruction/recréation des jetons).
- Fusion de _buildEventHand + _refreshEventHandAffordability en une seule
fonction _renderEventHand(eventIds), SEULE responsable de construire
this.eventCards — élimine le second chemin de mutation qui pouvait
diverger.
- Dans le listener 'game-state', selectedEventId est désormais TOUJOURS
resynchronisé sur state.pendingEventPlayId (source de vérité serveur)
AVANT de décider si la main doit être reconstruite, et la clé de diff
inclut maintenant ce verrouillage en plus de la composition de la main —
auparavant, un changement de pendingEventPlayId seul (main inchangée) ne
déclenchait aucune reconstruction, laissant l'ancien état affiché.
- _cancelTargeting() reconstruit désormais aussi la main pour lever tout
verrouillage visuel resté affiché après une annulation.
Fix connexe dans ItemBoardToken.destroy() : le minuteur d'OUVERTURE
(_showTimer) n'était jamais annulé à la destruction (seul _hideTimer
l'était) — un jeton détruit pendant qu'un survol venait de démarrer
pouvait déclencher _showExpanded() sur un objet déjà détruit une fois le
délai écoulé, une source de bug supplémentaire pour des cartes "fantômes".
54 tests unitaires client + 166 tests unitaires serveur toujours au vert.