Решили: ни один PanelSettings в Assets/_Project не имеет права на clearColor — непрозрачный фон даёт камера своей сцены. Инвариант держит тест PanelSettingsTests, потому что нарушить его можно в ассете dev-стенда, а сломается при этом кадр игры.

Почему: «иногда при запуске сцены просто серый экран» оказался не гонкой бута и не потерянной подпиской: пустая панель UI-стенда очищала весь буфер своим серым (0.060, 0.060, 0.070) и стирала кадр целиком — мир, интерфейс, всё. Второй кандидат, DisableDomainReload в Enter Play Mode, тут ни при чём, хотя выглядел убедительно и остаётся отдельным риском.

Грабли:

  • Панель UITK принадлежит АССЕТУ, а не сцене. PreviewPanelSettings живёт в UiPreview.unity, которая в игре не загружается — но стоит ассету попасть в память (открыли стенд, кликнули в Project, прошлись скриптом по FindAssets("t:PanelSettings")), его рантайм-панель регистрируется глобально и рисуется в любой сцене. Проверять «кто ссылается на ассет» здесь бесполезно: ссылок нет ни одной, а панель есть.
  • «Иногда» объяснялось приоритетом. У игровой панели и панели стенда одинаковый sortingPriority, поэтому порядок отрисовки решает порядок регистрации: разбудили стенд раньше игры — кадр цел, позже — стёрт. Отсюда недетерминизм, из-за которого баг месяцами читался как «показалось».
  • Цвет назвал виновника точнее логов. Серый на экране был 45454B, а colorClearValue стенда — (0.060, 0.060, 0.070): те же числа, переведённые из линейного в sRGB. Логи при этом были безупречны — бут проходил, экран строился, дерево элементов на месте.
  • Токен --gm-color-console-surface был холоднымrgba(10, 12, 14), синева среди тёплой палитры. Прозрачность разрешено задавать rgba напрямую (как у скрима), но оттенок обязан лежать на рампе ink: R > G > B.

Владелец правды: тест PanelSettingsTests, ассет UI/Dev/PreviewPanelSettings.asset, токен в UI/Theme/tokens.semantic.uss.