import html as html_lib from .visible_attrs import _visible_attrs from .style_string import _style_string from .render_children import _render_children def _render_overlay(el, meta, slug, children_map=None, ctx=None, parent_flex_direction=None): """3.4 (Confort) — overlay/modale réutilisable : une boîte de dialogue prête à l'emploi, par-dessus TOUT le reste de l'écran, fermeture manuelle uniquement (aucun clic-en-dehors-pour-fermer volontairement, conformément au manque documenté). Contrairement aux autres widgets, sa position ne dépend PAS de x/y/width/height (glissé-déposé sur le canevas) : `position:fixed; inset:0` la fait toujours couvrir tout l'écran, quel que soit l'endroit où elle a été posée dans l'éditeur — seul un voile semi-transparent + une boîte centrée, contenant les éléments posés à l'intérieur (comme un conteneur normal). Ouverture/fermeture : PAS de mécanisme dédié — elle réutilise l'action existante "Modifier un élément → Visibilité" (masquer/rendre visible), exactement comme n'importe quel autre élément. C'est pour ça qu'on fusionne le style de positionnement fixe ci-dessous AVEC le style normal de l'élément (_style_string) : si l'élément est réglé "Masqué" dans ses propriétés, ou si une action "Modifier un élément" le cache plus tard, ce masquage continue de fonctionner normalement. Classes Bulma ("modal is-active" / "box") posées en PLUS du style inline existant, jamais à sa place : tout le positionnement/masquage critique (position:fixed, z-index, display) reste en inline, qui gagne toujours sur une règle de classe — si Bulma (chargé depuis un CDN, voir play.html) ne se charge pas (hors-ligne), la boîte de dialogue continue de fonctionner exactement pareil, ces classes n'ajoutant qu'un habillage visuel (ombre, base de police) qui se dégrade sans casser quoi que ce soit. Pas de ".modal-background" séparé : le voile semi-transparent est déjà posé en inline sur cette même balise (background:rgba(...)) — un second calque tout aussi transparent par-dessus n'ajouterait rien.""" attrs_raw = el.get("attributes") or {} box_color = attrs_raw.get("_couleur_boite") or "#1f2430" radius = attrs_raw.get("_arrondi") or "12" attrs = _visible_attrs(el, meta, ctx) base_overlay_style = ( "position:fixed; inset:0; z-index:9999; display:flex; " "align-items:center; justify-content:center; background:rgba(0,0,0,0.6);" ) style = base_overlay_style + " " + _style_string(el, parent_flex_direction=parent_flex_direction) if not (ctx and ctx.get("_forge_play_mode")): # Dans l'ÉDITEUR (ctx sans _forge_play_mode — voir list_elements.py, # posé uniquement en mode JOUABLE), ce widget doit rester visible # quel que soit son réglage de visibilité statique — "Masqué" par # défaut à SA création (default_style_for_widget.py), pour ne pas # couvrir tout l'écran dès qu'on le pose. Sans ce forçage, la boîte # de dialogue reste display:none dans le canevas de l'éditeur, donc # invisible dès sa création : impossible d'y voir/positionner son # contenu tant qu'on n'a pas basculé "Visibilité" sur "Visible" à la # main (puis pensé à la remettre sur "Masqué" avant de tester). Le # "display:flex;" ajouté ICI, en dernier dans la chaîne de style, # gagne sur le "display:none" éventuellement posé plus tôt par # _style_string (CSS : même propriété déclarée deux fois -> la # dernière l'emporte). Seul le mode JOUABLE respecte réellement ce # réglage (ou une action "Modifier un élément → Visibilité" qui le # change en cours de partie).""" style += " display:flex;" attr_parts = [f'style="{html_lib.escape(style)}"'] for k, v in attrs.items(): if v in (None, "", False): continue attr_parts.append( html_lib.escape(str(k)) if v is True else f'{html_lib.escape(str(k))}="{html_lib.escape(str(v))}"' ) box_style = ( f"background:{html_lib.escape(str(box_color))}; border-radius:{html_lib.escape(str(radius))}px; " # max-width en min(...) plutôt qu'un simple pourcentage : sur un # écran de jeu large (desktop), "90%" seul donnait une boîte étirée # bord à bord peu lisible comme dialogue — 560px reste une largeur # de boîte de dialogue confortable, tout en retombant sur 90% sur un # écran de jeu étroit (mobile/portrait) pour ne jamais déborder. # color:#e8eaf0 : la classe Bulma ".box" (ajoutée ci-dessous) impose # elle-même une couleur de texte SOMBRE (pensée pour un fond blanc # par défaut) — comme aucun widget ne fige de couleur de texte à sa # création (default_style_for_widget.py), un titre/texte posé dans # la boîte SANS couleur personnalisée héritait de ce gris sombre # imposé par Bulma, invisible sur le fond sombre par défaut de cette # boîte de dialogue (texte "présent mais invisible", pas de bug côté # utilisateur). On redonne donc ici une couleur claire par défaut, # que Bulma ne peut plus écraser (élément le plus proche gagne) — # un texte/titre qui personnalise sa propre couleur reste bien sûr # prioritaire sur celle-ci. "color:#e8eaf0; padding:24px; width:100%; max-width:min(560px, 90%); max-height:90%; overflow:auto; box-sizing:border-box;" ) child_html = _render_children(el, slug, children_map, ctx) return ( f'