Andrey Epifancev 9f56add219 Архив OpenSpec: redesign (#65)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 08:33:06 +04:00

197 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Context
`main` 57bf1fa. Материалы дизайн-системы (вне репозитория, `~/projects/jira-bridge/design/`):
- `DESIGN-SYSTEM-RULES.md`, `STYLE-INVENTORY.md`, `REACT-COMPONENT-CATALOG.md` — правила и инвентарь AURA;
- `AURA-xlsx-tool-handoff-2026-09-29.zip` — исходники AURA: `design-system/tokens.json` (канон токенов),
`src/styles/tokens.css` (сгенерированные CSS-переменные), `src/styles.css`, `design-system/foundations.md`;
- `Overview.svg`, `Универсалки-2…7.svg` — экспорт Figma «Универсалки»: основы (цветовые роли, типографика, геометрия),
загрузка файлов, составные компоненты (плитки выбора, сообщения, панель действия), макеты, контейнер контента,
базовые компоненты (кнопки, табы, шаги, тема, навигация приложений).
Что важно из системы:
- **Цвета (светлая):** канва `#f8f8f6`, поверхность `#fdfdfc`, приглушённый фон `#fafaf8`, текст `#17171a`, вторичный
`#818190`, плейсхолдер `#5c6260`, граница `#e5e5e0`, сильная граница `#cfcfc8`, действие `#568d32` (hover/active
`#477729`), выбранное — фон `#f4faf5` и граница `#568d32`, ошибка `#b42318` / фон `#fff1f0`, предупреждение `#d89614`
/ фон `#fffbe6` / граница `#ffe58f`, фокус `rgb(42 122 70 / 35%)`. **Тёмная:** канва `#181818`, поверхность `#1f1f1f`,
приглушённый `#272727`, текст `#f2f4f2`, вторичный `#d6dcd7`, плейсхолдер `#aab2ac`, границы `rgb(232 238 233 / 10%)` и
`/ 17%`, действие `#69a93d` (hover `#83c657`), текст на действии `#112016`, ошибка `#e26c67` / фон `#402725`,
предупреждение `#e8c17a` / фон `#382f20` / граница `#8a6d1d`, фокус `rgb(116 184 255 / 55%)`.
- **Типографика:** заголовок раздела Bold 20/28, текст Regular 14/20, подпись Semibold 14/20, мелкий текст 12/16,
крупный 16/24.
- **Геометрия:** шаг 4 px; контрол 32 px (крупный 40), радиус контрола 10; кнопки — «таблетки» (радиус 999);
панели — радиус 16, отступ 16–24; окно/канва — радиус 20–24; флажок 16×16 радиус 4; контейнер контента 1440 px;
переходы 180 ms ease, нажатие 100 ms.
- **Компоненты из Figma:** кнопки (основная зелёная, вторичная контурная, опасная, с загрузкой), сегментный
переключатель на сером треке с белой активной «таблеткой» и зелёным текстом («Навигация приложений»), переключатель
темы (солнце / луна), сообщения успеха и ошибки (иконка в круге, заголовок, пояснение), плитки выбора, плашки
файлов, шаги процесса.
Приложение сейчас (`web/src`): глобальные стили `styles/{theme,base,controls}.css` (переменные `--bg`, `--fg`,
`--muted`, `--line`, `--card`, `--panel`, `--soft`, `--accent` синий `#1f6f8b`, палитра видов работ `--k-*`, приоритетов
`--p-*`, стрелок `--edge*`, `--guide`), стили страниц `board/board.css` (165 строк, в нём же вход, список, карточка),
`issues/issues.css`, `projects/projects.css`, `shell/shell.css`. Шрифт IBM Plex Sans/Mono из `@fontsource`. Иконки —
символы текста (⋯ ⇄ ⚑ ▥ ✕ ▼). Обновление из Jira, ход пакета и тема живут в `board/useBoardSource.ts` и
`board/components/Toolbar.tsx`; тема — `shell/theme.ts` (ключ `graph-theme`: `""` системная, `light`, `dark`).
## Goals / Non-Goals
**Goals:** приложение выглядит как AURA в обеих темах; каждый экран собран из одних компонентов и токенов; общие
действия (обновление из Jira, тема, токен) — в оболочке; фильтры доски и списка сгруппированы и не перегружают экран;
поведение, адреса, ключи `localStorage` и логика доски — прежние.
**Non-Goals:** см. proposal.md.
## Decisions
1. **Без Ant Design.** Приложение на своих компонентах; тянуть antd ради внешнего вида — тяжёлая зависимость и
переписывание всех контролов. Токены AURA переносятся в `web/src/styles/tokens.css` вручную с пометкой источника
(`tokens.json` 29.09.2026); скрипта синхронизации нет.
2. **Токены — два слоя.** Семантические имена AURA (`--color-bg-canvas`, `--color-text-secondary`,
`--color-action-primary`, `--space-*`, `--radius-*`, `--font-size-*`, `--component-control-height` …) для светлой и
тёмной темы плюс токены приложения, которых в AURA нет: палитра видов работ `--k-*`, приоритеты `--p-*`, стрелки
`--edge`, `--edge-strong`, `--guide`, дорожки доски. Старые имена (`--bg`, `--fg`, `--muted`, `--line`, `--card`,
`--panel`, `--soft`, `--accent`, `--accent-fg`) на время перехода — псевдонимы семантических; после переноса всех
страниц псевдонимы удаляются. `--edge-strong` и `--accent` становятся зелёными; `--guide` (передачи, критический
путь) остаётся оранжевым — его роль — выделение поверх зелёного. Палитра `--k-*` подбирается заново под тёплую
канву, оттенки остаются различимыми между собой и с зелёным действием.
3. **Цвета только из токенов.** Вне `tokens.css` в CSS нет литералов цвета (`#…`, `rgb(…)`, `hsl(…)`, именованных,
кроме `transparent`, `currentColor`, `inherit`); проверка — тест Vitest, который читает все `*.css` в `web/src`.
Так новая страница не может «забыть» тему.
4. **Шрифт — Mulish** (`@fontsource/mulish` 5.3.0, начертания 400/600/700, подмножества с кириллицей): ближайшая
свободная гарнитура к Proxima Nova по пропорциям; Montserrat шире и съедает место в плотных таблицах. Моноширинный —
IBM Plex Mono (ключи задач, код, исходник разметки), как сейчас. IBM Plex Sans удаляется из зависимостей.
5. **Иконки — свои SVG** в `web/src/ui/icons.tsx` (линейные 16/20 px, обводка 1.5, `currentColor`), набор под
нужды приложения: обновить, загрузка/файл, меню (⋯), закрыть, шеврон, поиск, фильтр, солнце, луна, внешняя ссылка,
предупреждение, галочка, ошибка, передачи, критический путь, по датам, соседи, связи, сетка, сброс, легенда. Без
новой зависимости; текстовые символы в интерфейсе заменяются иконками.
6. **Компоненты `web/src/ui/`:** `Button` (варианты `primary`, `secondary`, `danger`, `ghost`; размеры 32 и 40;
«таблетка»; состояние загрузки — крутилка вместо иконки, кнопка недоступна), `IconButton` (32×32, радиус 10, имя —
`aria-label`), `Segmented` (трек `--color-bg-subtle`/серый, активный сегмент — поверхность и зелёный текст; ссылки
или кнопки), `ThemeSwitch` (солнце/луна), `Field` (подпись Semibold 14/20 над контролом), `TextInput`, `SearchInput`
(иконка поиска, очистка), `Select` (родной `<select>`, 32 px, радиус 10, своя стрелка), `Checkbox` (16×16, радиус 4,
зелёный при отметке), `Badge` (статус, сосед, счётчик), `Chip` (снимаемая плашка фильтра: «Спринт: X ✕»), `Notice`
(успех / ошибка / предупреждение / сведения: иконка, текст, необязательное действие), `Panel` (поверхность, граница,
радиус 16), `PageHeader` (заголовок 20/28, подзаголовок 14/20 вторичным, место для действий справа), `Dialog`
(родной `<dialog>`, радиус 20, тень канвы), `Menu` (выпадающее меню на основе нынешнего `Dropdown`), `Popover`.
Компоненты держат только вид и доступность; логика страниц остаётся в страницах.
7. **Состояние «предупреждение» разрешено.** В AURA его нет в контролах, но токены `warning` в системе есть, а хабу
нужно отличать «агент офлайн», «хаб не отвечает — прежние данные» от ошибок. Используется только в `Notice`, `Badge`
и тексте состояния; у полей ввода состояния `warning` нет.
8. **Контейнер.** Страницы «Задачи», «не найдено», вход — контейнер до 1440 px по центру с боковым отступом 24 px
(16 px уже 640 px). Доска — во всю ширину окна с отступом 24 px: графу нужна ширина. Верхняя панель — во всю ширину,
её содержимое выровнено по тем же отступам.
9. **Верхняя панель (оболочка)**, высота 64 px, поверхность, нижняя граница; слева направо: название «Хаб Jira»
(Bold 16/24), выбор проекта (`Select`), разделы — `Segmented` из ссылок «Доска связей» / «Задачи» (активный —
`aria-current="page"`), растяжка, блок данных Jira, `ThemeSwitch`, меню `IconButton ⋯` с пунктом «Сменить токен».
Уже 1100 px блок данных переносится второй строкой панели; уже 640 px — название скрыто, разделы на всю ширину.
10. **Блок данных Jira:** точка и подпись агента («агент на связи» зелёной точкой / «агент офлайн» — предупреждение;
`GET /agent` при старте и раз в 60 с, подсказка — время последнего выхода на связь), текст «данные на ДД.ММ ЧЧ:ММ»
(`last_sync.finished_at` из снимка доски текущего проекта; «полного обновления не было»), кнопка `primary`
«Обновить из Jira» с иконкой; во время пакета — состояние загрузки и текст хода «пакет #N в очереди / выполняется,
~N с»; итог (выполнен / не выполнен: текст / отменён / потерян) — текстом с цветом статуса до следующего события
или 10 с для «выполнен». Тексты событий — нынешние `statusText` для пакетных событий.
11. **Обновление из Jira переезжает в оболочку** (`web/src/shell/refresh.ts` — хук и контекст): постановка
`POST /refresh {full: true, author: "viewer"}` с проверкой `GET /agent`, один опрос `GET /batches/{id}` раз в 3 с,
остановка на терминальном статусе, 4xx, 404 и после 5 ошибок «хаб не отвечает» подряд — правила прежние (M-2…M-4
#20). Подхват незавершённого пакета `viewer` с первой командой `refresh` — при входе в приложение и после каждой
успешной загрузки снимка доски (подписка на кэш запросов), кроме перечитывания после своего пакета. По завершении
пакета инвалидируются снимки всех досок (`["board"]`), списки задач (`["issues"]`), карточки (`["issue"]`) и
проекты (`["projects"]`, счётчики задач). Доска, показывающая файл, файл не заменяет (M-1). «Новый проект» отдаёт
`batch_id` созданного пакета прямо в оболочку — опрос начинается сразу, без подхвата.
12. **Доска после переезда** (`useBoardSource`): источник (хаб / файл), `reload`, `loadFile`, события снимка
(загрузка, хаб не отвечает, файл не разобран, JSON применён, ошибка) — как были; пакетных событий нет. Строка
состояния доски показывает только свои события, пакетные — в оболочке.
13. **Шапка доски** (липкая, как сейчас): `PageHeader` «Доска связей», подзаголовок — счётчики («42 задачи из 120 ·
+5 соседей · 60 связей из 80 · скрыто без связей: 3»), источник — `Badge` («хаб» не показывается; «из файла:
имя» с кнопкой ✕ = «Перечитать»), событие доски — текстом под заголовком; справа — `Button secondary` «Проблемы»
со счётчиком (`Badge` ошибки, если > 0) и меню ⋯: «Перечитать», «Загрузить файл…», «Экспорт JSON», «Таблица
связей» (переключатель), «Привязка к сетке» (переключатель), разделитель, «Сбросить раскладку» (с прежним
подтверждением). Темы в меню доски нет.
14. **Панель управления доски** — `Panel` в одну строку (перенос по ширине): «Спринты» и «Исполнители» —
мультиселекты (нынешний `MultiSelect`, кнопка в виде `Select` с подписью внутри), разделитель, группа «Показать»:
переключатели «Соседи по связям», «Только передачи», «Скрыть без связей»; группа «Режим»: «Критический путь», «По
датам». Переключатель — кнопка-«таблетка» с иконкой, включённый — стиль «выбрано» (фон `--color-bg-selected-green`,
зелёная граница и текст), `aria-pressed`. Подсказки (`title`) — нынешние.
15. **Легенда** — под панелью, сворачивается кнопкой «Легенда» (`aria-expanded`); свёрнута — видно число скрытых
видов работ и типов связей («скрыто: 2»), если они есть. Состояние свёртки — `localStorage` ключ
`jira-hub-legend` (`"0"` свёрнута; по умолчанию развёрнута). Поведение пунктов (щелчок скрывает вид / тип) —
прежнее.
16. **Карточки на доске:** радиус 12, граница `--color-border-default`, поверхность; ключ — моно, цвет действия;
статус — `Badge`; размеры, ручки перетаскивания, растяжка и измерение высоты — прежние (меняются только цвета,
радиусы и шрифт; высота по содержимому считается тем же слоем измерения, поэтому смена шрифта не ломает раскладку,
а сохранённые размеры карточек остаются). Дорожки — чередование через `--color-bg-subtle`.
17. **Список задач.** `PageHeader` «Задачи», подзаголовок «показано N» (и «есть ещё», если следующая порция есть).
Под ним `Panel` фильтров: строка 1 — `SearchInput` «Ключ или тема» (широкий), `Segmented` «Открытые | Все»
(замена флажка «скрыть закрытые», адрес тот же: «Все» — `closed=1`), переключатель-«таблетка» «Только соседи»
(`neighbor=1`), кнопка «Фильтры» со счётчиком выбранных из шести списков; строка 2 (при выбранных) — `Chip`
«Спринт: X ✕» на каждый выбранный список и «Сбросить» (снимает шесть списков, поиск и переключатели не трогает);
панель «Фильтры» раскрывается под строкой сеткой `Field`+`Select` по 3 в ряд (спринт, исполнитель, вид работы,
статус Jira, метка, эпик). Раскрыта ли панель — в `sessionStorage` (`jira-hub-issue-filters`). Подписи и варианты
списков, «(нет на доске)» — как сейчас.
18. **Таблица задач** — в `Panel` без внутреннего отступа, шапка липкая; колонки: Ключ (моно, ссылка; рядом `Badge`
«сосед»), Тема, Статус Jira (`Badge`), Исполнитель, Срок (просрочено — цветом ошибки, по правилу карточки), Спринт,
Эпик, Вид работы, Тип. Строка 44 px, при наведении — приглушённый фон; щелчок по строке (кроме ссылок и выделения
текста) открывает карточку тем же переходом, что ключ. «Показать ещё» — `Button secondary` по центру под таблицей.
Пусто — `Notice` сведений «По этим фильтрам задач нет».
19. **Карточка задачи** — `Dialog` 1000 px, радиус 20; шапка: ключ (моно), `Badge` статуса, справа `Button secondary`
«Открыть в Jira» с иконкой внешней ссылки и `IconButton` «Закрыть»; тема — 20/28 Bold; строка фактов — 14/20
вторичным, «просрочено» — `Badge` ошибки. Разделы — заголовки 16/24 Semibold (без верхнего регистра); правая
колонка — `Panel` приглушённого фона: заметки, прочие поля, команды. Форма заметок — `Field`/`Select`/`textarea`
системы, «Сохранить» `primary`, «Отмена» `secondary`. Содержание, порядок и поведение разделов — прежние.
20. **Вход** — `Panel` 480 px по центру канвы: заголовок 20/28, пояснение, поле 40 px, `Button primary` «Войти»
(40 px); ошибка — `Notice` ошибки. **«Новый проект»** — `Dialog` 480 px с `Field`-полями, «Создать» `primary`,
«Отмена» `secondary`, ошибка хаба — `Notice` у кнопок. **«Не найдено»**, **ошибка отрисовки**, **проект не
найден**, **нет проектов** — `Notice` в контейнере с действием.
21. **Тема** — `ThemeSwitch` в оболочке, два положения. Ключ `graph-theme` прежний: без сохранённого выбора (или `""`)
— тема системы, переключатель показывает её; щелчок сохраняет `light` или `dark`. Пункта «Тема: системная» больше
нет: вернуть «как в системе» — убрать выбор нельзя, это осознанное упрощение (вторичный сценарий).
22. **Фокус и доступность:** видимое кольцо фокуса 2 px `--color-focus-ring` со смещением 2 px у всех интерактивных
элементов; цвет не единственный признак состояния (включённые переключатели — `aria-pressed` и иконка-галочка или
заливка; ошибки — иконка); `prefers-reduced-motion` отключает переходы.
23. **Проверка вида.** Скриншоты Playwright на тестовом хабе (`web/scripts/test-hub.sh`) 1920×1080 и 390×844 в
светлой и тёмной темах: доска, задачи с раскрытыми фильтрами, карточка, вход, «Новый проект» — прикладываются к PR
(в репозиторий не попадают, снимаются скриптом `web/e2e/screens.spec.ts` по флагу `SCREENS=1`). Пиксельных
эталонов в наборе тестов нет: вид будет меняться по замечаниям владельца.
24. **Тесты.** Логика доски и golden-эталоны не меняются. Тесты, привязанные к разметке (`Toolbar`, `BoardPage`,
`IssuesPage`, `LoginScreen`, `projects`, e2e), переписываются под новые роли и подписи; тесты опроса пакета
переезжают из `useBoardSource.test.tsx` в тест хука оболочки. Новые: компоненты `ui/` (роли, `aria-*`, состояния),
тест «цвета только из токенов», тест переключателя темы.
## Risks / Trade-offs
- **Шрифт меняет ширину текста** → сохранённые высоты карточек на доске могут обрезать текст. Смягчение: высота «по
содержимому» пересчитывается двойным щелчком по уголку, как сейчас; «Сбросить раскладку» доступна.
- **Переезд обновления в оболочку** затрагивает отработанные правила опроса (M-1…M-5 #20). Смягчение: перенос кода и
тестов почти без изменений, меняется только владелец состояния и набор инвалидируемых запросов.
- **Большой дифф стилей** → регрессии вида на редких состояниях (ящик «Проблемы», режим «по датам», экспорт).
Смягчение: скриншоты всех экранов в PR, владелец смотрит живое приложение.
## Decisions made without discussion
Владелец 21.10.2026 отдал редизайн и UX на усмотрение агента («сделай редизайн и проработай UX сам, потом будем
отталкиваться»); его входные данные — только: «и то и то» (родство с AURA и исправление неудобств), примеры
неудобств (обновление из Jira только с доски, перегрузка фильтрами, «падинги не те»), сценарий (раз в спринт граф,
затем поиск и перепроверка задач), «фильтры все нужны». Всё ниже — решения агента.
| # | Дата | Решение | Обоснование | Цена ошибки |
|---|---|---|---|---|
| 1 | 21.10.2026 | Без Ant Design, токены вручную (решение 1) | antd — замена всех контролов и тяжёлая зависимость ради вида | низкая: вид тот же, antd можно добавить позже |
| 2 | 21.10.2026 | Mulish вместо Proxima Nova (решение 4) | Proxima Nova платная; Mulish ближе по пропорциям, с кириллицей | низкая: замена шрифта — одна строка токена и пакет |
| 3 | 21.10.2026 | Свои SVG-иконки без библиотеки (решение 5) | ~20 иконок, зависимость не нужна | низкая |
| 4 | 21.10.2026 | Предупреждение разрешено вне контролов (решение 7) | хабу нужно отличать «офлайн» и «прежние данные» от ошибок | низкая |
| 5 | 21.10.2026 | Доска во всю ширину, прочее — контейнер 1440 (решение 8) | графу нужна ширина, таблице и карточке — ограничение строки | низкая |
| 6 | 21.10.2026 | Обновление из Jira и ход пакета — в оболочке, инвалидация всех данных (решения 10–12) | пример неудобства владельца; после обновления устаревают и список, и карточка | средняя: правила опроса переносятся, регрессии ловят перенесённые тесты |
| 7 | 21.10.2026 | Редкие действия доски — в меню ⋯, режимы — группами «Показать» / «Режим» (решения 13–14) | «перегрузка фильтрами»; доска нужна раз в спринт, режимы — основное, файл/экспорт — редко | низкая: перестановка кнопок |
| 8 | 21.10.2026 | Легенда сворачивается, состояние в `localStorage` (решение 15) | легенда занимает строку, нужна для чтения цветов — свёрнута по выбору | низкая |
| 9 | 21.10.2026 | Список: поиск и «Открытые / Все» на виду, шесть списков — в панели «Фильтры» с плашками (решение 17) | частые действия на виду, редкие — по запросу; выбранное видно плашками | низкая |
| 10 | 21.10.2026 | Щелчок по строке таблицы открывает карточку (решение 18) | основной сценарий списка — открыть и перепроверить задачу | низкая |
| 11 | 21.10.2026 | Тема — два положения, системная только без сохранённого выбора (решение 21) | переключатель AURA двухпозиционный | низкая: вернуть третье положение — пункт меню |
| 12 | 21.10.2026 | Проверка вида скриншотами в PR, без пиксельных эталонов (решение 23) | вид будет меняться по замечаниям, эталоны мешали бы | низкая |
| 13 | 22.10.2026 | Задача 1: тёмные `--color-action-danger` `#ffaea5` и hover `#ffcbc5` взяты из tokens.json AURA; `--color-status-error` остаётся `#e26c67`; затемнение фона окон везде `--color-overlay` 45% (у проектов было 40%); палитра `--k-*`/`--p-*` подобрана на глаз, `--k-test` малиновый (`#a63d78` / `#e07fb0`), чтобы не сливаться с зелёным действием | токены AURA — канон; один overlay вместо двух значений; различимость видов задач на доске | низкая: правка значений в tokens.css |
| 14 | 22.10.2026 | Задача 4: регресс T4.1 (счётчик `skipPickup` не уменьшается при ошибке перечитывания) чинится в Задаче 5, без отдельного раунда ревью; в Задаче 4 пропуск подхвата сделан счётчиком вместо флага, подхват коалесцируется, тоны `refreshText`: error для batch-lost/failed/hub-down/error, warning для cancelled | регресс мелкий и в том же модуле, что правится в Задаче 5 | низкая: один пропущенный подхват чужого пакета до следующей загрузки снимка |
| 15 | 22.10.2026 | Задача 5: высота верхней панели `min-height: 64` (не фиксированная), чтобы вторая строка данных переносилась при ширине <1100 px; панель не sticky | перенос без обрезки | низкая: заменить на фиксированную высоту и скролл строки |
| 16 | 22.10.2026 | Задача 8: ниже 1100 px таблица списка прокручивается по горизонтали внутри панели, шапка таблицы там не липкая; от 1100 px липкая | overflow на предке отключает `position: sticky`; широкая таблица на узком экране важнее липкой шапки | низкая: на узком экране шапку не видно при прокрутке вниз |
| 17 | 22.10.2026 | Задача 9: в окне карточки текст `Notice` 14 px основным цветом (локальный оверрайд `.issue .ui-notice__text`, общий компонент не тронут); `ui/Dialog` пропускает остальные атрибуты `<dialog>` и принимает `onNativeClose`; классы `.who` → `c-head`, `.confirm` → `note-confirm` из-за протечки глобальных правил `board.css`/`controls.css` | 12 px вторичным плохо читается на фоне ошибки; `IssueModal` сохраняет прежнюю логику закрытия | низкая: вернуть размер текста / переименовать классы |
| 18 | 22.10.2026 | Задача 10: `--lane-alt` светлый `#f5f5f2`, тёмный `#252525` (свёрнутая дорожка в тёмной отличается рамками, не фоном); заголовки «не найдено» и ошибки отрисовки — `h2` внутри `Notice`; текст `Notice` основным цветом 12/16 (в карточке 14/20); на 390 px в верхней панели проект, тема и меню в одной строке, переключатель разделов — ниже | палитра AURA ограничена; различимость дорожек, контраст текста сообщений | низкая: правка значений токенов и `order` в shell.css |
| 19 | 22.10.2026 | Финал: задача 11 принята без отдельного ревью задачи (покрыта финальным ревью); фикс-волна по финальному ревью — кнопка в `loading` сохраняет вид своего варианта, текст предупреждений на светлом `color-mix(warning 55%, text-primary)`, статус пакета в верхней панели от 1100 px лежит у нижней границы (макс. 560 px, многоточие, полный текст в `title`), `role=status` — постоянный контейнер; «агент офлайн» и событие при офлайн-агенте — предупреждение | снизить дрейф раскладки и поднять контраст; соответствие решению 10 | низкая: правка CSS панели/Button/Notice |