diff --git a/templates/play.html b/templates/play.html
index 1fce822e..f6945494 100644
--- a/templates/play.html
+++ b/templates/play.html
@@ -411,21 +411,39 @@
screensData = gameData.screens;
const screenData = screensData.find(s => s.id === window.currentScreenId);
const screenDiv = document.querySelector('.playScreen[data-screen-id="' + window.currentScreenId + '"]');
- if (!screenData || !screenDiv) return;
- screenData.elements.filter(function(e){ return !e.parent_id; }).forEach(function(el) {
- if (!el.rendered_html) return;
- // "repeaterItem" (liste de données), "jaugeBar" (2.1 — jauge liée
- // à une donnée) et "visibilityGated" (condition de visibilité —
- // voir render_element_html.py) sont les types d'éléments dont le
- // contenu/l'affichage dépend de la donnée elle-même plutôt que
- // d'une action "Modifier un élément" posée à la main dans le
- // graphe — eux seuls doivent être régénérés après un changement
- // de donnée ou de variable.
- if (el.rendered_html.indexOf('repeaterItem') === -1 && el.rendered_html.indexOf('jaugeBar') === -1 && el.rendered_html.indexOf('visibilityGated') === -1) return;
- const wrapper = screenDiv.querySelector('.playElement[data-el-id="' + el.id + '"] .playElementInner');
- if (wrapper) wrapper.innerHTML = el.rendered_html;
- });
- applyOpenRowBindings();
+ // Le bloc ci-dessous (régénération du contenu de l'écran courant)
+ // est sauté si l'écran n'est pas trouvé, mais bindClicks() et les
+ // autres réattachements juste après ne doivent JAMAIS dépendre de
+ // cette condition : un retour anticipé ici a déjà laissé, dans la
+ // pratique, un Répéteur fraîchement régénéré sans AUCUN gestionnaire
+ // de clic pour le reste de la partie (plus aucune ligne ne
+ // répondait, silencieusement, sans erreur) — ces fonctions sont sans
+ // risque à rappeler même quand rien n'a changé.
+ if (screenData && screenDiv) {
+ // try/catch : une erreur inattendue pendant la régénération (ex.
+ // structure de données imprévue) ne doit jamais empêcher les
+ // réattachements ci-dessous de s'exécuter — sinon le Répéteur (ou
+ // tout autre élément cliquable) reste silencieusement inerte pour
+ // le reste de la partie, sans le moindre message d'erreur visible.
+ try {
+ screenData.elements.filter(function(e){ return !e.parent_id; }).forEach(function(el) {
+ if (!el.rendered_html) return;
+ // "repeaterItem" (liste de données), "jaugeBar" (2.1 — jauge liée
+ // à une donnée) et "visibilityGated" (condition de visibilité —
+ // voir render_element_html.py) sont les types d'éléments dont le
+ // contenu/l'affichage dépend de la donnée elle-même plutôt que
+ // d'une action "Modifier un élément" posée à la main dans le
+ // graphe — eux seuls doivent être régénérés après un changement
+ // de donnée ou de variable.
+ if (el.rendered_html.indexOf('repeaterItem') === -1 && el.rendered_html.indexOf('jaugeBar') === -1 && el.rendered_html.indexOf('visibilityGated') === -1) return;
+ const wrapper = screenDiv.querySelector('.playElement[data-el-id="' + el.id + '"] .playElementInner');
+ if (wrapper) wrapper.innerHTML = el.rendered_html;
+ });
+ applyOpenRowBindings();
+ } catch (err) {
+ console.error('refreshRuntimeData: erreur pendant la régénération de l\'écran', err);
+ }
+ }
bindClicks();
bindHoverTexts();
bindHoverTriggers();