Files
vidconf/frontend/src/styles/tokens.css

316 lines
11 KiB
CSS
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.
/*
* 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;
}