Первоначальная версия VidConf

This commit is contained in:
2026-07-23 01:04:01 +03:00
commit 896455381a
335 changed files with 61527 additions and 0 deletions

View File

@@ -0,0 +1,315 @@
/*
* VidConf — design tokens
* ВНИМАНИЕ: это копия design/tokens.css (источник истины — design/DESIGN_SYSTEM.md).
* Файл продублирован во frontend/, т.к. Vite не обслуживает статику вне корня
* проекта. При изменении design/tokens.css копию нужно обновить вручную.
* Значения синхронизированы 1:1.
*
* Три темы, независимые механизмы переключения:
* - Оболочка, светлая (дефолт) — :root.
* - Оболочка, тёмная — :root[data-theme="dark"] (переключатель
* пользователя, см. useTheme/ThemeToggle) ИЛИ автоматически по
* @media (prefers-color-scheme: dark), если data-theme не проставлен
* явно (см. блок ниже; design/mockups/dark/README.md)
* — палитра 1:1 из утверждённых тёмных
* макетов оболочки.
* - Комната конференции — [data-theme="room"] (скоуп на контейнер
* экрана конференции; отдельный неймспейс --color-room-*, НЕ переключается
* системной темой и НЕ смешивается с dark-оболочкой — комната всегда
* тёмная независимо от выбора пользователя).
*
* Шрифты самохостятся через npm-пакеты @fontsource (без внешних CDN —
* инвариант приватности), с кириллическим subset для русского интерфейса.
* @font-face объявляют сами пакеты; их CSS импортируется в
* frontend/src/main.tsx ДО ./index.css. Здесь — только имена семейств в
* переменных ниже (--font-display/--font-body/--font-mono), которые ДОЛЖНЫ
* совпадать с family из @fontsource: 'Unbounded' (@fontsource/unbounded),
* 'Inter' (@fontsource/inter — статический, не variable, у которого было бы
* 'Inter Variable'), 'JetBrains Mono' (@fontsource/jetbrains-mono).
*/
:root {
color-scheme: light;
/* ---------- Типографика ---------- */
--font-display: 'Unbounded', 'Arial Rounded MT Bold', -apple-system, 'Segoe UI', sans-serif;
--font-body: 'Inter', -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
--font-mono: 'JetBrains Mono', 'SFMono-Regular', Menlo, Consolas, monospace;
--text-display-2xl: 700 64px/1.05 var(--font-display);
--text-display-xl: 700 48px/1.1 var(--font-display);
--text-display-lg: 600 34px/1.2 var(--font-display);
--text-h1: 700 28px/1.25 var(--font-body);
--text-h2: 600 22px/1.3 var(--font-body);
--text-h3: 600 18px/1.35 var(--font-body);
--text-body-lg: 400 16px/1.5 var(--font-body);
--text-body: 400 14px/1.5 var(--font-body);
--text-caption: 600 12px/1.4 var(--font-body);
--text-mono-sm: 500 13px/1.4 var(--font-mono);
/* ---------- Spacing (8pt grid, база 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;
/* ---------- Радиусы ---------- */
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 20px;
--radius-2xl: 24px;
--radius-3xl: 32px;
--radius-full: 999px;
/* ---------- Границы ---------- */
--border-thin: 1px;
--border-md: 1.5px;
--border-thick: 2px;
--border-speaker: 3px;
/* ---------- Breakpoints (справочно, desktop-first) ---------- */
--bp-desktop: 1440px;
--bp-min: 1280px;
/* ---------- Motion ---------- */
--transition-fast: 120ms ease;
--transition-base: 200ms ease;
/* ---------- Цвета: светлая тема (оболочка) ---------- */
--color-bg: #F1F1F1;
--color-bg-alt: #F7F7F8;
--color-surface: #FFFFFF;
--color-surface-glass: rgba(255, 255, 255, 0.55);
--color-border: #E1E3E9;
--color-border-strong: #C7CCDC;
--color-border-pill: #4A5A9E;
--color-ink-900: #2E3454;
--color-ink-700: #3B4D95;
--color-ink-500: #535F94;
--color-ink-400: #6976AC;
--color-ink-300: #A6AECB;
/* Пастельная мята — нейтральный акцент оболочки (акцент не обязан
быть зелёным). Mapping см. design/DESIGN_SYSTEM.md §1.1/§1.3. */
--color-accent: #D4F2E3;
--color-accent-hover: #C7EBD9;
--color-accent-active: #BAE4CE;
--color-accent-text: #2E3454;
--color-success: #0A7A4C;
--color-success-bg: #E4F7ED;
--color-success-dot: #46916B;
--color-danger: #C7364F;
--color-danger-bg: #FCE7EB;
--color-danger-dot: #C65366;
--color-warning: #7F560D;
--color-warning-bg: #FBF0DC;
--color-warning-dot: #B58A26;
--color-focus-ring: #3B4D95;
/* ---------- Тени (светлая тема) ---------- */
--shadow-sm: 0 1px 2px rgba(46, 52, 84, 0.06);
--shadow-md: 0 4px 16px rgba(46, 52, 84, 0.08);
--shadow-lg: 0 12px 32px rgba(46, 52, 84, 0.12);
--shadow-glass: 0 8px 24px rgba(59, 77, 149, 0.15);
}
/* =====================================================================
* Тёмная тема: оболочка (auth/лобби/календарь/join/«мои конференции»/админка)
* Утверждено 2026-07-18. Палитра — 1:1 копия блока :root из
* design/mockups/dark/*.html (все 6 файлов идентичны), происхождение каждого
* значения задокументировано в design/mockups/dark/README.md и продублировано
* в design/DESIGN_SYSTEM.md §1.2b. Принцип: тёмная оболочка не изобретает
* новых цветов, а переиспользует уже утверждённые --color-room-* в новых
* ролях (см. таблицу происхождения), поэтому тёмное лобби и тёмная комната
* читаются как одна система.
*
* Механизм активации (два независимых триггера, одни и те же переопределения
* --color-* / --shadow-* — те же имена, что в :root светлой темы выше):
* 1) явный выбор пользователя — атрибут data-theme="dark" на <html>/:root;
* 2) дефолт по системной теме — @media (prefers-color-scheme: dark),
* только пока data-theme НЕ проставлен явно (:root:not([data-theme])).
* Явный data-theme="light" отключает автодетект и форсирует светлую
* тему (базовый :root выше) даже при тёмной ОС.
* Оба блока продублированы намеренно (plain CSS, без препроцессора) — при
* правке палитры менять оба синхронно.
* ===================================================================== */
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) {
color-scheme: dark;
--color-bg: #1E1E1E;
--color-bg-alt: #242424;
--color-surface: #2A2A2A;
--color-surface-glass: rgba(51, 51, 51, 0.55);
--color-border: #3F3F3F;
--color-border-strong: #585858;
--color-border-pill: #7FDDA8;
--color-ink-900: #E8E8E8;
--color-ink-700: #7FDDA8;
--color-ink-500: #B0B0B0;
--color-ink-400: #5D9A78;
--color-ink-300: #7A7A7A;
--color-accent: #7FDDA8;
--color-accent-hover: #75CA9A;
--color-accent-active: #6CB78C;
--color-accent-text: #10331F;
--color-success: #7FDDA8;
--color-success-bg: rgba(127, 221, 168, 0.14);
--color-success-dot: #7FDDA8;
--color-danger: #EB93A1;
--color-danger-bg: rgba(235, 147, 161, 0.14);
--color-danger-dot: #EB93A1;
--color-danger-solid: #B85468;
--color-danger-solid-hover: #B9495F;
--color-warning: #D6A83D;
--color-warning-bg: rgba(214, 168, 61, 0.16);
--color-warning-dot: #D6A83D;
--color-focus-ring: #D6A83D;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.5);
--shadow-glass: 0 8px 24px rgba(0, 0, 0, 0.45);
}
}
:root[data-theme='dark'] {
color-scheme: dark;
--color-bg: #1E1E1E;
--color-bg-alt: #242424;
--color-surface: #2A2A2A;
--color-surface-glass: rgba(51, 51, 51, 0.55);
--color-border: #3F3F3F;
--color-border-strong: #585858;
--color-border-pill: #7FDDA8;
--color-ink-900: #E8E8E8;
--color-ink-700: #7FDDA8;
--color-ink-500: #B0B0B0;
--color-ink-400: #5D9A78;
--color-ink-300: #7A7A7A;
--color-accent: #7FDDA8;
--color-accent-hover: #75CA9A;
--color-accent-active: #6CB78C;
--color-accent-text: #10331F;
--color-success: #7FDDA8;
--color-success-bg: rgba(127, 221, 168, 0.14);
--color-success-dot: #7FDDA8;
--color-danger: #EB93A1;
--color-danger-bg: rgba(235, 147, 161, 0.14);
--color-danger-dot: #EB93A1;
--color-danger-solid: #B85468;
--color-danger-solid-hover: #B9495F;
--color-warning: #D6A83D;
--color-warning-bg: rgba(214, 168, 61, 0.16);
--color-warning-dot: #D6A83D;
--color-focus-ring: #D6A83D;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.5);
--shadow-glass: 0 8px 24px rgba(0, 0, 0, 0.45);
}
/* ---------- Тёмная тема: комната конференции ---------- */
[data-theme='room'] {
color-scheme: dark;
--color-room-bg: #1E1E1E;
--color-room-surface: #2A2A2A;
--color-room-surface-raised: #333333;
--color-room-tile: #363636;
--color-room-tile-border: #3F3F3F;
--color-room-tile-hover: #3D3D3D;
--color-room-text-primary: #E8E8E8;
--color-room-text-secondary: #B0B0B0;
--color-room-text-tertiary: #7A7A7A;
--color-room-mic-on: #7FDDA8;
--color-room-mic-off: #EB93A1;
--color-room-speaker-ring: #D6A83D;
--color-room-danger: #EB93A1;
--color-room-danger-bg: #B85468;
--color-room-danger-bg-hover: #B9495F;
--color-room-focus-ring: #D6A83D;
--shadow-speaker-glow: 0 0 0 3px var(--color-room-speaker-ring), 0 0 24px rgba(214, 168, 61, 0.35);
--shadow-room-panel: 0 8px 24px rgba(0, 0, 0, 0.4);
}
/* ---------- Базовые сбросы, общие для макетов ---------- */
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
font: var(--text-body-lg);
color: var(--color-ink-900);
background: var(--color-bg);
-webkit-font-smoothing: antialiased;
}
[data-theme='room'] body,
[data-theme='room'] {
background: var(--color-room-bg);
color: var(--color-room-text-primary);
}
a { color: inherit; }
button {
font: inherit;
cursor: pointer;
}
:focus-visible {
outline: 2px solid var(--color-focus-ring);
outline-offset: 2px;
}
[data-theme='room'] :focus-visible {
outline-color: var(--color-room-focus-ring);
}
svg.icon {
width: 20px;
height: 20px;
stroke: currentColor;
stroke-width: 2;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
flex-shrink: 0;
}