Решили: диалог получает вилку min-height/max-height вместо жёсткого height; содержимое
тела панели не сжимается (flex-shrink: 0); тело обрезает переполнение как предохранитель, а по
конвенции является ScrollView. Инвариант держит гейт ScreenLayoutOverlapTests.
Почему: UI-элементы у нас могли ложиться друг на друга, и это не случайность разметки, а два
дефолта Yoga, работающие вместе: у каждого элемента flex-shrink: 1, а overflow: visible.
Контейнеру не хватило места — он ужимает всех детей подряд, включая те, что физически не умеют
быть меньше (кнопка с падингами, строка текста), и они продолжают рисоваться за его кромкой.
Замер на живом экране: тело 486px, контента 553px, mode-list сжат до 247 при своих 330, кнопка
PvP вылезла за кромку контейнера на 67px, подсказка встала под СЖАТОЙ границей — то есть на
кнопке.
Отвергнуто «поправить этот экран»: тот же дефолт стоит под каждым экраном, а переполнение зависит от длины текста, то есть приезжает из локализации и данных. Экран, целый на русском с двумя домами, ломается на английском или на восьми.
Сказано: «Это что за фигня с UI? Почему UI у нас принципе может друг на друга залезать? […] Мне кажется проверки - это НЕ решения проблемы, а латание дыр. У нас пайплайн это позволяет в принципе.» (04.08.2026, сессия 60e7fc08).
Грабли: гейт раскладки был написан раньше фикса и дважды оказался ложно-зелёным. Первый
раз — без simulate.FrameUpdate() раскладка не считается вовсе: worldBound у всех элементов
NaN, ничто ни с чем не пересекается, тест «проходит». Второй раз — обход пропускал абсолютные
элементы ВМЕСТЕ с потомками, а корень каждого экрана (.gm-screen) как раз абсолютный: проверка
умирала на первом шаге и не смотрела ни на что. Оба раза тест был зелёным на заведомо сломанной
раскладке. Отсюда правило для таких гейтов: сначала саботаж, потом доверие — гейт обязан
покраснеть на исходной поломке, иначе он не гейт.
Второе: overflow: hidden сам по себе не лечит, а меняет вид аварии — наложение превращается в
тихую обрезку, и кнопка просто исчезает под кромкой. Поэтому гейт ловит ОБА исхода: и наложение,
и содержимое за кромкой контейнера, который не умеет прокручиваться.
Владелец правды: components.uss (.gm-panel--dialog, .gm-panel__body, .gm-clip),
тест ScreenLayoutOverlapTests.