diff --git a/internal/loki/ui/index.html b/internal/loki/ui/index.html
index e89a032..f31524e 100644
--- a/internal/loki/ui/index.html
+++ b/internal/loki/ui/index.html
@@ -1651,6 +1651,12 @@ button:active:not(:disabled){transform:translateY(1px)}
display:inline-flex;align-items:center;justify-content:center;align-self:center;
border:0;border-radius:10px;background:transparent;color:var(--dim);
transition:background .15s ease,color .15s ease,transform .08s ease}
+/* Envoyer / arrêter : un seul des deux à la fois, décidé par data-busy (posé par
+ syncSendBtn). C'est la feuille qui garde la main sur `display` — un style
+ inline y substituait `inline-block`, et le centrage flex tombait avec lui. */
+#stop{display:none}
+html[data-busy="1"] #send{display:none}
+html[data-busy="1"] #stop{display:inline-flex}
#inputbar #attach svg,#inputbar #files-btn svg,#send svg,#stop svg{display:block;width:18px;height:18px}
#inputbar #attach:hover,#inputbar #files-btn:hover{background:var(--row-bg-on);color:var(--text)}
html[data-files="1"] #files-btn{color:var(--accent)}
@@ -2218,7 +2224,7 @@ html[data-files="1"] #files-btn{color:var(--accent)}
-
+
@@ -5461,8 +5467,12 @@ function labelTokens(el, role, n, firstTs, lastTs){
function setBusy(on){ busy=on; if(!REPLAYING) syncSendBtn(); }
function syncSendBtn(){
const sb=document.getElementById('send');
- sb.style.display=busy?'none':'inline-block';
- document.getElementById('stop').style.display=busy?'inline-block':'none';
+ // ⚠️ L'état passe par un ATTRIBUT, jamais par un style inline. Ces deux
+ // boutons étaient montrés/cachés avec `style.display='inline-block'`, qui
+ // l'emportait sur le `display:flex` de la feuille : le bouton gardait sa
+ // boîte de 34 px mais son icône de 18 px se collait à gauche, décalée de 8 px.
+ // C'est invisible tant que l'icône est un glyphe de texte, flagrant en SVG.
+ document.documentElement.setAttribute('data-busy', busy ? '1' : '0');
// Tant que le moteur n'a pas fini de charger le modèle, envoyer ne mène à rien :
// on bloque le bouton et l'Entrée, et on le DIT sous le champ. `STATUS_SEEN`
// évite de verrouiller le chat quand /api/status n'a pas encore répondu (ou ne
diff --git a/internal/loki/ui/src/index.tmpl.html b/internal/loki/ui/src/index.tmpl.html
index 6b49c35..9eb1480 100644
--- a/internal/loki/ui/src/index.tmpl.html
+++ b/internal/loki/ui/src/index.tmpl.html
@@ -419,7 +419,7 @@ document.documentElement.setAttribute('data-side',localStorage.getItem('loki-sid
-
+
diff --git a/internal/loki/ui/src/js/09-stream.js b/internal/loki/ui/src/js/09-stream.js
index 3a0a07a..29ea230 100644
--- a/internal/loki/ui/src/js/09-stream.js
+++ b/internal/loki/ui/src/js/09-stream.js
@@ -136,8 +136,12 @@ function labelTokens(el, role, n, firstTs, lastTs){
function setBusy(on){ busy=on; if(!REPLAYING) syncSendBtn(); }
function syncSendBtn(){
const sb=document.getElementById('send');
- sb.style.display=busy?'none':'inline-block';
- document.getElementById('stop').style.display=busy?'inline-block':'none';
+ // ⚠️ L'état passe par un ATTRIBUT, jamais par un style inline. Ces deux
+ // boutons étaient montrés/cachés avec `style.display='inline-block'`, qui
+ // l'emportait sur le `display:flex` de la feuille : le bouton gardait sa
+ // boîte de 34 px mais son icône de 18 px se collait à gauche, décalée de 8 px.
+ // C'est invisible tant que l'icône est un glyphe de texte, flagrant en SVG.
+ document.documentElement.setAttribute('data-busy', busy ? '1' : '0');
// Tant que le moteur n'a pas fini de charger le modèle, envoyer ne mène à rien :
// on bloque le bouton et l'Entrée, et on le DIT sous le champ. `STATUS_SEEN`
// évite de verrouiller le chat quand /api/status n'a pas encore répondu (ou ne
diff --git a/internal/loki/ui/src/styles.css b/internal/loki/ui/src/styles.css
index 7923423..0ea05fd 100644
--- a/internal/loki/ui/src/styles.css
+++ b/internal/loki/ui/src/styles.css
@@ -1620,6 +1620,12 @@ button:active:not(:disabled){transform:translateY(1px)}
display:inline-flex;align-items:center;justify-content:center;align-self:center;
border:0;border-radius:10px;background:transparent;color:var(--dim);
transition:background .15s ease,color .15s ease,transform .08s ease}
+/* Envoyer / arrêter : un seul des deux à la fois, décidé par data-busy (posé par
+ syncSendBtn). C'est la feuille qui garde la main sur `display` — un style
+ inline y substituait `inline-block`, et le centrage flex tombait avec lui. */
+#stop{display:none}
+html[data-busy="1"] #send{display:none}
+html[data-busy="1"] #stop{display:inline-flex}
#inputbar #attach svg,#inputbar #files-btn svg,#send svg,#stop svg{display:block;width:18px;height:18px}
#inputbar #attach:hover,#inputbar #files-btn:hover{background:var(--row-bg-on);color:var(--text)}
html[data-files="1"] #files-btn{color:var(--accent)}