# AURA — раскладка и UX ## Оболочка (`AppShell`) - Слева **закреплённая боковая панель** 240 px (`position: sticky; height: 100dvh`), прокрутка — у окна. Сверху вниз: название приложения (16/24 700) и кнопка свёртки → `top` (выбор проекта/аккаунта) → разделы (иконка 20 + подпись, высота 40, активный — фон selected и зелёный текст, `aria-current="page"`) → растяжка → `bottom` (состояние данных, синхронизация) → подвал: `ThemeSwitch` и меню «Ещё» (открывается вверх). - Свёрнутая панель 64 px: только иконки, подписи — `visually-hidden` + `title`; состояние в `localStorage`. - **Телефон (<640 px)**: вместо панели закреплённая строка 56 px: «Меню» (гамбургер), название, `topbarEnd`. Панель выезжает слева (`min(300px, 85vw)`) поверх подложки 45%; фокус — на первый раздел, Esc и щелчок по подложке закрывают, фокус возвращается на «Меню». Нижней панели вкладок нет. - Верхней шапки во всю ширину нет: общие действия (тема, синхронизация, аккаунт) живут в панели. - Липкие элементы страниц: `top: var(--topbar-h, 0)`. ## Страница - `main.page`: до 1440 px по центру, поля 24/16; `wide` — во всю ширину (доски, графики, широкие таблицы). - `.page` — контейнер (`container: page/inline-size`): пороги раскладки внутри страниц — **`@container page`**, не `@media`. Рядом панель, поэтому ширина окна врёт. `@media (max-width: 639px)` — только для оболочки. - Сверху `PageHeader`: заголовок, подзаголовок-сводка вторичным («12 подписок · 3 просрочено»), справа одна `primary` («Добавить …») и при необходимости `secondary`/меню «⋯». ## Шаблоны экранов - **Список/таблица:** под заголовком `.ui-toolbar` — `SearchInput`, `Segmented` для 2–3 состояний («Все / Активные / Просроченные»), фильтры-списки: один — кнопка с его именем («Категория (N)»), несколько — одна кнопка «Фильтры (N)» → панель со списками. Выбранные значения — `Chip`-ами в `.ui-chips` с «Сбросить». Не выкладывать шесть селектов в ряд. Таблица — `Panel padding="none"` + `.ui-table`, шапка липнет, строка 44, щелчок по строке открывает карточку (`tr.is-clickable` + ссылка в первой ячейке для клавиатуры). На узкой странице — горизонтальная прокрутка внутри панели, не карточки; ширину, уже которой колонки не сжимаются, задай `--table-min` на таблице. - **Действия строки:** частые (1–2: «Изменить», «Удалить») — `IconButton` с `label` «Удалить: <название>» в `td.actions`. Меню «⋯» в строке таблицы не ставить: обёртка таблицы обрезает выпадашку. Удаление — через `Confirm`. - **Редкие действия** (экспорт, импорт, сброс, настройки вида) — в меню «⋯» (`Menu`), переключатели в нём — `pressed`. Разрушительные — `danger` в конце, после `MenuSeparator`, с подтверждением. - **Форма:** поля столбцом с шагом 16, `Field` над каждым контролом, обязательность — в подписи или подсказке. Проверка при отправке и при уходе с поля; ошибка под полем + `aria-invalid`; фокус на первое невалидное. Кнопки внизу справа: `secondary` «Отмена» слева от `primary`. Во время отправки — `loading`, повторный щелчок невозможен. - **Окно:** `Dialog` → `h2.ui-dialog__title`, `form.ui-form`, `div.ui-actions`. Esc и «Отмена» закрывают; щелчок по фону закрывает только окно без ввода. Есть несохранённый ввод — спросить через `Confirm` («Закрыть без сохранения?», `danger`), не `window.confirm`. - **Карточка объекта:** основная колонка + боковая колонка свойств на `--color-bg-subtle`; уже ~900 px — колонкой. ## Состояния и статусы - Статус — `Badge` с текстом; цвет только дублирует текст. - **Просрочка/срок:** просрочено, если срок **строго раньше сегодняшней даты** (сегодня — ещё не просрочка) и объект не закрыт/не на паузе. Красным (`.ui-late`: цвет ошибки, 600) — сама дата, плюс `title="просрочено"` и `, просрочено`; статус-`Badge error` — если в таблице есть колонка статуса. Строку не заливать красным, полос и рамок не добавлять. Сводка в подзаголовке: «… · N просрочено». - **Чередование строк («зебра») не делать**: мешает читать цветовые пометки. Разделение — границей и hover. - Загрузка: кнопка `loading` или `.ui-spinner` на месте результата; скелетоны не обязательны. - Ошибка загрузки/операции — `Notice error` с действием «Повторить»; успех фоновой операции — текст успеха, гаснет через ~10 с; предупреждение («нет связи, показаны прежние данные») — `Notice warning`. - Пусто — `.ui-empty`: заголовок 16/24 700, одна строка пояснения, `primary`-действие («Добавить первую …»); `primary` в `PageHeader` на это время скрыть — основная кнопка на экране одна. «Ничего не найдено» по фильтру — с кнопкой «Сбросить фильтры». ## Тема - `:root` — светлая; тёмная — `prefers-color-scheme` или `data-theme="dark"` на ``; выбор хранится в `localStorage` (`THEME_KEY`). Встроенный скрипт в `` ставит `data-theme` до отрисовки (см. SKILL.md). - Любой новый цвет — токен в трёх блоках `tokens.css`; тест паритета ловит забытый. ## Доступность (минимум) - Видимый `:focus-visible` (уже в base.css); всё кликабельное — `button`/`a`, не `div`. - Кнопка без текста — `IconButton` с `label`. Меню/выпадашки — `aria-expanded`, Esc закрывает. - Живые сообщения о ходе операции — `role="status"`; ошибки — `role="alert"`. - Контраст: вторичный текст не мельче 12 px; предупреждение на светлом — через `color-mix` (см. foundations). ## Проверка перед сдачей - Скриншоты 1920×1080 и 390×844 в обеих темах (Playwright). - Вне `tokens.css` нет литералов цвета (`tokens.test.ts` зелёный). - Высоты контролов 32/40, кнопки — «таблетки», панели — радиус 16, одна `primary` на экран. - Нет текстовых символов вместо иконок (✕ ⋯ ▼ ☰ ⚙ ☀ ☾). - Узкая страница: ничего не вылезает за правый край (`document.documentElement.scrollWidth === innerWidth`).