{% comment %} Server-driven modal. `is_open` comes from the host LiveView's `Modal` descriptor, and the close control dispatches `toggle_modal`. Visibility is an inline `display`, and it was forced to be: `.modal-backdrop` is `display: flex` in BOTH `theming/css/components.css` and `scaffold.css`, and an author rule beats the UA's `[hidden] { display: none }`, so `hidden` here would have rendered the dialog permanently visible. `components.css` now carries a `[hidden]` guard with `!important` (#3290), so the attribute would work for a page that links it. The inline style stays anyway: it is what the retired JS did, and it keeps working for a page that loads `scaffold.css` without `components.css`. Escape-to-close now works through the framework rather than `components.js`: `51-keyboard-nav.js:_closeModal` locates a dialog's close control with `[dj-click]` and dispatches it, which this button carries. Focus trapping and `aria-modal` come from the same module. `data-theme-modal` / `data-theme-modal-close` below are the client fallback, and they are load-bearing for plain pages: `components.js` finds the backdrop with `[data-theme-modal=""]`, so removing them (as a first pass at this did) leaves the theming gallery's triggers pointing at nothing. LiveView pages never use them — the guard in `components.js` stands down when a djust mount root is present. One behaviour is deliberately dropped: click-the-backdrop-to-close. It cannot be expressed with a plain `dj-click` on the backdrop, because the event bubbles — clicking anywhere inside the dialog would close it. There is no `dj-self` modifier in the client to guard it. The close button and Escape both still work. Restoring it needs either that modifier or a sibling scrim element positioned behind the dialog, which is a markup change worth making on purpose rather than as a side effect of this one. {% endcomment %}