Le fil ne passe plus sous la carte de saisie

Sur écran large, la fin de la conversation était recouverte par la carte de
saisie et aucun défilement ne la ramenait : le fil réservait 8 px sous lui
là où le composeur en occupe ~160.

styles.css réservait bien la hauteur (#chat{padding-bottom:170px}), mais deux
règles POSTÉRIEURES dans la feuille — ajoutées par le redesign « Terre » puis
par le correctif de largeur de lecture — réécrivaient `padding` en raccourci
sous @media (min-width:721px), ce qui remet padding-bottom à la valeur du
raccourci. Sous 721 px la règle en raccourci est déclarée AVANT, d'où un bug
invisible sur mobile. Ces règles passent en longhands (padding-top +
padding-inline), et un commentaire dit pourquoi le raccourci est proscrit ici.

La réserve devient mesurée au lieu d'être devinée : syncComposer() publie
--composer-h (hauteur réelle du composeur) via un ResizeObserver, à côté de
syncGutter() qui fait déjà ce travail pour --sbw. Une constante redevenait
fausse dès que la saisie grandit ou qu'une pièce jointe s'affiche. Le
scrollbtn suit la même variable. env(safe-area-inset-bottom) disparaît du
calcul : il est déjà dans la hauteur mesurée, le compter deux fois creusait
un trou en PWA iOS.

Le voile de fondu au-dessus de la carte s'exprimait en % de la hauteur TOTALE
du composeur : l'opacité pleine tombait sous le bord haut de la carte, et le
texte restait lisible au ras du bord — l'impression de « passer derrière ».
Une variable --fade pilote désormais la bande réservée ET la course du
dégradé, qui devient donc opaque exactement au bord de la carte.

Mesuré au navigateur, du 380 px au 2000 px, au repos / saisie 10 lignes /
pièce jointe en attente : écart de 46 à 52 px partout. En réinjectant
l'ancienne règle : -119 px, bug reproduit. La largeur de lecture est
inchangée (1080 px de contenu à 2000 px de fenêtre).

Barre latérale : la discussion sélectionnée porte un cadre sauge complet et
fin (1 px) au lieu d'un liseré de 3 px sur le seul bord gauche. La bordure
transparente est portée par tous les états, la sélection ne décale donc pas
le contenu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VueWA9xcYadaYq65tBisix
This commit is contained in:
Claude committed 2026-08-16 09:09:38 +00:00
1 parent 3740b881a8
commit 1fa8452e44
3 files changed
+100 -26

No files matched your search

+18
View File
@@ -14,8 +14,26 @@ function syncGutter(){
const g=Math.max(0,(chat.offsetWidth-chat.clientWidth)/2);
document.documentElement.style.setProperty('--sbw', g+'px');
}
// La carte de saisie flotte AU-DESSUS du fil (position:absolute) : c'est au fil
// de réserver sa hauteur en rembourrage bas, sinon ses derniers messages passent
// dessous et deviennent hors d'atteinte — aucun défilement ne les ramène.
// Cette hauteur n'est pas constante : la saisie grandit avec le texte (autoGrow),
// et une pièce jointe en attente ajoute une rangée de pastilles. On la mesure
// donc au lieu de la deviner, comme on le fait déjà pour la gouttière.
// Pas de boucle d'observation : le composeur est en position:absolute, changer le
// rembourrage de #chat ne modifie pas sa hauteur.
function syncComposer(){
const c=document.getElementById('composer'); if(!c) return;
document.documentElement.style.setProperty('--composer-h', c.offsetHeight+'px');
}
addEventListener('resize', syncGutter);
addEventListener('DOMContentLoaded', syncGutter);
addEventListener('resize', syncComposer);
addEventListener('DOMContentLoaded', ()=>{
syncComposer();
const c=document.getElementById('composer');
if(c && window.ResizeObserver) new ResizeObserver(syncComposer).observe(c);
});
function scrollMaybe(){
// Pendant le replay initial on NE force AUCUN reflow : lire scrollHeight à chaque