Решили: диалог получает вилку 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.