Files
vidconf/design/DESIGN_SYSTEM.md

73 KiB
Raw Blame History

VidConf — Дизайн-система

Дизайн зафиксирован как обязательный референс для реализации; изменения — только через обновление этого документа и макетов design/mockups/. Оболочка поддерживает светлую и тёмную тему с переключателем и автодетектом системной темы (см. §0.1 и §1.2b ниже).

Референсы: referens.png (стиль/layout светлой оболочки), collor_ico.png (цвета/иконография тёмной комнаты конференции). Все hex-значения взяты пипеткой непосредственно из референсов (см. таблицы ниже) и проверены на контраст по формуле WCAG 2.1 (относительная светимость sRGB); тёмная оболочка (§1.2b) — производная от уже утверждённой палитры комнаты (hex переиспользованы 1:1, без повторной пипетки, см. таблицу происхождения).

0. Принцип тем

Оболочка (auth, лобби, календарь, «Мои конференции», join, админка, профиль, email) имеет две темы — светлую (дефолт) и тёмную, с ручным переключателем и автодетектом системной темы (см. §0.1). Комната конференции — всегда тёмная, отдельная тема без переключателя.

Экраны Референс Характер
Оболочка, светлая auth, лобби (хаб действий), календарь (менеджер конференций), «Мои конференции», подключение по ссылке/номеру, админка, профиль, email referens.png светлый фон, глубокий индиго в типографике, крупные скругления (2032px), pill-кнопки с обводкой, пастельно-мятный CTA, glass-панели
Оболочка, тёмная те же экраны оболочки design/mockups/dark/ (утв. 2026-07-18), палитра — производная от collor_ico.png (см. §1.2b) графитовый фон, пастельная мята вместо индиго (бренд/заголовки/ссылки/CTA), розовый danger, янтарный warning/focus, те же формы/скругления/типографика, что у светлой оболочки — меняется только цвет
Комната (всегда тёмная) room (конференция) collor_ico.png графитовый фон, тёмно-серые плитки участников, зелёный/красный микрофон, жёлто-оранжевая рамка активного спикера, контурные иконки тулбара

Темы не смешиваются на одном экране: комната конференции — единственный экран с собственной несменяемой тёмной темой; всё остальное — оболочка, которая целиком переключается между светлым и тёмным вариантом (пользователь никогда не видит светлую панель внутри тёмной оболочки или наоборот).

0.1 Механизм переключения (оболочка)

Контракт для frontend-dev (реализовано в design/tokens.css):

  • Атрибут на корнеdata-theme="dark" / data-theme="light" на <html> (или другом предке :root-скоупа приложения) — явный выбор пользователя, сохраняется (localStorage/настройка профиля), имеет приоритет над системной темой.
  • Дефолт по ОС — если data-theme не проставлен вообще, действует @media (prefers-color-scheme: dark): тёмная палитра активируется автоматически при тёмной системной теме, светлая — при светлой/отсутствии поддержки. Как только пользователь явно переключил тему, автодетект отключается для этого выбора (селектор :root:not([data-theme]) в tokens.css перестаёт совпадать).
  • Оба триггера переопределяют один и тот же набор переменных, что и светлый :root (--color-bg, --color-ink-900, --color-accent и т.д.) — весь остальной CSS оболочки (компоненты, frontend/) ссылается на них через var() и не нуждается в собственной dark:-логике.
  • [data-theme="room"] (комната) — независимый третий скоуп с отдельным неймспейсом --color-room-*; не активируется ни атрибутом dark, ни prefers-color-scheme, и не участвует в переключателе оболочки.

Предустановленных переговорных комнат нет — конференции создаются динамически (мгновенно из лобби или планово из календаря), закрепляются с повторением и видны в «Мои конференции»; вход — по ссылке или номеру, гости входят через «представиться». Макеты: design/mockups/lobby.html, calendar.html, my-conferences.html, join.html.


1. Цветовые токены

Все значения продублированы 1:1 в tokens.css. Контраст текста проверен и везде ≥ 4.5:1 (см. колонку «контраст»), кроме специально помеченных декоративных/крупных элементов (правило WCAG для large text ≥ 3:1, отмечено ⚠︎).

1.1 Светлая тема (оболочка)

Токен Hex Назначение Контраст
--color-bg #F1F1F1 фон страницы (пипетка referens.png, фон вокруг карточек)
--color-bg-alt #F7F7F8 альтернативный фон секций / подложка полей
--color-surface #FFFFFF карточки, модалки, поля ввода
--color-surface-glass rgba(255,255,255,.55) glass-панели (стат-карточки в стиле referens.png), с backdrop-filter: blur(16px)
--color-border #E1E3E9 базовая обводка карточек/инпутов
--color-border-strong #C7CCDC обводка при hover
--color-border-pill #4A5A9E обводка pill-кнопок (пипетка контура «НАПРАВЛЕНИЕ»)
--color-ink-900 #2E3454 основной текст (параграфы), текст на CTA (--color-accent-text, см. ниже) 11.3:1 на --color-bg-alt
--color-ink-700 #3B4D95 брендовый индиго — дисплейные заголовки, ссылки (пипетка «X'FLOW GYM») 6.9:1 на --color-bg
--color-ink-500 #535F94 вторичный текст (подписи, мета) 5.7:1 на --color-bg-alt
--color-ink-400 #6976AC third-tier — только крупный/жирный текст (эйбрау-подписи в [скобках], ≥ 20px) 4.1:1 ⚠︎ large-text-only
--color-ink-300 #A6AECB плейсхолдеры, disabled-текст
--color-accent #D4F2E3 пастельная мята CTA (заливка primary-кнопки; токен переименован из --color-accent-green, т.к. акцент больше не обязан быть зелёным)
--color-accent-hover #C7EBD9 hover CTA (переименовано из --color-accent-green-hover; осветлена на 50%, было #8FD6B2)
--color-accent-active #BAE4CE active/pressed CTA (переименовано из --color-accent-green-active; осветлена на 50%, было #74C89D)
--color-accent-text #2E3454 текст на мятной заливке — тёмный индиго, равен --color-ink-900 (переименовано из --color-accent-green-text) 10.15:1 (default) / 9.40:1 (hover) / 8.69:1 (active)
--color-success #0A7A4C текст статуса «свободна» 5.38:1 на белом
--color-success-bg #E4F7ED подложка бейджа «свободна»
--color-success-dot #46916B индикатор-точка (пастелизирована, была неоновой #1BC46B; не единственный носитель статуса) 3.80:1 на белом (нетекст)
--color-danger #C7364F текст статуса «отменена», кнопки удаления 5.16:1 на белом
--color-danger-bg #FCE7EB подложка бейджа «отменена»
--color-danger-dot #C65366 индикатор-точка (пастелизирована, была #E0526B) 4.35:1 на белом (нетекст)
--color-warning #7F560D текст статуса «запланирована» 6.48:1 на белом
--color-warning-bg #FBF0DC подложка бейджа «запланирована»
--color-warning-dot #B58A26 индикатор-точка (углублена с #D6A83D ради контраста 3:1 на белом; рамка спикера в тёмной теме — отдельный токен, тот же исходный тон, оставлена без изменений) 3.17:1 на белом (нетекст)
--color-focus-ring #3B4D95 focus-visible обводка

1.2a Тёмная тема — комната конференции

Токен Hex Назначение Контраст
--color-room-bg #1E1E1E фон канвы конференции (пипетка collor_ico.png)
--color-room-surface #2A2A2A топбар, нижний тулбар, всплывающие панели
--color-room-surface-raised #333333 дропдауны, поповеры, панель чата
--color-room-tile #363636 плитка участника (пипетка тёмно-серых плиток)
--color-room-tile-border #3F3F3F обводка плитки в покое
--color-room-tile-hover #3D3D3D плитка при hover/фокусе
--color-room-text-primary #E8E8E8 имя участника, основной текст 9.9:1 на tile
--color-room-text-secondary #B0B0B0 вторичный текст (время, статус) 5.6:1 на tile
--color-room-text-tertiary #7A7A7A таймстемпы чата (декоративно, не единственный носитель смысла)
--color-room-mic-on #7FDDA8 микрофон активен, пастельная мята (была неоновая #46D97A, тот же зелёный вектор, что и --color-accent в оболочке) 8.76:1 на surface / 7.37:1 на tile (нетекст)
--color-room-mic-off #EB93A1 микрофон выключен / mute, пастельный розово-красный (была #F2778C) 6.30:1 на surface / 5.31:1 на tile (нетекст)
--color-room-speaker-ring #D6A83D рамка активного спикера, жёлто-оранжевая (пипетка collor_ico.png) 6.51:1 ⚠︎ декоративная рамка
--color-room-danger #EB93A1 иконка «выйти», деструктивные контуры (пастелизирована вместе с mic-off) 6.30:1 (нетекст)
--color-room-danger-bg #B85468 заливка кнопки «Выйти» (hover/подтверждение), пастельная роза (была #B3384E) 4.66:1 (белый текст)
--color-room-danger-bg-hover #B9495F hover заливки danger (была #C24363) 5.02:1 (белый текст)
--color-room-focus-ring #D6A83D focus-visible обводка в тёмной теме

Статусы никогда не передаются только цветом: у микрофона есть форма иконки (перечёркнутый микрофон = mute), у бейджей лобби — иконка + текст, у активного спикера — рамка + подпись, у конфликта брони — иконка AlertTriangle + текст.

1.2b Тёмная тема — оболочка

Макеты: design/mockups/dark/*.html (6 экранов, 1:1 разметка со светлыми прообразами design/mockups/*.html, меняется только цвет — см. design/mockups/dark/README.md, полное обоснование подбора палитры). Механизм переключения — §0.1.

Принцип. Тёмная оболочка не изобретает новых цветов, а переиспользует уже утверждённые токены комнаты (§1.2a) в новых ролях — так тёмное лобби и тёмная комната конференции читаются как одна система при переходе пользователя между ними. Там, где у комнаты нет готового аналога (бренд-панель, формы, glass- карточки — компоненты, которых в комнате не существует), значения получены подмешиванием уже утверждённых цветов комнаты к графитовому фону/друг к другу, а не придуманы независимо.

Токены, переиспользованные из комнаты 1:1 (тот же hex, что и --color-room-*, §1.2a):

Токен оболочки ([data-theme='dark']) = токен комнаты Hex Новая роль в оболочке
--color-bg --color-room-bg #1E1E1E фон страницы
--color-surface --color-room-surface #2A2A2A карточки, топбар, поля
--color-border --color-room-tile-border #3F3F3F базовая обводка
--color-ink-900 --color-room-text-primary #E8E8E8 основной текст
--color-ink-500 --color-room-text-secondary #B0B0B0 вторичный текст
--color-ink-300 --color-room-text-tertiary #7A7A7A плейсхолдеры/disabled
--color-ink-700, --color-accent, --color-border-pill, --color-success, --color-success-dot --color-room-mic-on #7FDDA8 мята: бренд/заголовки/ссылки/CTA/«успех» — единая пастельно-зелёная роль (см. ниже)
--color-danger, --color-danger-dot --color-room-mic-off #EB93A1 розово-красный: текст/иконки/обводка статуса «отменена»/ошибки
--color-warning, --color-warning-dot --color-room-speaker-ring #D6A83D янтарь: статус «запланирована»
--color-focus-ring --color-room-focus-ring #D6A83D кольцо :focus-visible
--color-danger-solid, --color-danger-solid-hover --color-room-danger-bg(-hover) #B85468 / #B9495F заливка сплошных danger-кнопок (.btn-danger) — отдельная пара, см. ниже почему

Одна мята — три роли. В светлой оболочке бренд-индиго (--color-ink-700) и мятный CTA (--color-accent) — два разных токена/hex. В тёмной оболочке они сведены к одному и тому же #7FDDA8 (= --color-room-mic-on), как и в самой комнате, где одна пастельная мята уже покрывает всё «позитивное» (микрофон вкл, демонстрация экрана, счётчик участников, отправка в чате). Различие ролей (бренд-текст vs интерактивная заливка) остаётся читаемым за счёт контекста, а не второго оттенка.

Почему заливка danger-кнопок — отдельный токен. В светлой теме один hex (--color-danger, #C7364F) одинаково хорошо работает и как текст на белом, и как заливка кнопки с белым текстом. В тёмной теме роли расходятся: --color-danger (#EB93A1, светлый пастельный тон) отлично читается как текст на тёмном фоне (6.30:1 на #2A2A2A), но слишком светлый для белого текста кнопки поверх него (≈1.9:1, провал). Поэтому у тёмной оболочки заведена отдельная пара --color-danger-solid / --color-danger-solid-hover (#B85468 / #B9495F, контраст с белым текстом 4.66:1 / 5.02:1) — только для сплошных danger-кнопок (.btn-danger: «Отменить все повторения» в календаре, «Удалить» в админке). В светлой теме этот токен не заведён — компонент .btn-danger там по-прежнему ссылается на --color-danger напрямую (§4.3), т.к. проблема специфична для тёмной палитры.

Новые токены (введены там, где у комнаты нет готового компонента-аналога — формы, бренд-панель, glass-карточки; получены смешиванием уже утверждённых цветов комнаты, не придуманы независимо):

Токен Hex Как получен Контраст Роль
--color-bg-alt #242424 между --color-room-bg и --color-room-surface альт-фон секций, инпуты, disabled-поля
--color-surface-glass rgba(51,51,51,.55) --color-room-surface-raised (#333333) с прозрачностью, по образцу светлой --color-surface-glass glass-панели (стат-виджеты)
--color-border-strong #585858 осветление --color-border 2.02:1 на surface (нетекст, декоративный hover-акцент, задублирован тенью — не единственный носитель состояния) обводка при hover
--color-ink-400 #5D9A78 мята #7FDDA8 × фон #1E1E1E, смешение 35% 5.05:1 на bg / 4.35:1 на surface эйбрау-подписи [ В СКОБКАХ ], крупные подписи
--color-accent-hover #75CA9A мята × фон, смешение 10% текст #10331F на заливке: 7.04:1 hover CTA
--color-accent-active #6CB78C мята × фон, смешение 20% текст #10331F на заливке: 5.80:1 active/pressed CTA
--color-accent-text #10331F буквальный hex, уже встречающийся инлайн в room.html (.chat-input-row button, .tb-btn.is-positive-active, .badge-count) как цвет текста на --color-room-mic-on 8.45:1 на мяте текст на CTA/бренд-заливках мятой
--color-success-bg rgba(127,221,168,.14) мята, низкая непрозрачность поверх тёмной поверхности подложка бейджей «идёт сейчас»/«свободна»/«активен»
--color-danger-bg rgba(235,147,161,.14) розовый (mic-off), низкая непрозрачность подложка бейджей «отменена»
--color-warning-bg rgba(214,168,61,.16) янтарь (speaker-ring), низкая непрозрачность подложка бейджей «запланирована»
--shadow-sm/md/lg/glass rgba(0,0,0,.35.5) по образцу --shadow-room-panel комнаты (тёмные тени вместо индиго-тонированных) тени карточек/модалок/glass-панелей

Компонентные исключения (не токены, точечные правки в самих макетах). Пять мест, где CSS светлого макета использовал литеральный hex/rgba вместо var() и поэтому не мог автоматически перекраситься — задокументированы в design/mockups/dark/README.md (раздел «Точечные правки поверх скопированного CSS»), в tokens.css не заводились как отдельные токены:

  1. Аватары/.weekday-chip.is-selected/.badge-role-admin — заливка var(--color-ink-700) + жёсткий color: #fff заменены на var(--color-accent-text) (белый на мятной заливке нечитаем).
  2. .btn-danger — заливка var(--color-danger-solid) вместо var(--color-danger) (см. таблицу выше).
  3. .copy-toast (тултип «Скопировано») — фон был var(--color-ink-900) (тёмный в светлой теме → стал бы светлым в тёмной, ломая тёмный чип- тултип); в макетах заменён на буквальный #333333 (= --color-room-surface-raised). При переносе в frontend/ (реальный компонент на React, не статичная копия страницы) рекомендуется завести токен-алиас --color-surface-raised под обе темы, а не повторять этот литерал — тултип не единственное будущее место такой потребности.
  4. Декоративные градиенты/rgba-подложки (бренд-панель login.html, фон body в lobby.html, .day-col.is-today/.cancel-alert в calendar.html, box-shadow фокуса/ошибки форм, glass-обводка) — тональные аналоги новой палитры (мятное свечение вместо индигового, янтарный focus-glow вместо индигового, розовый error-glow); та же практика уже используется в светлых макетах (см. auth.html — там эти значения тоже не токенизированы).
  5. color-scheme: dark — добавлен в активационный блок tokens.css (см. §0.1), чтобы нативные элементы форм (скроллбар, чекбоксы) тоже рендерились в тёмной палитре браузера.

Доступность. Текст ≥ 4.5:1 везде, кроме крупных/декоративных элементов (правило §5, порог 3:1). Статус не передаётся только цветом (см. §1.2a). Палитра пастельная, той же светлоты, что и утверждённая палитра комнаты — неоновых/кислотных акцентов не вводилось. Регрессия — design/tools/contrast.py.

1.3 Проверка контраста

Палитра пастельная (не неоновая) во всей системе — все текстовые пары проходят WCAG 2.1 (≥4.5:1, кроме отмеченных ⚠︎ декоративных/крупных элементов, ≥3:1). Регрессионная проверка — скрипт design/tools/contrast.py (явный список пар с ratio и порогом), запуск: python3 design/tools/contrast.py — 24/24 пар PASS.

1.4 Логотип

Логотип — стилизованный объектив камеры, отсылка к видео как сути продукта.

Файлы:

  • design/logo.svg — мастер-версия, квадратный viewBox 0 0 64 64, масштабируется без искажений. Для крупных начертаний: центральный медальон лобби, промо-материалы, шапка письма при экспорте в PNG высокого разрешения.
  • design/favicon.svg — упрощённая версия для мелких размеров (1632px): меньше колец, толще штрихи, чтобы силуэт не «замыливался». Используется как иконка в топбаре рядом со словом «VidConf» во всех макетах, а также как browser favicon / app-иконка продакшен-сборки.

Конструкция (обе версии):

  • центр — плоский шестигранник (polygon), закрытая диафрагма объектива, залита сплошным цветом;
  • вокруг — концентрические окружности (4 в мастер-версии, 1 в favicon), каждая нарисована как <circle> со stroke-dasharray/stroke-dashoffset, что даёт разорванные на сегменты дуги неровной длины и разной толщины штриха — техно/HUD-эстетика, ощущение вращения диафрагменных лепестков.

Цвет: строго монохром, один тон — currentColor, наследующий цвет текста в месте использования (в проекте это всегда var(--color-ink-700), #3B4D95). Никаких градиентов, бликов или цветов из референса-эскиза. Контраст #3B4D95 на --color-bg (#F1F1F1) — 6.93:1, на --color-surface (#FFFFFF) — 7.83:1 (обе пары — в design/tools/contrast.py, порог для графики 3:1 — проходят с большим запасом даже как текстовый).

Использование в макетах:

  • топбар/сайдбар (.brand-mark) — favicon.svg инлайн, 22×22px (соразмерно высоте строки словесного знака, заменяет прежний .logo-dot) во всех макетах design/mockups/*.html, где есть слово «VidConf»;
  • центральный медальон лобби (.hub-logo) — полная logo.svg, 56×56px внутри медальона 156×156px, вместе со словом «VidConf» под знаком (см. §4.12 «Карточка-действие хаба (лобби)» — геометрия перекрытия медальона);
  • email-summary.html — инлайн SVG допустим только для HTML-макета; в продакшен-письме обязателен растровый PNG (почтовые клиенты в массе не рендерят инлайн-SVG), см. комментарий в файле рядом с разметкой.

1.5 Аватары (инициалы)

Круглый аватар с инициалами (.avatar, компонент Avatar §4) — заливка всегда var(--color-ink-700) (основной, current-user — user-pill топбара, сайдбар админки) либо var(--color-ink-500) (второстепенные, списки участников — таблицы админки, участники встречи в письме-саммари). Текст инициалов — всегда светлый, #FFFFFF, никогда не тёмный ink-900/ ink-700: тёмные инициалы на индиго-заливке дают нечитаемый, «слипшийся» результат. Правило зафиксировано как регрессионные пары в design/tools/contrast.py:

Заливка Текст Контраст
--color-ink-700 (#3B4D95) #FFFFFF 7.83:1
--color-ink-500 (#535F94) #FFFFFF 6.12:1

Обе пары — с большим запасом выше порога 4.5:1 для текста. Дополнительно: font-weight инициалов — не ниже 600 (используется --text-caption, 600 12px), text-transform: none (кириллические инициалы не должны проходить через uppercase-трансформацию родителя).

⚠ Предупреждение о каскаде CSS-специфичности. В calendar.html и my-conferences.html правило .avatar-btn span { color: var(--color-ink-900); } (специфичность 0,1,1 — класс + тип-селектор) имело специфичность ВЫШЕ, чем .avatar { color: #fff; } (0,1,0 — один класс), и перебивало белый цвет у <span class="avatar"> (он тоже span внутри .avatar-btn, значит попадал под общее правило .avatar-btn span) — инициалы рендерились тёмным ink-900 на индиго-заливке, нечитаемо. Специфичность решает независимо от порядка правил в файле, поэтому простое переупорядочивание CSS не спасает. Правило на будущее: имя рядом с аватаром — всегда через адресный класс (.user-name, не голый span), никогда .wrapper span без уточнения — такой селектор непреднамеренно задевает <span class="avatar">, если он лежит в той же обёртке. Проверено headless-рендером (getComputedStyle(...).color) после фикса — rgb(255, 255, 255) в обоих файлах; заодно проверены admin.html, lobby.html (структура другая — .avatar-btn div span/.user-pill .avatar, коллизии не было) — там уже было rgb(255, 255, 255) и до правки.


2. Типографика

Роль Шрифт Fallback-стек Где
Дисплей (display) Unbounded 'Arial Rounded MT Bold', -apple-system, 'Segoe UI', sans-serif H1 лендинг-подобных блоков, крупные цифры дашборда, логотип
Текст (body/UI) Inter -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif вся UI-типографика: формы, таблицы, кнопки, параграфы
Моно (mono) JetBrains Mono 'SFMono-Regular', Menlo, Consolas, monospace код комнаты, ID брони, таймер конференции, .ics-детали

Шрифты подключаются как самостоятельно захостенные (frontend/public/fonts, @font-face с относительным путём), CDN Google Fonts не используется нигде (в т.ч. в макетах) согласно правилу проекта «секреты и зависимости — не из внешних сетей на рантайме». В tokens.css объявлены @font-face с путями ../fonts/..., отсутствие файлов в макетах безопасно деградирует в fallback-стек без сетевых запросов.

Unbounded выбран за геометричные, слегка скруглённые формы букв — это то же семейство характера, что у дисплейного заголовка в referens.png (широкие O/G/W, единая толщина штриха). Inter — для плотного кириллического текста интерфейса (отличная читаемость в мелких кеглях, стандарт де-факто для shadcn/ui).

Шкала

Токен Размер / line-height Начертание Применение
--text-display-2xl 64px / 1.05 Unbounded 700 Hero-заголовок (не используется в MVP-экранах, зарезервировано)
--text-display-xl 48px / 1.1 Unbounded 700 Крупные цифры (админ-дашборд, счётчики)
--text-display-lg 34px / 1.2 Unbounded 600 H1 экрана (заголовок лобби, «VidConf» в auth)
--text-h1 28px / 1.25 Inter 700 заголовок карточки/секции
--text-h2 22px / 1.3 Inter 600 подзаголовок
--text-h3 18px / 1.35 Inter 600 заголовок компонента (карточка комнаты, панель)
--text-body-lg 16px / 1.5 Inter 400/500 основной текст форм
--text-body 14px / 1.5 Inter 400/500 таблицы, списки, вторичный UI
--text-caption 12px / 1.4, uppercase, letter-spacing: .04em Inter 600 эйбрау-подписи [ В КВАДРАТНЫХ СКОБКАХ ], статус-бейджи
--text-mono-sm 13px / 1.4 JetBrains Mono 500 код комнаты/брони

3. Spacing, радиусы, тени, границы

Spacing (8pt-грид с базой 4px)

--space-1: 4px · --space-2: 8px · --space-3: 12px · --space-4: 16px · --space-5: 20px · --space-6: 24px · --space-8: 32px · --space-10: 40px · --space-12: 48px · --space-16: 64px · --space-20: 80px · --space-24: 96px

Радиусы

Крупные скругления карточек взяты из referens.png (визуально 2432px).

--radius-sm: 8px (инпуты, чипы) · --radius-md: 12px (кнопки не-pill, теги) · --radius-lg: 16px (плитки участников в комнате, пипетка collor_ico.png) · --radius-xl: 20px (малые карточки) · --radius-2xl: 24px (карточки комнат/лобби) · --radius-3xl: 32px (крупные панели, hero-блоки) · --radius-full: 999px (pill-кнопки, аватары, бейджи-статусы)

Тени

  • --shadow-sm 0 1px 2px rgba(46,52,84,.06) — лёгкий отрыв карточки от фона.
  • --shadow-md 0 4px 16px rgba(46,52,84,.08) — карточка при hover.
  • --shadow-lg 0 12px 32px rgba(46,52,84,.12) — модалки, поповеры.
  • --shadow-glass 0 8px 24px rgba(59,77,149,.15) + backdrop-filter: blur(16px) — glass-панели (стат-виджеты).
  • --shadow-speaker-glow 0 0 0 3px var(--color-room-speaker-ring), 0 0 24px rgba(214,168,61,.35) — свечение активного спикера (доп. к рамке).
  • --shadow-room-panel 0 8px 24px rgba(0,0,0,.4) — панель чата/поповеры в тёмной теме.

Границы

--border-thin: 1px (базовая) · --border-md: 1.5px (pill-кнопки) · --border-thick: 2px (hover/focus состояния) · --border-speaker: 3px (рамка активного спикера).

Breakpoints (desktop-first)

--bp-desktop: 1440px — расчётная ширина макета. --bp-min: 1280px — минимальная поддерживаемая ширина (контент перетекает, колонки не ломаются до 1280px; мобильная адаптация — вне скоупа).

Motion

Только микро-переходы состояний (hover/focus/toggle), без декоративных анимаций: --transition-fast: 120ms ease, --transition-base: 200ms ease.


4. Компоненты и их состояния

4.1 Кнопка Primary (pill CTA, светлая тема)

Форма: --radius-full, паддинг 12px 24px, шрифт --text-body-lg / Inter 600.

Состояние Фон Текст Обводка
default --color-accent --color-accent-text нет
hover --color-accent-hover тот же нет, --shadow-md
active/pressed --color-accent-active тот же нет
focus-visible как default тот же 2px --color-focus-ring, offset 2px
disabled --color-ink-300 фон 40% --color-surface нет, cursor: not-allowed

4.2 Кнопка Secondary (pill outline, светлая тема)

Прозрачный фон, обводка 1.5px --color-border-pill, текст --color-ink-700. Hover: фон --color-bg-alt, обводка --color-ink-700. Focus-visible: кольцо --color-focus-ring. Disabled: обводка --color-border, текст --color-ink-300.

4.3 Кнопка Danger (светлая тема, напр. «Удалить комнату» в админке)

Фон --color-danger, текст #FFFFFF, форма --radius-full. Hover — темнее на 8%. Всегда сопровождается иконкой (Trash2), не только цветом.

4.4 Инпут / форма

Фон --color-surface, обводка 1px --color-border, радиус --radius-md, паддинг 10px 14px, текст --text-body-lg.

Состояние Обводка Доп.
default --color-border
hover --color-border-strong
focus 2px --color-focus-ring подпись-хинт индиго
error 2px --color-danger текст ошибки под полем, иконка AlertCircle слева
disabled --color-border, фон --color-bg-alt текст --color-ink-300

4.5 Карточка (светлая тема)

Фон --color-surface, радиус --radius-2xl, обводка 1px --color-border, тень --shadow-sm (по умолчанию) → --shadow-md (hover, если карточка кликабельна). Glass-вариант (стат-виджеты): --color-surface-glass + backdrop-filter: blur(16px)

  • --shadow-glass, обводка 1px rgba(255,255,255,.6).

4.6 Бейдж статуса конференции (календарь, «Мои конференции»)

Бейдж описывает жизненный цикл КОНФЕРЕНЦИИ (комнат в системе нет). Pill (--radius-full), паддинг 4px 12px (мелкий вариант в сетке календаря — 2px 9px, font-size: 11px), --text-caption, иконка 1214px слева от текста.

Статус Фон Текст Иконка
Запланирована (разовая) --color-warning-bg --color-warning Clock
Закреплена · повторяется --color-bg-alt, обводка 1px --color-border-strong --color-ink-700 Repeat
Идёт сейчас --color-success-bg --color-success Play
Завершена --color-bg-alt --color-ink-500 CheckCircle2
Отменена --color-danger-bg --color-danger X, заголовок карточки — line-through

Закрытость паролем — НЕ отдельный статус жизненного цикла (ортогональна ему: запланированная, закреплённая или идущая сейчас конференция может быть закрытой одновременно). Отображается отдельно — маленькая иконка Lock (1315px, --color-ink-700/--color-room-text-secondary) инлайном перед названием конференции, не бейджем.

4.7 Плитка участника (комната, тёмная тема)

Фон --color-room-tile, радиус --radius-lg, обводка 1px --color-room-tile-border. Имя — верхний левый угол, --text-body / --color-room-text-primary, поверх полупрозрачной подложки-градиента снизу-вверх для читаемости на видео. Иконка микрофона — нижний левый угол, 20px, круглая подложка rgba(0,0,0,.35).

Состояние Обводка/эффект Микрофон
default (не говорит) --color-room-tile-border Mic зелёный, если не muted
активный спикер --border-speaker --color-room-speaker-ring + --shadow-speaker-glow форма рамки — единственный, кто её имеет
muted обводка как default MicOff --color-room-mic-off, иконка перечёркнута (не только цвет)
видео выключено вместо видео — аватар-заглушка на --color-room-tile-hover значок VideoOff в углу
pinned/развёрнута увеличенный размер в сетке, иконка Pin активна
hover (крупная плитка) показывается toolbar-оверлей (Maximize2, MoreVertical)

4.8 Нижний тулбар комнаты (тёмная тема)

Фон --color-room-surface, высота 72px, иконки контурные 24px, подпись под иконкой --text-caption --color-room-text-secondary.

Кнопка Цвет по умолчанию Toggled-off/mute Позитивное действие
Микрофон --color-room-text-primary outline фон --color-room-mic-off заливка, иконка MicOff
Камера --color-room-text-primary outline фон --color-room-mic-off, иконка VideoOff
Демонстрация экрана --color-room-text-primary outline active-состояние: иконка/подпись --color-room-mic-on
Чат --color-room-text-primary outline активна (панель открыта): подложка --color-room-surface-raised
Участники --color-room-text-primary outline бейдж-счётчик --color-room-mic-on
Выйти обводка --color-room-danger всегда красная, hover → заливка --color-room-danger-bg

4.9 Панель чата (комната)

Свёрнута: не занимает места, доступна кнопкой в тулбаре (см. 4.8). Развёрнута: правая колонка 320px, фон --color-room-surface-raised, разделитель 1px --color-room-tile-border, сетка участников сужается. Сообщения — пузыри --color-room-tile, имя автора --color-room-mic-on (лёгкий акцент, не критично для контраста т.к. декоративно), текст --color-room-text-primary.

4.10 Ячейка календаря-менеджера

Календарь не бронирует переговорные (нет привязки к комнате, нет конфликтов брони по EXCLUDE-констрейнту БД) — это менеджер запланированных/закреплённых КОНФЕРЕНЦИЙ. Единица сетки — дневная колонка (--radius-lg, фон --color-bg-alt, min-height: 460px), внутри — стопка карточек-конференций («чипов», --radius-md, --text-body).

Состояние Фон/обводка Текст/иконка
День без конференций колонка --color-bg-alt подпись-заглушка --color-ink-300 по центру («Свободный день» / «Ещё нет конференций»)
Сегодняшняя колонка лёгкая подсветка rgba(212,242,227,.16) (тон --color-accent) заголовок дня --color-ink-700
Чип конференции (default) --color-surface, обводка 1px --color-border бейдж статуса §4.6 сверху, hover → --shadow-sm + --color-border-strong
Чип отменённой конференции как default, opacity: .6 заголовок line-through, --color-ink-500
Закрытая паролем как default иконка Lock инлайн перед названием (см. §4.6)

4.11 Таблица (админка)

Заголовок --color-bg-alt, --text-caption uppercase --color-ink-500. Строки — разделитель 1px --color-border, hover-строка --color-bg-alt. Действия — icon-button (Pencil, Trash2, Mail) 32px, --radius-md.

4.12 Карточка-действие хаба (лобби)

Лобби — хаб из 4 плиток-действий вокруг медальона VidConf (design/mockups/lobby.html), а не список комнат. Фон --color-surface, радиус --radius-3xl, обводка 1px --color-border, тень --shadow-sm. Фиксированная высота (не min-height) у всех 4 плиток — обязательное условие строгой симметрии сетки 2×2 независимо от длины текста внутри.

Тайл 816×340px (при доступной ширине ≥ ~1728px; на меньших вьюпортах, вплоть до --bp-min: 1280px, сетка пропорционально сжимается через width: min(1664px, 100%) на контейнере .hub, оставаясь строго симметричной 2×2, без переполнения); контейнер .hub1664px, gap между тайлами — --space-8 (32px). Типографика внутри: заголовок 40px/1.2 (54px/1.1 для акцентной плитки «Создать»), подпись-объект 21px, примечание 17px.

Медальон-иконка (68px, круг, обводка --border-thick --color-ink-700) вынесен на верхнюю кромку карточки (position: absolute; top: -34px), под него на самой карточке зарезервирован margin-top: 34px. Заголовок --color-ink-700, uppercase; подзаголовок-объект --color-ink-900; примечание --color-ink-500.

Главное действие («Создать») — акцентный вариант на пастельной мяте (--color-accent), текст и медальон — --color-accent-text.

Состояние Фон (обычная / акцентная) Эффект
default --color-surface / --color-accent --shadow-sm
hover тот же / --color-accent-hover --shadow-lg, translateY(-4px)
active тот же / --color-accent-active translateY(-1px)
focus-visible тот же кольцо --color-focus-ring, offset 2px

Медальон VidConf в центре — декоративный (pointer-events: none, aria-hidden), диаметр 156px, фон --color-surface (непрозрачный), обводка --border-thick --color-ink-700, тень --shadow-lg, z-index: 20 (гарантированно поверх карточек). Содержимое — знак объектива logo.svg (56×56px, §1.4) + слово «VidConf» под ним (600 16px var(--font-display), --color-ink-700).

Медальон не просто сидит в промежутке сетки, а лежит поверх равных по величине частей видимых углов всех 4 карточек. Геометрия фиксированная (в пикселях, не в процентах — высота .hub всегда 2×340 + 32 = 712px, независимо от ширины вьюпорта):

  • по горизонтали асимметрии нет — центр строго на границе колонок, 16px (половина gap) до ближнего края каждой карточки;
  • по вертикали — видимый низ карточек ряда 1 на y = 340px от верха .hub, видимый верх карточек ряда 2 на y = 406px (gap 32px + margin-top 34px карточки под собственный медальон-иконку); равноудалённая от обеих точка — y = 373px (33px до каждой), а не геометрический центр сетки 356px (712 / 2), — из-за несимметричного резерва под action-icon только у нижнего ряда.

Медальон центрирован в (50%, 373px) (top: 373px; left: 50%; transform: translate(-50%, -50%)), а не (50%, 50%). Такая точка — зеркально-симметричная по обеим осям относительно всех 4 карточек (что подтверждается тем, что сдвиг 16px/33px — общий для обеих карточек по каждой оси, а не индивидуальный для одной), поэтому перекрытие получается одинаковым на все 4 угла по построению, без ручной подгонки под каждый угол. Проверено headless-рендером (Playwright/Chromium, 1280/1440/1728px): перекрытие видимой (с учётом скругления --radius-3xl, 32px) части каждой из 4 карточек — 29.2px, идентично на всех четырёх и на всех проверенных ширинах вьюпорта (симметрия по x/y — расхождение 0px).

4.13 Карточка создания конференции (календарь)

Фон --color-surface, радиус --radius-2xl, паддинг --space-6, sticky в двухколоночном layout календаря. Поля «Название / Дата / Время / Участники» — стандартный инпут §4.4. Два тумблера общего компонента .switch/.slider (заливка --color-accent-active во включённом состоянии):

  • «Закрытая по паролю» — раскрывает поле пароля под тумблером.
  • «Закрепить постоянную конференцию» — раскрывает блок повторений (§4.14) со всеми 4 вариантами сразу.

Оба раскрытия — чистый CSS через :has() (без JS): тумблер и раскрываемый блок — сиблинги внутри общего .pin-block/.toggle-block, :has(input:checked) .sub-block { display: … }. При адаптации на frontend/ — то же поведение через useState/controlled-компонент.

4.14 Блок повторений (recurrence)

Раскрывается под тумблером «Закрепить постоянную конференцию» (§4.13), отделён 1px dashed --color-border. Список из 4 вариантов (.recurrence-option, radio-группа — выбран ровно один):

Вариант Доп. поля Обязательная подсказка (edge cases)
По дням недели, еженедельно 7 круглых чипов дней недели (34px, множественный выбор) ближайшие 2 даты вхождения
Раз в 2 недели дата начала + день недели ближайшие 2 даты вхождения
Раз в месяц число месяца (131) «если в месяце нет такого числа — переносится на последний день месяца» (31-е число, 29 февраля)
Каждые N дней целое N + дата начала ближайшие даты вхождения («через N, 2N, 3N дней»)

Строка варианта: --radius-md, обводка 1px --color-border → при выборе обводка --color-ink-700 + фон --color-bg-alt (через :has(input:checked), см. §4.13). Под-поля выбранного варианта раскрываются тем же CSS-приёмом; у невыбранных — скрыты (display: none), а не задизейблены — чтобы список из 4 строк был виден целиком сразу после раскрытия тумблера. Выбранный день недели/чип — заливка --color-ink-700, текст белый. Подсказки — 12px, --color-ink-500.

4.15 Пилюли «ссылка / номер» с копированием

Новый компонент «Моих конференций»: у каждой конференции есть постоянная ссылка и человеко-диктуемый номер, доступные для копирования одним кликом. Подпись-заголовок над пилюлей — --text-caption, --color-ink-400 («Ссылка» / «Номер»). Пилюля — --radius-full, фон --color-bg-alt, обводка 1px --color-border; значение — --text-mono-sm --color-ink-700, обрезается text-overflow: ellipsis (для длинных ссылок). Кнопка копирования — круг 28px справа внутри пилюли.

Состояние кнопки копирования Иконка Доп.
default Copy, --color-ink-500
hover Copy, --color-ink-700 --shadow-sm
скопировано (~1.5s) Check, --color-success всплывающая подсказка «Скопировано» над кнопкой
focus-visible как default кольцо --color-focus-ring

Статус «скопировано» не передаётся только сменой цвета иконки — обязательно дублируется сменой формы иконки (CopyCheck) и текстовым тултипом.

4.16 Селект (кастомный выпадающий список)

Заменяет нативный <select> в полях «Рассылка саммари» (карточка создания/редактирования конференции, §4.13) и «Получатели по умолчанию» (настройки админки), а также любой будущий одиночный выбор из списка. Собран из уже утверждённых примитивов — триггер переиспользует геометрию инпута (§4.4), дроплист переиспользует паттерн .menu (выпадающее меню бургера лобби, design/mockups/lobby.html), пункт списка — паттерн .menu a. Ничего нового в токенах не заводится.

Триггер (закрытое состояние). Высота 44px (паддинг 10px 14px + --text-body-lg при line-height: 1.5 — идентично инпуту §4.4, чтобы селект и текстовые поля в одной форме были на одной высоте), фон --color-surface, обводка 1px --color-border, радиус --radius-md. Значение слева, шеврон ChevronDown (18px, --color-ink-500) прижат вправо. Текст — --text-body-lg --color-ink-900; если значение не выбрано — плейсхолдер --color-ink-300 (та же роль токена, что у плейсхолдера инпута).

Состояние Обводка/фон Текст/шеврон Доп.
default --color-border --color-ink-900 / шеврон --color-ink-500
hover --color-border-strong те же курсор pointer
focus-visible (закрыт) 2px --color-focus-ring те же как фокус инпута §4.4
открыт 2px --color-focus-ring, нижние углы дроплиста продолжают радиус триггера визуально (панель — отдельный блок, см. ниже) шеврон повёрнут rotate(180deg), --transition-fast aria-expanded="true"
error 2px --color-danger текст --color-ink-900 текст ошибки под полем + AlertCircle слева от значения, как у инпута §4.4
disabled --color-border, фон --color-bg-alt текст и шеврон --color-ink-300 курсор not-allowed, aria-disabled="true"

Дроплист (открытое состояние). position: absolute, top: calc(100% + 6px), ширина равна триггеру (width: 100%, в отличие от .menu, у которого min-width фиксирован — селект обязан совпадать по ширине с полем, иначе теряется визуальная связь триггер↔панель). Фон --color-surface, обводка 1px --color-border, радиус --radius-lg, тень --shadow-lg, внутренний паддинг --space-2 (8px), z-index: 30 (над соседними карточками формы). Список длиннее ~7 пунктов — max-height: 280px; overflow-y: auto со стандартным скроллбаром (не кастомизируется, см. color-scheme в tokens.css, влияет на нативный скроллбар браузера в обеих темах).

Пункт списка (role="option"): паддинг 10px 14px, радиус --radius-sm, --text-body-lg 400, текст --color-ink-900, display: flex; justify-content: space-between (значение слева, место под иконку Check справа).

Состояние пункта Фон Текст Доп. индикатор
default (не выбран, не наведён) прозрачный --color-ink-900
hover / клавиатурная подсветка (aria-activedescendant) --color-bg-alt --color-ink-700
выбран (aria-selected="true") прозрачный (или --color-bg-alt, если одновременно наведён/подсвечен — состояния комбинируются аддитивно) --color-ink-900, font-weight: 600 иконка Check (16px, --color-ink-700) справа — «выбрано» никогда не передаётся только фоном/цветом
disabled-пункт прозрачный --color-ink-300 cursor: not-allowed, aria-disabled="true", без hover-эффекта

Опциональный разделитель групп внутри списка — тот же приём, что .menu-divider: 1px --color-border, margin: var(--space-2) 6px.

Клавиатурная доступность и ARIA. Паттерн — listbox-combobox (role="combobox" на триггере + role="listbox" на панели), без нативного <select>, чтобы стилизация дроплиста была полностью в токенах проекта.

Действие Клавиша Поведение
Открыть список Enter, Space, ArrowDown, ArrowUp (фокус на триггере, список закрыт) раскрывает дроплист; подсветка ставится на выбранный пункт (если значения ещё нет — на первый)
Навигация ArrowDown / ArrowUp (список открыт) двигает клавиатурную подсветку на следующий/предыдущий пункт (циклически не переходит с последнего на первый), обновляет aria-activedescendant триггера — фокус физически остаётся на триггере
К началу/концу Home / End подсветка на первый/последний доступный (не disabled) пункт
Быстрый переход ввод буквы подсветка прыгает на ближайший следующий пункт, начинающийся с введённого символа (стандартное ожидание пользователей от <select>)
Выбрать и закрыть Enter, Space (на подсвеченном пункте) фиксирует значение, закрывает панель, фокус остаётся на триггере, aria-expanded="false"
Закрыть без изменений Esc закрывает панель, значение не меняется, фокус остаётся на триггере
Закрыть без изменений клик вне триггера/панели, Tab панель закрывается, значение не меняется (если пункт не был явно выбран через Enter/клик)

ARIA-контракт: триггер — role="combobox", aria-haspopup="listbox", aria-expanded, aria-controls="<id панели>", aria-labelledby/aria-label (подпись поля, как у инпута §4.4); панель — role="listbox", aria-activedescendant на триггере указывает на id текущего подсвеченного role="option"; каждый пункт — aria-selected, disabled-пункты — aria-disabled="true" и исключены из навигации стрелками/type-ahead.

Обе темы. Компонент целиком собран из уже описанных выше токенов (--color-surface, --color-border(-strong), --color-ink-*, --color-focus-ring, --color-danger, --shadow-lg, --radius-md/lg/sm), которые уже переключаются между светлой и тёмной оболочкой по механизму §0.1 — отдельной тёмной версии спеки не требуется. Прецедент — .menu (дроплист бургер-меню лобби): его CSS в design/mockups/lobby.html и design/mockups/dark/lobby.html побайтово идентичен, меняется только подстановка переменных из tokens.css; Select использует ту же панель целиком на var(), поэтому корректно рендерится в тёмной теме без правок. В тёмной оболочке фон панели/триггера — графитовый --color-surface (#2A2A2A), подсветка пункта — --color-bg-alt (#242424), выбранный пункт и hover-текст — пастельная мята --color-ink-700 (#7FDDA8), кольцо фокуса — янтарь --color-focus-ring (#D6A83D), см. §1.2b.


5. Доступность

  • Текст ≥ 4.5:1 везде, кроме крупных декоративных элементов (отмечены ⚠︎ выше, ≥ 3:1 по правилу WCAG для large text).
  • Статус всегда дублируется не цветом: иконка (статус конференции §4.6, mic on/off, «скопировано» при копировании ссылки/номера) + текстовая подпись.
  • :focus-visible — везде видимое кольцо (--color-focus-ring светлая тема, --color-room-focus-ring тёмная), никогда outline: none без замены.
  • Интерактивные элементы ≥ 40×40px области клика (кнопки тулбара — 48×48px).
  • Все декоративные SVG-иконки — aria-hidden="true", интерактивные — с aria-label на кнопке-обёртке.
  • Логотип (§1.4) в топбаре — role="img" aria-label="VidConf" на SVG внутри .brand-mark, где рядом уже есть текстовое «VidConf» — SVG физически декоративен (aria-hidden="true" в разметке), словесный знак читает скринридер. Медальон лобби — весь блок aria-hidden="true" (дублирует бренд, не несёт уникальной информации).
  • Аватары с инициалами (§1.5) — текст инициалов всегда светлый (#FFFFFF) на заливке --color-ink-700/--color-ink-500, ≥ 4.5:1 (см. design/tools/contrast.py).

6. Имплементация для frontend-dev

shadcn/ui

Тема подключается через CSS-переменные tokens.css, а не через хардкод в tailwind.config. Компоненты shadcn/ui кастомизировать так:

shadcn/ui компонент Что переопределить Токены
Button варианты default (pill CTA), outline (pill secondary), destructive, ghost (иконки тулбара) --color-accent*, --color-border-pill, --color-danger*, --radius-full
Input, Textarea border/focus/error-состояния --color-border, --color-focus-ring, --color-danger
Card радиус, тень, glass-вариант отдельным классом .card-glass --radius-2xl, --shadow-sm/md, --shadow-glass
Badge варианты success / danger / warning / neutral под статусы конференций (§4.6) цвета из 1.1
Dialog / Sheet модалка брони, панель чата (Sheet справа в тёмной теме) --shadow-lg, --color-room-surface-raised
Select (кастомный, §4.16, не нативный <select>) триггер как Input (§4.4), дроплист — паттерн .menu (лобби) триггер --radius-md; панель --radius-lg + --shadow-lg; пункт --radius-sm; --color-border, --color-focus-ring
Tabs Вход/Регистрация на auth --color-ink-700 активная вкладка, подчёркивание --color-accent-active
Table админка --color-bg-alt заголовок, --color-border разделители
Toggle/ToggleGroup переключатель layout сетки в комнате, кнопки mic/camera активное состояние --color-room-mic-on / --color-room-mic-off
Calendar (FullCalendar, не shadcn) обёртка токенами, ячейки — см. 4.10
Avatar участники комнаты, аватары в лобби/админке --radius-full; заливка/текст инициалов — см. §1.5 (заливка ink-700/ink-500, текст всегда #FFFFFF)
Tooltip подсказки тулбара --color-room-surface-raised

Тёмная тема room включается локальным скоупом (напр. data-theme="room" на контейнере страницы конференции), а не глобальным dark: — остальная оболочка всегда светлая независимо от системной темы ОС.

Иконки — lucide-react, контурные, stroke-width: 2

Экран Иконки
auth Mail, Lock, Eye/EyeOff, User, CheckCircle2 (подтверждён email), ArrowRight
lobby (хаб действий) Video («Создать»), CalendarDays («Календарь»), Link2 («Подключиться»), User («Мои»), бургер-меню: Download, Info, LayoutDashboard, LogOut
room Mic, MicOff, Video, VideoOff, ScreenShare, MessageSquare, PhoneOff (выход), Users, Settings, LayoutGrid, Columns, Grid2x2, Maximize2, MoreVertical, Pin, Send, ChevronLeft/ChevronRight (лента превью)
calendar (менеджер конференций) ChevronLeft/ChevronRight, CalendarDays, Clock, Lock, AlertTriangle, Check, Plus, Repeat (закреплена), Play (идёт сейчас), X (отменена/отмена), ChevronDown (селект «Рассылка саммари», §4.16)
my-conferences Repeat, Clock, CheckCircle2, Users, Copy/Check (копирование), Play («Войти»), Pencil, FileText (саммари), Lock
join Link2, Hash, User, Mail, Lock, Eye/EyeOff, ArrowRight, AlertCircle, Video (карточка целевой конференции)
admin LayoutDashboard, Video, Lock, Users, Mail, Trash2, Pencil, Search, Plus, Send, ChevronDown/Check (селект «Получатели по умолчанию», §4.16)
email-summary инлайн-SVG (email-клиенты не грузят icon-шрифты/JS): CheckCircle2, ListChecks, HelpCircle, BarChart3, стрелка CTA

В HTML-макетах иконки встроены как инлайн-SVG (без иконных шрифтов и CDN); во frontend — заменяются на lucide-react компоненты 1:1 по смыслу.

Файлы

design/tokens.css — источник истины по значениям (используется напрямую или транслируется в tailwind.config.*, см. design/tailwind.md).

Макеты (design/mockups/, единый источник истины по разметке)

  • auth.html — форма входа/регистрации
  • lobby.htmlхаб действий (2×2 плитки)
  • calendar.html — менеджер запланированных конференций
  • my-conferences.html — мои конференции (закреплённые и предстоящие)
  • join.html — подключение по ссылке/номеру → представиться → пароль
  • room.html — конференция (тёмная тема)
  • admin.html — администрирование
  • email-summary.html — экспорт-письмо с транскриптом и резюме (всегда светлое — почтовые клиенты в массе не поддерживают тёмную тему/CSS-переменные, не участвует в переключателе тем оболочки)
  • dark/*.html — тёмный вариант оболочки (6 экранов: login, lobby, calendar, join, my-conferences, admin); палитра — §1.2b, см. dark/README.md за происхождением цветов