Первоначальная версия VidConf
This commit is contained in:
232
design/mockups/admin.html
Normal file
232
design/mockups/admin.html
Normal file
@@ -0,0 +1,232 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Админка</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../tokens.css">
|
||||
<style>
|
||||
html { min-width: 1280px; }
|
||||
|
||||
.app-shell { display: flex; min-height: 100vh; }
|
||||
|
||||
/* ---------- Сайдбар ---------- */
|
||||
.sidebar { width: 260px; flex-shrink: 0; background: var(--color-surface); border-right: 1px solid var(--color-border); padding: var(--space-6) var(--space-4); display: flex; flex-direction: column; }
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); padding: 0 var(--space-2); margin-bottom: var(--space-8); }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
|
||||
.side-nav { display: flex; flex-direction: column; gap: 2px; }
|
||||
.side-link {
|
||||
display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: var(--radius-md);
|
||||
font: var(--text-body); font-weight: 600; color: var(--color-ink-500); text-decoration: none;
|
||||
}
|
||||
.side-link:hover { background: var(--color-bg-alt); color: var(--color-ink-900); }
|
||||
.side-link.is-active { background: var(--color-bg-alt); color: var(--color-ink-700); }
|
||||
.side-link .icon { color: inherit; }
|
||||
|
||||
.side-footer { margin-top: auto; padding: var(--space-3) var(--space-2); border-top: 1px solid var(--color-border); }
|
||||
.avatar-btn { display: flex; align-items: center; gap: 8px; padding: 8px 0; width: 100%; background: none; border: none; text-align: left; }
|
||||
.avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--color-ink-700); color: #fff; display:flex; align-items:center; justify-content:center; font: var(--text-caption); text-transform: none; letter-spacing: 0; flex-shrink: 0; }
|
||||
.avatar-btn div strong { display: block; font: var(--text-body); color: var(--color-ink-900); }
|
||||
.avatar-btn div span { font: 12px var(--font-body); color: var(--color-ink-500); }
|
||||
|
||||
/* ---------- Контент ---------- */
|
||||
main { flex: 1; padding: var(--space-8); max-width: 1220px; }
|
||||
.page-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: var(--space-6); }
|
||||
.page-head h1 { font: var(--text-display-lg); font-family: var(--font-display); color: var(--color-ink-700); margin: 0 0 6px; }
|
||||
.page-head p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0; }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; border: none; cursor: pointer; font-family: var(--font-body); white-space: nowrap; transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary { background: var(--color-accent); color: var(--color-accent-text); font: var(--text-body); font-weight: 700; padding: 11px 22px; border-radius: var(--radius-full); }
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-secondary { background: transparent; color: var(--color-ink-700); border: 1.5px solid var(--color-border-pill); font: var(--text-body); font-weight: 600; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); }
|
||||
.btn-danger { background: var(--color-danger); color: #fff; font: var(--text-body); font-weight: 700; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
|
||||
/* Стат-виджеты (glass) */
|
||||
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); margin-bottom: var(--space-8); }
|
||||
.stat-glass {
|
||||
background: var(--color-surface-glass); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
|
||||
border: 1px solid rgba(255,255,255,.7); box-shadow: var(--shadow-glass); border-radius: var(--radius-xl);
|
||||
padding: var(--space-5); background-color: var(--color-bg-alt);
|
||||
}
|
||||
.stat-glass strong { display: block; font: var(--text-display-xl); font-family: var(--font-display); font-size: 36px; color: var(--color-ink-700); }
|
||||
.stat-glass span { font: var(--text-body); color: var(--color-ink-500); }
|
||||
|
||||
/* Табы разделов */
|
||||
.section-tabs { display: flex; gap: var(--space-2); margin-bottom: var(--space-5); border-bottom: 1px solid var(--color-border); }
|
||||
.section-tab { padding: 10px 4px; margin-right: var(--space-6); background: none; border: none; border-bottom: 2px solid transparent; font: var(--text-body-lg); font-weight: 600; color: var(--color-ink-500); }
|
||||
.section-tab.is-active { color: var(--color-ink-700); border-color: var(--color-accent-active); }
|
||||
|
||||
.toolbar-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-5); gap: var(--space-4); }
|
||||
.search-wrap { position: relative; width: 320px; }
|
||||
.search-wrap .icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--color-ink-400); }
|
||||
.search-wrap input { width: 100%; font: var(--text-body); padding: 9px 12px 9px 38px; border-radius: var(--radius-full); border: 1px solid var(--color-border); background: var(--color-surface); }
|
||||
.search-wrap input:focus { outline: none; border-color: var(--color-focus-ring); }
|
||||
|
||||
/* Таблица */
|
||||
.table-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); overflow: hidden; margin-bottom: var(--space-8); }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
thead th { text-align: left; background: var(--color-bg-alt); font: var(--text-caption); color: var(--color-ink-500); padding: 12px 20px; text-transform: uppercase; }
|
||||
tbody td { padding: 14px 20px; font: var(--text-body-lg); color: var(--color-ink-900); border-top: 1px solid var(--color-border); }
|
||||
tbody tr:hover { background: var(--color-bg-alt); }
|
||||
|
||||
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: var(--radius-full); font: var(--text-caption); white-space: nowrap; }
|
||||
.badge-free { background: var(--color-success-bg); color: var(--color-success); }
|
||||
.badge-busy { background: var(--color-danger-bg); color: var(--color-danger); }
|
||||
.badge-booked { background: var(--color-warning-bg); color: var(--color-warning); }
|
||||
.badge-locked { background: var(--color-bg-alt); color: var(--color-ink-700); }
|
||||
.badge-role-admin { background: var(--color-ink-700); color: #fff; }
|
||||
.badge-role-user { background: var(--color-bg-alt); color: var(--color-ink-500); }
|
||||
|
||||
.row-actions { display: flex; gap: 6px; }
|
||||
.icon-btn { width: 32px; height: 32px; border-radius: var(--radius-md); border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-ink-500); display:flex; align-items:center; justify-content:center; }
|
||||
.icon-btn:hover { border-color: var(--color-border-strong); color: var(--color-ink-900); }
|
||||
.icon-btn.danger:hover { border-color: var(--color-danger); color: var(--color-danger); background: var(--color-danger-bg); }
|
||||
|
||||
.user-cell { display: flex; align-items: center; gap: 10px; }
|
||||
.user-cell .avatar { width: 32px; height: 32px; font-size: 12px; }
|
||||
.user-cell div span { display: block; font: 13px var(--font-body); color: var(--color-ink-500); }
|
||||
|
||||
/* Секция рассылки */
|
||||
.invite-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); display: grid; grid-template-columns: 1fr 320px; gap: var(--space-8); }
|
||||
.invite-card h2 { font: var(--text-h2); margin: 0 0 4px; color: var(--color-ink-900); }
|
||||
.invite-card p.desc { font: var(--text-body); color: var(--color-ink-500); margin: 0 0 var(--space-5); }
|
||||
.invite-card textarea {
|
||||
width: 100%; min-height: 140px; font: var(--text-body-lg); color: var(--color-ink-900); font-family: var(--font-mono);
|
||||
padding: 14px; border-radius: var(--radius-md); border: 1px solid var(--color-border); background: var(--color-surface); resize: vertical;
|
||||
}
|
||||
.invite-card textarea:focus { outline: none; border-color: var(--color-focus-ring); }
|
||||
.invite-side { background: var(--color-bg-alt); border-radius: var(--radius-xl); padding: var(--space-5); }
|
||||
.invite-side h3 { font: var(--text-h3); margin: 0 0 var(--space-3); color: var(--color-ink-900); }
|
||||
.invite-side ul { margin: 0 0 var(--space-5); padding-left: 18px; font: var(--text-body); color: var(--color-ink-500); }
|
||||
.invite-side li { margin-bottom: 6px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-dashboard" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="9" rx="1"/><rect x="14" y="3" width="7" height="5" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/><rect x="3" y="16" width="7" height="5" rx="1"/></symbol>
|
||||
<symbol id="i-video" viewBox="0 0 24 24"><rect x="2" y="6" width="14" height="12" rx="2"/><path d="m22 8-6 4 6 4V8Z"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-users" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>
|
||||
<symbol id="i-mail" viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 6 10 7 10-7"/></symbol>
|
||||
<symbol id="i-search" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></symbol>
|
||||
<symbol id="i-plus" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></symbol>
|
||||
<symbol id="i-pencil" viewBox="0 0 24 24"><path d="M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></symbol>
|
||||
<symbol id="i-trash" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></symbol>
|
||||
<symbol id="i-send" viewBox="0 0 24 24"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></symbol>
|
||||
<symbol id="i-check-circle" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></symbol>
|
||||
<symbol id="i-ban" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="4.9" y1="4.9" x2="19.1" y2="19.1"/></symbol>
|
||||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
||||
</svg>
|
||||
|
||||
<div class="app-shell">
|
||||
|
||||
<aside class="sidebar">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
<nav class="side-nav">
|
||||
<a class="side-link is-active" href="#rooms"><svg class="icon" style="width:18px;height:18px"><use href="#i-video"/></svg>Конференции</a>
|
||||
<a class="side-link" href="#closed"><svg class="icon" style="width:18px;height:18px"><use href="#i-lock"/></svg>Закрытые конференции</a>
|
||||
<a class="side-link" href="#users"><svg class="icon" style="width:18px;height:18px"><use href="#i-users"/></svg>Пользователи</a>
|
||||
<a class="side-link" href="#invites"><svg class="icon" style="width:18px;height:18px"><use href="#i-mail"/></svg>Рассылка приглашений</a>
|
||||
</nav>
|
||||
<div class="side-footer">
|
||||
<button class="avatar-btn"><span class="avatar">АИ</span><div><strong>Анна Иванова</strong><span>Администратор</span></div></button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main>
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>Администрирование</h1>
|
||||
<p>Управление конференциями, доступом и пользователями VidConf</p>
|
||||
</div>
|
||||
<button class="btn btn-primary"><svg class="icon" style="width:16px;height:16px"><use href="#i-plus"/></svg>Добавить конференцию</button>
|
||||
</div>
|
||||
|
||||
<section class="stat-grid">
|
||||
<div class="stat-glass"><strong>100</strong><span>Всего конференций</span></div>
|
||||
<div class="stat-glass"><strong>12</strong><span>Активны сейчас</span></div>
|
||||
<div class="stat-glass"><strong>34</strong><span>Забронировано сегодня</span></div>
|
||||
<div class="stat-glass"><strong>248</strong><span>Пользователей</span></div>
|
||||
</section>
|
||||
|
||||
<div class="section-tabs">
|
||||
<button class="section-tab is-active">Конференции</button>
|
||||
<button class="section-tab">Закрытые конференции</button>
|
||||
<button class="section-tab">Пользователи</button>
|
||||
<button class="section-tab">Рассылка приглашений</button>
|
||||
</div>
|
||||
|
||||
<!-- ===================== КОНФЕРЕНЦИИ ===================== -->
|
||||
<div class="toolbar-row">
|
||||
<div class="search-wrap"><svg class="icon"><use href="#i-search"/></svg><input type="text" placeholder="Поиск конференции…"></div>
|
||||
<span style="font:14px var(--font-body); color:var(--color-ink-500)">Показано 6 из 100</span>
|
||||
</div>
|
||||
|
||||
<div class="table-card">
|
||||
<table>
|
||||
<thead><tr><th>Конференция</th><th>Вместимость</th><th>Статус</th><th>Тип</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>Переговорная №01</td><td>8 мест</td><td><span class="badge badge-free"><svg class="icon" style="width:12px;height:12px"><use href="#i-check-circle"/></svg>Свободна</span></td><td>Открытая</td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td></tr>
|
||||
<tr><td>Переговорная №02</td><td>10 мест</td><td><span class="badge badge-busy"><svg class="icon" style="width:12px;height:12px"><use href="#i-ban"/></svg>Занята</span></td><td>Открытая</td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td></tr>
|
||||
<tr><td>Переговорная №04</td><td>12 мест</td><td><span class="badge badge-locked"><svg class="icon" style="width:12px;height:12px"><use href="#i-lock"/></svg>По паролю</span></td><td>Закрытая</td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td></tr>
|
||||
<tr><td>Переговорная №42</td><td>16 мест</td><td><span class="badge badge-booked"><svg class="icon" style="width:12px;height:12px"><use href="#i-clock"/></svg>Забронирована</span></td><td>Открытая</td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- ===================== ПОЛЬЗОВАТЕЛИ ===================== -->
|
||||
<div class="page-head" style="margin-bottom: var(--space-4)"><h2 style="font:var(--text-h2); color:var(--color-ink-900); margin:0">Пользователи</h2></div>
|
||||
<div class="table-card">
|
||||
<table>
|
||||
<thead><tr><th>Пользователь</th><th>Роль</th><th>Регистрация</th><th>Статус</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><div class="user-cell"><span class="avatar">АИ</span><div>Анна Иванова<span>a.ivanova@vidconf.dev</span></div></div></td>
|
||||
<td><span class="badge badge-role-admin">Администратор</span></td>
|
||||
<td>03.02.2026</td>
|
||||
<td><span class="badge badge-free"><svg class="icon" style="width:12px;height:12px"><use href="#i-check-circle"/></svg>Активен</span></td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div class="user-cell"><span class="avatar">МК</span><div>Мария Кузнецова<span>m.kuznetsova@company.ru</span></div></div></td>
|
||||
<td><span class="badge badge-role-user">Пользователь</span></td>
|
||||
<td>15.07.2026</td>
|
||||
<td><span class="badge badge-booked"><svg class="icon" style="width:12px;height:12px"><use href="#i-clock"/></svg>Ждёт подтверждения</span></td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- ===================== РАССЫЛКА ПРИГЛАШЕНИЙ ===================== -->
|
||||
<div class="page-head" style="margin-bottom: var(--space-4)"><h2 style="font:var(--text-h2); color:var(--color-ink-900); margin:0">Рассылка приглашений</h2></div>
|
||||
<div class="invite-card">
|
||||
<div>
|
||||
<h2>Пригласить новых пользователей</h2>
|
||||
<p class="desc">Каждый адрес получит письмо со ссылкой регистрации, действительной 7 дней.</p>
|
||||
<textarea placeholder="i.sokolov@company.ru o.panina@company.ru v.sedykh@company.ru">i.sokolov@company.ru
|
||||
o.panina@company.ru
|
||||
v.sedykh@company.ru</textarea>
|
||||
<button class="btn btn-primary" style="margin-top: var(--space-4)"><svg class="icon" style="width:16px;height:16px"><use href="#i-send"/></svg>Отправить приглашения (3)</button>
|
||||
</div>
|
||||
<div class="invite-side">
|
||||
<h3>Последняя рассылка</h3>
|
||||
<ul>
|
||||
<li>28.06.2026 · 12 приглашений</li>
|
||||
<li>9 приняли, 3 ожидают</li>
|
||||
</ul>
|
||||
<button class="btn btn-secondary" style="width:100%; justify-content:center">Посмотреть журнал</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
330
design/mockups/auth.html
Normal file
330
design/mockups/auth.html
Normal file
@@ -0,0 +1,330 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Вход / Регистрация / Подтверждение email</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../tokens.css">
|
||||
<style>
|
||||
html { min-width: 1280px; }
|
||||
body { min-height: 100vh; }
|
||||
|
||||
.layout { display: flex; min-height: 100vh; }
|
||||
|
||||
/* ---------- Брендовая панель ---------- */
|
||||
.brand-panel {
|
||||
width: 42%;
|
||||
background: linear-gradient(160deg, #EDEFFA 0%, #F1F1F1 55%, #F7F7F8 100%);
|
||||
padding: var(--space-12) var(--space-12);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-right: 1px solid var(--color-border);
|
||||
}
|
||||
.brand-panel::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -120px; bottom: -120px;
|
||||
width: 380px; height: 380px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 30% 30%, rgba(212,242,227,.45), rgba(212,242,227,0) 70%);
|
||||
}
|
||||
.brand-mark {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
font: var(--text-h3);
|
||||
color: var(--color-ink-700);
|
||||
z-index: 1;
|
||||
}
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
|
||||
.brand-copy { z-index: 1; }
|
||||
.eyebrow {
|
||||
font: var(--text-caption);
|
||||
letter-spacing: .08em;
|
||||
color: var(--color-ink-400);
|
||||
margin: 0 0 var(--space-4);
|
||||
}
|
||||
.brand-headline {
|
||||
font: var(--text-display-lg);
|
||||
font-family: var(--font-display);
|
||||
color: var(--color-ink-700);
|
||||
margin: 0 0 var(--space-4);
|
||||
max-width: 460px;
|
||||
}
|
||||
.brand-sub {
|
||||
font: var(--text-body-lg);
|
||||
color: var(--color-ink-500);
|
||||
max-width: 420px;
|
||||
margin: 0;
|
||||
}
|
||||
.brand-stats { display: flex; gap: var(--space-4); z-index: 1; margin-top: var(--space-8); }
|
||||
.stat-glass {
|
||||
background: var(--color-surface-glass);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
border: 1px solid rgba(255,255,255,.7);
|
||||
box-shadow: var(--shadow-glass);
|
||||
border-radius: var(--radius-xl);
|
||||
padding: var(--space-4) var(--space-5);
|
||||
min-width: 140px;
|
||||
}
|
||||
.stat-glass strong { display: block; font: var(--text-h1); font-family: var(--font-display); color: var(--color-ink-700); }
|
||||
.stat-glass span { font: var(--text-caption); color: var(--color-ink-500); text-transform: none; letter-spacing: normal; }
|
||||
|
||||
/* ---------- Форма-панель ---------- */
|
||||
.form-panel {
|
||||
width: 58%;
|
||||
padding: var(--space-12) var(--space-16);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-16);
|
||||
}
|
||||
.screen-block { max-width: 440px; }
|
||||
.screen-label {
|
||||
font: var(--text-caption);
|
||||
color: var(--color-ink-400);
|
||||
margin: 0 0 var(--space-3);
|
||||
}
|
||||
.screen-label b { color: var(--color-ink-700); }
|
||||
.screen-title { font: var(--text-h1); color: var(--color-ink-900); margin: 0 0 var(--space-8); }
|
||||
|
||||
.divider { border: none; border-top: 1px solid var(--color-border); max-width: 720px; margin: 0; }
|
||||
|
||||
.tabs { display: flex; gap: var(--space-2); margin-bottom: var(--space-6); background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); width: fit-content; }
|
||||
.tab { padding: 8px 20px; border-radius: var(--radius-full); border: none; background: transparent; font: var(--text-body); color: var(--color-ink-500); }
|
||||
.tab.is-active { background: var(--color-surface); color: var(--color-ink-700); font-weight: 600; box-shadow: var(--shadow-sm); }
|
||||
|
||||
.field { margin-bottom: var(--space-5); }
|
||||
.field label { display: block; font: var(--text-body); font-weight: 600; color: var(--color-ink-900); margin-bottom: var(--space-2); }
|
||||
.input-wrap { position: relative; }
|
||||
.input-wrap .icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--color-ink-400); }
|
||||
.input-wrap input {
|
||||
width: 100%;
|
||||
font: var(--text-body-lg);
|
||||
color: var(--color-ink-900);
|
||||
padding: 11px 14px 11px 42px;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
outline: none;
|
||||
}
|
||||
.input-wrap input::placeholder { color: var(--color-ink-300); }
|
||||
.input-wrap input:hover { border-color: var(--color-border-strong); }
|
||||
.input-wrap input:focus { border-color: var(--color-focus-ring); box-shadow: 0 0 0 3px rgba(59,77,149,.12); }
|
||||
.input-wrap .toggle-eye { left: auto; right: 14px; background: none; border: none; padding: 0; cursor: pointer; }
|
||||
|
||||
.field.has-error input { border-color: var(--color-danger); box-shadow: 0 0 0 3px rgba(199,54,79,.1); }
|
||||
.error-msg { display: flex; align-items: center; gap: 6px; margin-top: var(--space-2); font: var(--text-body); color: var(--color-danger); }
|
||||
.hint-msg { margin-top: var(--space-2); font: var(--text-body); color: var(--color-ink-500); }
|
||||
|
||||
.field-disabled input { background: var(--color-bg-alt); color: var(--color-ink-300); cursor: not-allowed; }
|
||||
|
||||
.row-between { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-6); }
|
||||
.checkbox-row { display: flex; align-items: center; gap: 8px; font: var(--text-body); color: var(--color-ink-500); }
|
||||
.link { color: var(--color-ink-700); font-weight: 600; text-decoration: none; }
|
||||
.link:hover { text-decoration: underline; }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; border: none; cursor: pointer; font-family: var(--font-body); transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary {
|
||||
width: 100%;
|
||||
background: var(--color-accent);
|
||||
color: var(--color-accent-text);
|
||||
font: var(--text-body-lg);
|
||||
font-weight: 700;
|
||||
padding: 13px 24px;
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-primary:active { background: var(--color-accent-active); }
|
||||
.btn-primary[disabled] { background: rgba(166,174,203,.4); color: var(--color-surface); cursor: not-allowed; }
|
||||
|
||||
.btn-secondary {
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
color: var(--color-ink-700);
|
||||
border: 1.5px solid var(--color-border-pill);
|
||||
font: var(--text-body-lg);
|
||||
font-weight: 600;
|
||||
padding: 12px 24px;
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); border-color: var(--color-ink-700); }
|
||||
|
||||
.oauth-row { display: flex; gap: var(--space-3); margin-top: var(--space-5); }
|
||||
.oauth-row .btn-secondary { flex: 1; }
|
||||
|
||||
.separator { display: flex; align-items: center; gap: 12px; color: var(--color-ink-400); font: var(--text-caption); margin: var(--space-6) 0; text-transform: none; letter-spacing: normal; }
|
||||
.separator::before, .separator::after { content: ""; flex: 1; height: 1px; background: var(--color-border); }
|
||||
|
||||
/* ---------- Подтверждение email ---------- */
|
||||
.confirm-card {
|
||||
max-width: 440px;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-2xl);
|
||||
padding: var(--space-8);
|
||||
text-align: left;
|
||||
}
|
||||
.confirm-icon {
|
||||
width: 56px; height: 56px; border-radius: var(--radius-full);
|
||||
background: var(--color-success-bg); color: var(--color-success);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
margin-bottom: var(--space-5);
|
||||
}
|
||||
.confirm-icon .icon { width: 28px; height: 28px; }
|
||||
.confirm-card h3 { font: var(--text-h2); color: var(--color-ink-900); margin: 0 0 var(--space-2); }
|
||||
.confirm-card p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0 0 var(--space-6); }
|
||||
.confirm-card .mail-chip {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
background: var(--color-bg-alt); border-radius: var(--radius-full);
|
||||
padding: 6px 14px; font: var(--text-mono-sm); color: var(--color-ink-700);
|
||||
margin-bottom: var(--space-6);
|
||||
}
|
||||
|
||||
/* pending confirmation state variant */
|
||||
.confirm-card.pending .confirm-icon { background: var(--color-warning-bg); color: var(--color-warning); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-mail" viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 6 10 7 10-7"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-user" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M6 21v-2a6 6 0 0 1 12 0v2"/></symbol>
|
||||
<symbol id="i-eye" viewBox="0 0 24 24"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></symbol>
|
||||
<symbol id="i-eye-off" viewBox="0 0 24 24"><path d="M3 3l18 18"/><path d="M10.58 10.58a2 2 0 0 0 2.83 2.83"/><path d="M9.88 5.09A9.77 9.77 0 0 1 12 5c6.5 0 10 7 10 7a13.16 13.16 0 0 1-3.06 4.06M6.1 6.1A13.16 13.16 0 0 0 2 12s3.5 7 10 7a9.77 9.77 0 0 0 4.9-1.3"/></symbol>
|
||||
<symbol id="i-check-circle" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></symbol>
|
||||
<symbol id="i-arrow-right" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></symbol>
|
||||
<symbol id="i-alert" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></symbol>
|
||||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
||||
</svg>
|
||||
|
||||
<div class="layout">
|
||||
|
||||
<!-- ===================== БРЕНД-ПАНЕЛЬ ===================== -->
|
||||
<aside class="brand-panel">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
<div class="brand-copy">
|
||||
<p class="eyebrow">[ SELF-HOSTED ВИДЕОКОНФЕРЕНЦИИ ]</p>
|
||||
<h1 class="brand-headline">Ваши встречи.<br>Ваша инфраструктура.</h1>
|
||||
<p class="brand-sub">Видео, записи и AI-саммари обрабатываются на ваших серверах - данные не уходят
|
||||
за пределы вашей инфраструктуры. Гости подключаются по ссылке или номеру, без регистрации.</p>
|
||||
<div class="brand-stats">
|
||||
<div class="stat-glass"><strong>100%</strong><span>данных - в вашем контуре</span></div>
|
||||
<div class="stat-glass"><strong>AI-саммари</strong><span>на почту после встречи</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="hint-msg" style="z-index:1">© 2026 VidConf · self-hosted</p>
|
||||
</aside>
|
||||
|
||||
<!-- ===================== ФОРМА: ВХОД / РЕГИСТРАЦИЯ ===================== -->
|
||||
<main class="form-panel">
|
||||
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>вход в аккаунт</b></p>
|
||||
<div class="tabs" role="tablist" aria-label="Способ авторизации">
|
||||
<button class="tab is-active" role="tab" aria-selected="true">Вход</button>
|
||||
<button class="tab" role="tab" aria-selected="false">Регистрация</button>
|
||||
</div>
|
||||
|
||||
<form>
|
||||
<div class="field">
|
||||
<label for="login-email">Рабочая почта</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-mail"/></svg>
|
||||
<input id="login-email" type="email" placeholder="you@company.ru" value="a.ivanova@vidconf.dev">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field has-error">
|
||||
<label for="login-pass">Пароль</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-lock"/></svg>
|
||||
<input id="login-pass" type="password" placeholder="••••••••" value="wrongpass">
|
||||
<button type="button" class="toggle-eye" aria-label="Показать пароль">
|
||||
<svg class="icon"><use href="#i-eye"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="error-msg"><svg class="icon" style="width:16px;height:16px"><use href="#i-alert"/></svg> Неверный email или пароль</p>
|
||||
</div>
|
||||
|
||||
<div class="row-between">
|
||||
<label class="checkbox-row"><input type="checkbox" checked> Запомнить меня</label>
|
||||
<a href="#" class="link">Забыли пароль?</a>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Войти <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>регистрация</b></p>
|
||||
<h2 class="screen-title">Создать аккаунт</h2>
|
||||
<form>
|
||||
<div class="field">
|
||||
<label for="reg-name">Имя и фамилия</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-user"/></svg>
|
||||
<input id="reg-name" type="text" placeholder="Мария Кузнецова">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="reg-email">Рабочая почта</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-mail"/></svg>
|
||||
<input id="reg-email" type="email" placeholder="you@company.ru">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="reg-pass">Пароль</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-lock"/></svg>
|
||||
<input id="reg-pass" type="password" placeholder="Минимум 8 символов">
|
||||
<button type="button" class="toggle-eye" aria-label="Скрыть пароль">
|
||||
<svg class="icon"><use href="#i-eye-off"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="hint-msg">Минимум 8 символов, буквы и цифры</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="margin-top:8px">Зарегистрироваться</button>
|
||||
<div class="separator">или</div>
|
||||
<div class="field field-disabled" style="margin-bottom:0">
|
||||
<label for="reg-invite">Код приглашения (недоступно без администратора)</label>
|
||||
<div class="input-wrap">
|
||||
<input id="reg-invite" type="text" placeholder="INVITE-XXXX-XXXX" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>подтверждение email</b></p>
|
||||
|
||||
<div class="confirm-card" style="margin-bottom: var(--space-6);">
|
||||
<div class="confirm-icon"><svg class="icon"><use href="#i-check-circle"/></svg></div>
|
||||
<h3>Почта подтверждена</h3>
|
||||
<p>Аккаунт <strong>a.ivanova@vidconf.dev</strong> активирован. Теперь
|
||||
доступно бронирование переговорных и вход в конференции.</p>
|
||||
<button class="btn btn-primary">Перейти в лобби <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</div>
|
||||
|
||||
<div class="confirm-card pending">
|
||||
<div class="confirm-icon"><svg class="icon"><use href="#i-clock"/></svg></div>
|
||||
<h3>Подтвердите почту</h3>
|
||||
<p>Мы отправили письмо со ссылкой на <span class="mail-chip"><svg class="icon" style="width:14px;height:14px"><use href="#i-mail"/></svg>m.kuznetsova@company.ru</span></p>
|
||||
<button class="btn btn-secondary">Отправить письмо повторно</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
507
design/mockups/calendar.html
Normal file
507
design/mockups/calendar.html
Normal file
@@ -0,0 +1,507 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Календарь конференций</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../tokens.css">
|
||||
<style>
|
||||
/*
|
||||
* Календарь — менеджер ЗАПЛАНИРОВАННЫХ КОНФЕРЕНЦИЙ (фаза R1, пивот),
|
||||
* не бронирование комнат: комнат больше нет, поэтому легенда
|
||||
* «занято/выбрано» и привязка к конкретной переговорной убраны.
|
||||
* Слева — сетка недели (5 дневных колонок) со списком конференций по дням,
|
||||
* справа — карточка создания со «Закрепить постоянную конференцию»
|
||||
* (раскрывает 4 варианта повторения). Ниже — доп. состояния:
|
||||
* редактирование закреплённой и отмена вхождения/всех повторений.
|
||||
* Интерактивность toggle/recurrence — чистый CSS (:has()), без JS,
|
||||
* по образцу .switch в исходном calendar.html (входное состояние — CSS).
|
||||
*/
|
||||
|
||||
html { min-width: 1280px; }
|
||||
|
||||
.topbar {
|
||||
position: sticky; top: 0; z-index: 20;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: var(--space-4) var(--space-8);
|
||||
background: var(--color-surface);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
.topbar-right { display: flex; align-items: center; gap: var(--space-5); }
|
||||
.nav-link { font: var(--text-body); font-weight: 600; color: var(--color-ink-500); text-decoration: none; }
|
||||
.nav-link.is-active { color: var(--color-ink-700); }
|
||||
.avatar-btn { display: flex; align-items: center; gap: 8px; background: var(--color-bg-alt); border: 1px solid var(--color-border); border-radius: var(--radius-full); padding: 6px 14px 6px 6px; }
|
||||
.avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--color-ink-700); color: #fff; display:flex; align-items:center; justify-content:center; font: var(--text-caption); text-transform: none; letter-spacing: 0; }
|
||||
/* Каскад-баг гейта (2026-07-16, 3-я итерация): было `.avatar-btn span`
|
||||
(0,1,1) — перебивало `.avatar { color:#fff }` (0,1,0), инициалы
|
||||
рендерились тёмным ink-900 на индиго-заливке (нечитаемо). Селектор имени
|
||||
сделан адресным — задевает только `.user-name`, не пересекается с
|
||||
`.avatar` ни при каком порядке правил. См. DESIGN_SYSTEM.md §1.5. */
|
||||
.avatar-btn .user-name { font: var(--text-body); font-weight: 600; color: var(--color-ink-900); }
|
||||
|
||||
main { padding: var(--space-8); max-width: 1440px; margin: 0 auto; }
|
||||
|
||||
.page-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: var(--space-6); }
|
||||
.page-head h1 { font: var(--text-display-lg); font-family: var(--font-display); color: var(--color-ink-700); margin: 0 0 6px; }
|
||||
.page-head p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0; max-width: 560px; }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; border: none; cursor: pointer; font-family: var(--font-body); white-space: nowrap; transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary { background: var(--color-accent); color: var(--color-accent-text); font: var(--text-body); font-weight: 700; padding: 11px 22px; border-radius: var(--radius-full); }
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-primary:active { background: var(--color-accent-active); }
|
||||
.btn-primary:disabled { background: rgba(166,174,203,.35); color: var(--color-surface); cursor: not-allowed; }
|
||||
.btn-secondary { background: transparent; color: var(--color-ink-700); border: 1.5px solid var(--color-border-pill); font: var(--text-body); font-weight: 600; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); }
|
||||
.btn-danger { background: var(--color-danger); color: #fff; font: var(--text-body); font-weight: 700; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
.btn-danger:hover { filter: brightness(0.92); }
|
||||
.btn-text { background: none; border: none; color: var(--color-danger); font: var(--text-body); font-weight: 600; padding: 4px; }
|
||||
.btn-text:hover { text-decoration: underline; }
|
||||
.btn.full { width: 100%; justify-content: center; }
|
||||
:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
|
||||
|
||||
/* ---------- Основной грид: неделя + карточка создания ---------- */
|
||||
.layout-grid { display: grid; grid-template-columns: 1fr 400px; gap: var(--space-6); align-items: start; }
|
||||
|
||||
.week-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); }
|
||||
.week-toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-5); }
|
||||
.date-nav { display: flex; align-items: center; gap: var(--space-3); }
|
||||
.date-nav button { width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-ink-500); display:flex; align-items:center; justify-content:center; }
|
||||
.date-nav button:hover { border-color: var(--color-border-strong); color: var(--color-ink-900); }
|
||||
.date-nav span { font: var(--text-h3); color: var(--color-ink-900); min-width: 200px; text-align: center; }
|
||||
.view-toggle { display: flex; gap: 4px; background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); }
|
||||
.view-toggle button { padding: 7px 16px; border-radius: var(--radius-full); border: none; background: transparent; font: var(--text-body); font-weight: 600; color: var(--color-ink-500); }
|
||||
.view-toggle button.is-active { background: var(--color-surface); color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
|
||||
.week-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--space-4); }
|
||||
.day-col { background: var(--color-bg-alt); border-radius: var(--radius-lg); padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); min-height: 460px; }
|
||||
.day-col.is-today { background: rgba(212,242,227,.16); }
|
||||
.day-col-head { text-align: center; padding-bottom: var(--space-2); margin-bottom: var(--space-1); border-bottom: 1px solid var(--color-border); }
|
||||
.day-col-head .dow { display: block; font: var(--text-caption); color: var(--color-ink-500); }
|
||||
.day-col-head .dom { display: block; font: var(--text-h3); color: var(--color-ink-900); margin-top: 2px; }
|
||||
.day-col.is-today .day-col-head .dom { color: var(--color-ink-700); }
|
||||
|
||||
.conf-chip { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-3); display: flex; flex-direction: column; gap: 4px; cursor: pointer; transition: box-shadow var(--transition-fast), border-color var(--transition-fast); text-align: left; }
|
||||
.conf-chip:hover { box-shadow: var(--shadow-sm); border-color: var(--color-border-strong); }
|
||||
.chip-time { display: flex; align-items: center; gap: 4px; font: var(--text-caption); color: var(--color-ink-500); text-transform: none; letter-spacing: normal; }
|
||||
.chip-title { display: flex; align-items: center; gap: 6px; font: var(--text-body); font-weight: 700; color: var(--color-ink-900); }
|
||||
.chip-meta { display: flex; align-items: center; gap: 10px; font: 12px var(--font-body); color: var(--color-ink-500); }
|
||||
.chip-meta .meta-item { display: flex; align-items: center; gap: 4px; }
|
||||
|
||||
.conf-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: var(--radius-full); font: var(--text-caption); font-size: 11px; width: fit-content; }
|
||||
.conf-badge.scheduled { background: var(--color-warning-bg); color: var(--color-warning); }
|
||||
.conf-badge.pinned { background: var(--color-bg-alt); color: var(--color-ink-700); border: 1px solid var(--color-border-strong); }
|
||||
.conf-badge.live { background: var(--color-success-bg); color: var(--color-success); }
|
||||
.conf-badge.cancelled { background: var(--color-danger-bg); color: var(--color-danger); }
|
||||
|
||||
.conf-chip.is-cancelled { opacity: .6; }
|
||||
.conf-chip.is-cancelled .chip-title { text-decoration: line-through; color: var(--color-ink-500); }
|
||||
|
||||
.day-empty { flex: 1; display: flex; align-items: center; justify-content: center; text-align: center; font: var(--text-body); color: var(--color-ink-300); padding: var(--space-4) 0; }
|
||||
|
||||
/* ---------- Карточка создания / редактирования ---------- */
|
||||
.create-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); position: sticky; top: 96px; }
|
||||
.create-card h2 { font: var(--text-h2); color: var(--color-ink-900); margin: 0 0 var(--space-5); display: flex; align-items: center; gap: 8px; }
|
||||
|
||||
.field { margin-bottom: var(--space-5); }
|
||||
.field label { display: flex; align-items: center; gap: 6px; font: var(--text-body); font-weight: 600; color: var(--color-ink-900); margin-bottom: var(--space-2); }
|
||||
.field input, .field textarea, .field select {
|
||||
width: 100%; font: var(--text-body-lg); color: var(--color-ink-900);
|
||||
padding: 10px 14px; border-radius: var(--radius-md); border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
}
|
||||
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--color-focus-ring); box-shadow: 0 0 0 3px rgba(59,77,149,.12); }
|
||||
.field-row { display: flex; gap: var(--space-3); }
|
||||
.field-row .field { flex: 1; }
|
||||
.field-hint { font: 12px var(--font-body); color: var(--color-ink-500); margin: 6px 2px 0; }
|
||||
|
||||
/* Тумблер (используется и для «закрытая по паролю», и для «закрепить») */
|
||||
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) 0; border-top: 1px solid var(--color-border); }
|
||||
.toggle-copy strong { display: block; font: var(--text-body); color: var(--color-ink-900); }
|
||||
.toggle-copy span { font: 12px var(--font-body); color: var(--color-ink-500); }
|
||||
.switch { position: relative; width: 44px; height: 24px; flex-shrink: 0; }
|
||||
.switch input { opacity: 0; width: 0; height: 0; }
|
||||
.slider { position: absolute; inset: 0; background: var(--color-border-strong); border-radius: var(--radius-full); transition: background var(--transition-fast); cursor: pointer; }
|
||||
.slider::before { content:""; position:absolute; width:18px; height:18px; left:3px; top:3px; background:#fff; border-radius:50%; transition: transform var(--transition-fast); }
|
||||
.switch input:checked + .slider { background: var(--color-accent-active); }
|
||||
.switch input:checked + .slider::before { transform: translateX(20px); }
|
||||
.switch input:focus-visible + .slider { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
|
||||
|
||||
.password-block { display: none; margin-top: var(--space-4); }
|
||||
.toggle-block:has(#pw-toggle:checked) .password-block { display: block; }
|
||||
|
||||
/* ---------- Блок повторений (recurrence) ---------- */
|
||||
.pin-block .recurrence-panel { display: none; }
|
||||
.pin-block:has(input[type="checkbox"]:checked) .recurrence-panel {
|
||||
display: flex; flex-direction: column; gap: var(--space-2);
|
||||
margin-top: var(--space-4); padding-top: var(--space-4);
|
||||
border-top: 1px dashed var(--color-border);
|
||||
}
|
||||
|
||||
.recurrence-option-row {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 10px 12px; border: 1px solid var(--color-border); border-radius: var(--radius-md);
|
||||
cursor: pointer; font: var(--text-body); font-weight: 600; color: var(--color-ink-900);
|
||||
transition: border-color var(--transition-fast), background var(--transition-fast);
|
||||
}
|
||||
.recurrence-option-row input[type="radio"] { width: 16px; height: 16px; accent-color: var(--color-ink-700); flex-shrink: 0; }
|
||||
.recurrence-option:has(input:checked) .recurrence-option-row { border-color: var(--color-ink-700); background: var(--color-bg-alt); }
|
||||
|
||||
.recurrence-sub { display: none; padding: var(--space-3) 12px 4px 38px; }
|
||||
.recurrence-option:has(input:checked) .recurrence-sub { display: block; }
|
||||
|
||||
.weekday-toggles { display: flex; gap: 6px; flex-wrap: wrap; }
|
||||
.weekday-chip {
|
||||
width: 34px; height: 34px; border-radius: 50%;
|
||||
border: 1.5px solid var(--color-border); background: var(--color-surface);
|
||||
font: var(--text-caption); color: var(--color-ink-500);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.weekday-chip.is-selected { background: var(--color-ink-700); border-color: var(--color-ink-700); color: #fff; }
|
||||
|
||||
.recurrence-hint { font: 12px var(--font-body); color: var(--color-ink-500); margin-top: 8px; }
|
||||
|
||||
/* ---------- Доп. состояния (ниже основного грида) ---------- */
|
||||
.states-section { margin-top: var(--space-10); }
|
||||
.states-head { margin-bottom: var(--space-5); }
|
||||
.states-head h2 { font: var(--text-h1); color: var(--color-ink-900); margin: 0 0 4px; }
|
||||
.states-head p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0; }
|
||||
.states-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); align-items: start; }
|
||||
|
||||
.state-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); }
|
||||
.screen-label { font: var(--text-caption); color: var(--color-ink-400); margin: 0 0 var(--space-4); }
|
||||
.screen-label b { color: var(--color-ink-700); }
|
||||
|
||||
.next-occurrence { display: flex; align-items: center; gap: 8px; background: var(--color-bg-alt); border-radius: var(--radius-md); padding: 10px 14px; font: var(--text-body); color: var(--color-ink-700); font-weight: 600; margin-bottom: var(--space-5); }
|
||||
|
||||
.btn-row { display: flex; gap: var(--space-3); margin-top: var(--space-5); }
|
||||
.btn-row .btn { flex: 1; justify-content: center; }
|
||||
.danger-link-row { text-align: center; margin-top: var(--space-4); }
|
||||
|
||||
.cancel-alert { display: flex; gap: 10px; background: var(--color-warning-bg); border: 1px solid rgba(181,138,38,.3); color: var(--color-warning); border-radius: var(--radius-md); padding: var(--space-4); font: var(--text-body); margin-bottom: var(--space-5); }
|
||||
.cancel-alert strong { display: block; margin-bottom: 2px; color: var(--color-ink-900); }
|
||||
.cancel-options { display: flex; flex-direction: column; gap: var(--space-3); }
|
||||
.cancel-options .btn { width: 100%; justify-content: center; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-chevron-left" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></symbol>
|
||||
<symbol id="i-chevron-right" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></symbol>
|
||||
<symbol id="i-calendar" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></symbol>
|
||||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-alert" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></symbol>
|
||||
<symbol id="i-plus" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></symbol>
|
||||
<symbol id="i-repeat" viewBox="0 0 24 24"><path d="m17 2 4 4-4 4"/><path d="M3 11v-1a4 4 0 0 1 4-4h14"/><path d="m7 22-4-4 4-4"/><path d="M21 13v1a4 4 0 0 1-4 4H3"/></symbol>
|
||||
<symbol id="i-play" viewBox="0 0 24 24"><polygon points="6 3 20 12 6 21 6 3"/></symbol>
|
||||
<symbol id="i-users" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>
|
||||
<symbol id="i-x" viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
<nav class="topbar-right">
|
||||
<a href="lobby.html" class="nav-link">Лобби</a>
|
||||
<a href="calendar.html" class="nav-link is-active">Календарь</a>
|
||||
<a href="my-conferences.html" class="nav-link">Мои конференции</a>
|
||||
<a href="admin.html" class="nav-link">Админка</a>
|
||||
<button class="avatar-btn"><span class="avatar">АИ</span><span class="user-name">Анна Иванова</span></button>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>Календарь конференций</h1>
|
||||
<p>Запланируйте разовую встречу или закрепите постоянную конференцию с повторением — рабочая неделя 14–18 июля</p>
|
||||
</div>
|
||||
<button class="btn btn-primary"><svg class="icon" style="width:16px;height:16px"><use href="#i-plus"/></svg>Новая конференция</button>
|
||||
</div>
|
||||
|
||||
<div class="layout-grid">
|
||||
|
||||
<!-- ===================== СЕТКА КОНФЕРЕНЦИЙ ПО ДНЯМ ===================== -->
|
||||
<section class="week-card">
|
||||
<div class="week-toolbar">
|
||||
<div class="date-nav">
|
||||
<button aria-label="Предыдущая неделя"><svg class="icon" style="width:16px;height:16px"><use href="#i-chevron-left"/></svg></button>
|
||||
<span>14 — 18 июля 2026</span>
|
||||
<button aria-label="Следующая неделя"><svg class="icon" style="width:16px;height:16px"><use href="#i-chevron-right"/></svg></button>
|
||||
</div>
|
||||
<div class="view-toggle">
|
||||
<button class="is-active">Неделя</button>
|
||||
<button>Месяц</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="week-grid">
|
||||
|
||||
<div class="day-col">
|
||||
<div class="day-col-head"><span class="dow">ПН</span><span class="dom">14</span></div>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge scheduled"><svg class="icon" style="width:11px;height:11px"><use href="#i-clock"/></svg>Запланирована</span>
|
||||
<span class="chip-time">09:00–09:15</span>
|
||||
<span class="chip-title">Дейли команды</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>6</span></span>
|
||||
</button>
|
||||
<div class="day-empty">Свободный день</div>
|
||||
</div>
|
||||
|
||||
<div class="day-col is-today">
|
||||
<div class="day-col-head"><span class="dow">ВТ</span><span class="dom">15</span></div>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:11px;height:11px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
<span class="chip-time">11:00–11:45</span>
|
||||
<span class="chip-title">Ревью спринта</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>8</span></span>
|
||||
</button>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge live"><svg class="icon" style="width:11px;height:11px"><use href="#i-play"/></svg>Идёт сейчас</span>
|
||||
<span class="chip-time">14:00–…</span>
|
||||
<span class="chip-title"><svg class="icon" style="width:13px;height:13px;flex-shrink:0"><use href="#i-lock"/></svg>Синк по релизу 2.4</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>4</span></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="day-col">
|
||||
<div class="day-col-head"><span class="dow">СР</span><span class="dom">16</span></div>
|
||||
<button class="conf-chip is-cancelled">
|
||||
<span class="conf-badge cancelled"><svg class="icon" style="width:11px;height:11px"><use href="#i-x"/></svg>Отменена</span>
|
||||
<span class="chip-time">10:00–10:30</span>
|
||||
<span class="chip-title">Собес: Frontend</span>
|
||||
</button>
|
||||
<div class="day-empty">Свободный день</div>
|
||||
</div>
|
||||
|
||||
<div class="day-col">
|
||||
<div class="day-col-head"><span class="dow">ЧТ</span><span class="dom">17</span></div>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:11px;height:11px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
<span class="chip-time">11:00–11:45</span>
|
||||
<span class="chip-title">Ревью спринта</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>8</span></span>
|
||||
</button>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge scheduled"><svg class="icon" style="width:11px;height:11px"><use href="#i-clock"/></svg>Запланирована</span>
|
||||
<span class="chip-time">15:00–15:30</span>
|
||||
<span class="chip-title">1:1 с руководителем</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>2</span></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="day-col">
|
||||
<div class="day-col-head"><span class="dow">ПТ</span><span class="dom">18</span></div>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge scheduled"><svg class="icon" style="width:11px;height:11px"><use href="#i-clock"/></svg>Запланирована</span>
|
||||
<span class="chip-time">12:00–13:00</span>
|
||||
<span class="chip-title"><svg class="icon" style="width:13px;height:13px;flex-shrink:0"><use href="#i-lock"/></svg>Итоги квартала</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>14</span></span>
|
||||
</button>
|
||||
<div class="day-empty">Ещё нет конференций</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ===================== КАРТОЧКА СОЗДАНИЯ (состояние: создание, пусто) ===================== -->
|
||||
<aside class="create-card" id="create-card">
|
||||
<h2><svg class="icon"><use href="#i-calendar"/></svg>Новая конференция</h2>
|
||||
|
||||
<form>
|
||||
<div class="field">
|
||||
<label>Название</label>
|
||||
<input type="text" placeholder="Например, Синк по релизу 2.4">
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>Дата</label><input type="text" value="21.07.2026"></div>
|
||||
<div class="field"><label>Время</label><input type="text" value="10:00–10:30"></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Участники (email через запятую)</label>
|
||||
<textarea rows="2" placeholder="i.sokolov@company.ru, m.kuznetsova@company.ru"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="toggle-block">
|
||||
<div class="toggle-row" style="border-top:none; padding-top:0">
|
||||
<div class="toggle-copy"><strong>Закрытая по паролю</strong><span>Вход только по паролю, включая гостей</span></div>
|
||||
<label class="switch"><input type="checkbox" id="pw-toggle"><span class="slider"></span></label>
|
||||
</div>
|
||||
<div class="password-block field">
|
||||
<label><svg class="icon" style="width:14px;height:14px"><use href="#i-lock"/></svg>Пароль конференции</label>
|
||||
<input type="password" placeholder="Минимум 6 символов">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pin-block">
|
||||
<div class="toggle-row">
|
||||
<div class="toggle-copy"><strong>Закрепить постоянную конференцию</strong><span>Сохранится и попадёт в «Мои конференции», не исчезнет после встречи</span></div>
|
||||
<label class="switch"><input type="checkbox" id="pin-toggle"><span class="slider"></span></label>
|
||||
</div>
|
||||
|
||||
<!-- Раскрывается по клику на тумблер выше (CSS :has(), без JS) -->
|
||||
<div class="recurrence-panel">
|
||||
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence" checked>
|
||||
По дням недели, еженедельно
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="weekday-toggles">
|
||||
<span class="weekday-chip">ПН</span>
|
||||
<span class="weekday-chip is-selected">ВТ</span>
|
||||
<span class="weekday-chip">СР</span>
|
||||
<span class="weekday-chip is-selected">ЧТ</span>
|
||||
<span class="weekday-chip">ПТ</span>
|
||||
<span class="weekday-chip">СБ</span>
|
||||
<span class="weekday-chip">ВС</span>
|
||||
</div>
|
||||
<p class="recurrence-hint">Ближайшие: вторник 21 июля, четверг 23 июля</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence">
|
||||
Раз в 2 недели
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="field-row">
|
||||
<div class="field" style="margin-bottom:0"><label>Начиная с</label><input type="text" value="21.07.2026"></div>
|
||||
<div class="field" style="margin-bottom:0"><label>День недели</label><select><option>Вторник</option><option>Среда</option></select></div>
|
||||
</div>
|
||||
<p class="recurrence-hint">Следующие: 4 августа, 18 августа</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence">
|
||||
Раз в месяц
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="field"><label>Число месяца</label><input type="text" value="31" inputmode="numeric"></div>
|
||||
<p class="recurrence-hint">Если в месяце нет такого числа — переносится на последний день месяца (напр. 28/29 февраля)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence">
|
||||
Каждые N дней
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="field-row">
|
||||
<div class="field" style="margin-bottom:0"><label>N (дней)</label><input type="text" value="10" inputmode="numeric"></div>
|
||||
<div class="field" style="margin-bottom:0"><label>Начиная с</label><input type="text" value="21.07.2026"></div>
|
||||
</div>
|
||||
<p class="recurrence-hint">Ближайшие: через 10, 20, 30 дней</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary full" style="margin-top: var(--space-5)">Создать конференцию</button>
|
||||
</form>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ===================== ДОП. СОСТОЯНИЯ: РЕДАКТИРОВАНИЕ И ОТМЕНА ===================== -->
|
||||
<section class="states-section">
|
||||
<div class="states-head">
|
||||
<h2>Другие состояния карточки</h2>
|
||||
<p>Раскрытая карточка с закреплением, редактирование существующей закреплённой конференции и отмена вхождения/всех повторений.</p>
|
||||
</div>
|
||||
|
||||
<div class="states-grid">
|
||||
|
||||
<!-- Состояние: редактирование существующей закреплённой конференции -->
|
||||
<div class="state-card">
|
||||
<p class="screen-label">Состояние: <b>редактирование закреплённой конференции</b></p>
|
||||
|
||||
<div class="next-occurrence">
|
||||
<svg class="icon" style="width:16px;height:16px"><use href="#i-clock"/></svg>
|
||||
Следующее вхождение: вторник, 22 июля, 11:00
|
||||
</div>
|
||||
|
||||
<form>
|
||||
<div class="field"><label>Название</label><input type="text" value="Ревью спринта"></div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>Время</label><input type="text" value="11:00–11:45"></div>
|
||||
<div class="field"><label>Участники</label><input type="text" value="8 человек"></div>
|
||||
</div>
|
||||
|
||||
<div class="pin-block">
|
||||
<div class="toggle-row" style="border-top:none; padding-top:0">
|
||||
<div class="toggle-copy"><strong>Закреплена</strong><span>Повторяется по расписанию</span></div>
|
||||
<label class="switch"><input type="checkbox" id="pin-toggle-edit" checked><span class="slider"></span></label>
|
||||
</div>
|
||||
<div class="recurrence-panel">
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence-edit" checked>
|
||||
По дням недели, еженедельно
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="weekday-toggles">
|
||||
<span class="weekday-chip">ПН</span>
|
||||
<span class="weekday-chip is-selected">ВТ</span>
|
||||
<span class="weekday-chip">СР</span>
|
||||
<span class="weekday-chip is-selected">ЧТ</span>
|
||||
<span class="weekday-chip">ПТ</span>
|
||||
<span class="weekday-chip">СБ</span>
|
||||
<span class="weekday-chip">ВС</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row"><input type="radio" name="recurrence-edit">Раз в 2 недели</label>
|
||||
</div>
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row"><input type="radio" name="recurrence-edit">Раз в месяц</label>
|
||||
</div>
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row"><input type="radio" name="recurrence-edit">Каждые N дней</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-row">
|
||||
<button type="submit" class="btn btn-primary">Сохранить изменения</button>
|
||||
<button type="button" class="btn btn-secondary">Открепить</button>
|
||||
</div>
|
||||
<div class="danger-link-row">
|
||||
<button type="button" class="btn-text">Удалить конференцию навсегда</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Состояние: отмена одной / всех повторяющихся -->
|
||||
<div class="state-card">
|
||||
<p class="screen-label">Состояние: <b>отмена вхождения повторяющейся конференции</b></p>
|
||||
|
||||
<div class="cancel-alert">
|
||||
<svg class="icon" style="width:18px;height:18px;flex-shrink:0;margin-top:1px"><use href="#i-alert"/></svg>
|
||||
<div><strong>«Ревью спринта» — вторник, 22 июля, 11:00</strong>Это повторяющаяся конференция (по вторникам и четвергам). Что отменить?</div>
|
||||
</div>
|
||||
|
||||
<div class="cancel-options">
|
||||
<button class="btn btn-secondary"><svg class="icon" style="width:16px;height:16px"><use href="#i-x"/></svg>Отменить только это вхождение</button>
|
||||
<button class="btn btn-danger"><svg class="icon" style="width:16px;height:16px"><use href="#i-x"/></svg>Отменить все повторения</button>
|
||||
</div>
|
||||
<div class="danger-link-row">
|
||||
<button type="button" class="btn-text" style="color: var(--color-ink-500)">Оставить как есть</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
188
design/mockups/dark/README.md
Normal file
188
design/mockups/dark/README.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# VidConf — тёмные варианты оболочки
|
||||
|
||||
Обязательный референс для разработки.
|
||||
|
||||
Тёмная тема для экранов «оболочки» (auth/лобби/календарь/join/«мои
|
||||
конференции»/админка), реализована **поверх** дизайн-системы, а не взамен
|
||||
неё. `design/tokens.css` и `design/DESIGN_SYSTEM.md` — единственный
|
||||
источник истины по значениям (см. §0 `DESIGN_SYSTEM.md`: «светлая тема —
|
||||
оболочка (со светлым/тёмным вариантом), тёмная — комната конференции
|
||||
всегда»). Реализация во frontend — `frontend/src/hooks/useTheme.ts` и
|
||||
`frontend/src/components/ui/ThemeToggle.tsx` (см. `frontend/README.md`,
|
||||
раздел «Темы оболочки»).
|
||||
|
||||
## Что здесь
|
||||
|
||||
Разметка, контент и русские данные каждого файла — 1:1 копия
|
||||
соответствующего светлого макета из `design/mockups/`. Меняется только
|
||||
цветовая схема: вместо индиго-на-белом (`referens.png`) — графит-мята-роза-
|
||||
янтарь той же гаммы, что уже утверждена для комнаты конференции
|
||||
(`collor_ico.png`, токены `[data-theme="room"]` в `tokens.css`).
|
||||
|
||||
| Файл | Светлый прообраз | Экран |
|
||||
|---|---|---|
|
||||
| `login.html` | `../auth.html` | Вход / регистрация / подтверждение email |
|
||||
| `lobby.html` | `../lobby.html` | Лобби — хаб действий 2×2 |
|
||||
| `calendar.html` | `../calendar.html` | Календарь-менеджер конференций (+ создание/редактирование/отмена) |
|
||||
| `join.html` | `../join.html` | Подключение по ссылке/номеру → представиться (гость) → пароль |
|
||||
| `my-conferences.html` | `../my-conferences.html` | Мои конференции |
|
||||
| `admin.html` | `../admin.html` | Админка (конференции, пользователи, рассылка приглашений) |
|
||||
|
||||
`room.html` и `email-summary.html` в комплект не входят: комната уже тёмная
|
||||
(эталон гаммы), а письмо-саммари по правилам проекта всегда светлое
|
||||
(почтовые клиенты не гарантируют поддержку тёмной темы/CSS-переменных).
|
||||
Ссылки на «Войти»/«Создать» из `lobby.html`/`my-conferences.html` ведут на
|
||||
уже существующий `../room.html`; ссылка «Открыть саммари» — на
|
||||
`../email-summary.html`.
|
||||
|
||||
Каждый файл самодостаточен: встроенный `<style>`, инлайн-SVG-иконки
|
||||
(lucide-совместимые контуры), без CDN и внешних сетевых зависимостей —
|
||||
открывается двойным кликом. Единственная локальная зависимость —
|
||||
`<link rel="stylesheet" href="../../tokens.css">` (тот же приём, что и в
|
||||
светлых макетах: используются базовые не-цветовые токены — spacing, радиусы,
|
||||
типографика, тени-заготовки, шрифты).
|
||||
|
||||
## Переключатель темы
|
||||
|
||||
В шапке каждого макета — сегментированный переключатель ☀ / 🌙 (иконки
|
||||
`Sun`/`Moon`, lucide-стиль), «Тёмная» — активный сегмент. Элемент
|
||||
статичный (демонстрирует точку входа в реальный toggle, не переключает
|
||||
тему по клику в макете) и размещён:
|
||||
- `login.html` — плавающей плашкой в правом верхнем углу (у экрана нет
|
||||
общего топбара, панель бренда/форма — раздельные колонки);
|
||||
- `lobby.html`, `calendar.html`, `my-conferences.html` — внутри правой
|
||||
группы топбара, рядом с меню пользователя;
|
||||
- `join.html` — в топбаре, справа от логотипа;
|
||||
- `admin.html` — в шапке сайдбара, рядом с логотипом.
|
||||
|
||||
## Как получена палитра
|
||||
|
||||
### Принцип
|
||||
|
||||
Тёмная схема **не изобретает новых цветов**, а переиспользует уже
|
||||
утверждённые токены комнаты конференции (`tokens.css`, блок
|
||||
`[data-theme='room']`, см. `DESIGN_SYSTEM.md` §1.2) в новых ролях — так
|
||||
оболочка и комната читаются как одна система, когда пользователь входит
|
||||
из тёмного лобби в тёмную комнату. Все переопределения делаются одним
|
||||
блоком `:root { … }` в начале `<style>` каждого файла — он перекрывает
|
||||
одноимённые переменные `:root` из `tokens.css` (та же специфичность,
|
||||
позже в источнике — выигрывает), поэтому весь остальной CSS ниже —
|
||||
дословная копия светлого макета и автоматически перекрашивается.
|
||||
|
||||
### Токены, переиспользованные из комнаты 1:1 (без изменения hex)
|
||||
|
||||
| Токен оболочки (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-room-danger-bg` | `#B85468` | заливка **сплошных** danger-кнопок (см. ниже, почему это отдельный токен) |
|
||||
| `--color-danger-solid-hover` | `--color-room-danger-bg-hover` | `#B9495F` | hover сплошной danger-кнопки |
|
||||
|
||||
**Одна мята — три роли.** В светлой оболочке бренд-индиго (`--color-ink-700`,
|
||||
заголовки/ссылки/обводка pill-кнопок) и мятный CTA (`--color-accent`) — два
|
||||
разных токена с разными hex. В комнате пастельная мята уже одна на всё
|
||||
«позитивное» (`--color-room-mic-on` = «микрофон включён» + активная
|
||||
демонстрация экрана + счётчик участников + кнопка отправки в чате). Чтобы
|
||||
не завозить в тёмную оболочку новый, ничем не подкреплённый в комнате
|
||||
оттенок, `--color-ink-700` и `--color-accent` в тёмной оболочке **сведены
|
||||
к одному и тому же** `#7FDDA8` — бренд, заголовки, ссылки, обводка
|
||||
secondary-кнопок и заливка CTA используют один и тот же «фирменный» зелёный.
|
||||
Различие ролей (бренд-текст vs интерактивная заливка) остаётся читаемым за
|
||||
счёт контекста (текст vs заливка с тёмным текстом поверх), а не за счёт
|
||||
второго оттенка — это соответствует прецеденту самой комнаты.
|
||||
|
||||
**Почему заливка danger-кнопок — отдельный токен, а не `--color-danger`.**
|
||||
В светлой теме один hex (`#C7364F`) одинаково хорошо работает и как текст на
|
||||
белом, и как заливка кнопки с белым текстом (тёмный, насыщенный тон). В
|
||||
тёмной теме эти две роли расходятся: `--color-room-mic-off` (`#EB93A1`) —
|
||||
светлый пастельный тон, читаемый как **текст на тёмном фоне** (6.30:1 на
|
||||
`#2A2A2A`), но слишком светлый, чтобы на нём читался белый текст кнопки
|
||||
(≈1.9:1, провал). Поэтому для сплошных danger-кнопок (`.btn-danger` —
|
||||
«Отменить все повторения» в календаре, «Удалить» в админке) заведена
|
||||
отдельная пара `--color-danger-solid` / `--color-danger-solid-hover`,
|
||||
переиспользующая уже готовые `--color-room-danger-bg(-hover)` (`#B85468` /
|
||||
`#B9495F`, задокументированы в `DESIGN_SYSTEM.md` §1.2 с контрастом
|
||||
4.66:1/5.02:1 для белого текста).
|
||||
|
||||
### Новые токены (введены только там, где у комнаты нет готового аналога)
|
||||
|
||||
Комната — экран без брендинга, форм и многошаговых карточек, поэтому под
|
||||
нужды оболочки понадобилось несколько новых значений. Все получены
|
||||
подмешиванием уже утверждённых цветов комнаты к графитовому фону/друг к
|
||||
другу (не независимо придуманные тона), проверены по WCAG 2.1 (см. расчёт
|
||||
ниже, тот же метод, что в `design/tools/contrast.py`):
|
||||
|
||||
| Токен | Hex | Как получен | Контраст | Роль |
|
||||
|---|---|---|---|---|
|
||||
| `--color-bg-alt` | `#242424` | между `--color-room-bg` (`#1E1E1E`) и `--color-room-surface` (`#2A2A2A`) | — | альт-фон секций, инпуты, disabled-поля |
|
||||
| `--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 | эйбрау-подписи `[ В СКОБКАХ ]`, крупные подписи (аналог ⚠︎ large-text-only из светлой темы, но с запасом) |
|
||||
| `--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-панелей |
|
||||
|
||||
Контраст всех текстовых пар проверен по формуле WCAG 2.1 — пары, использованные
|
||||
в макетах (основной текст, вторичный текст, мята/роза/янтарь как текст на
|
||||
`bg`/`surface`/`tile`, белый текст на `--color-danger-solid`), все дают
|
||||
≥ 4.5:1 (текст) либо ≥ 3:1 (декоративные элементы, статус которых также
|
||||
задублирован иконкой/текстом — см. правило §5 `DESIGN_SYSTEM.md`). Регрессия
|
||||
этих пар — в `design/tools/contrast.py`.
|
||||
|
||||
## Точечные правки поверх скопированного CSS
|
||||
|
||||
Для каждого файла CSS светлого макета скопирован дословно (все `.class`
|
||||
правила без изменений) — перекраска идёт только через блок `:root`. Ручных
|
||||
точечных правок пять видов, во всех случаях — потому что исходное правило
|
||||
использовало **литеральный hex/rgba**, а не `var()`, и не могло
|
||||
перекраситься автоматически:
|
||||
|
||||
1. **Аватары и `.weekday-chip.is-selected`/`.badge-role-admin`** — в
|
||||
светлой теме заливка `var(--color-ink-700)` (тёмный индиго) сочеталась с
|
||||
жёстким `color: #fff`. Так как `--color-ink-700` теперь = мята (светлый
|
||||
тон), белый текст перестаёт читаться (≈1.9:1) — заменено на
|
||||
`var(--color-accent-text)` (`#10331F`, 8.45:1 на мяте).
|
||||
2. **`.btn-danger`** (`calendar.html`, `admin.html`) — добавлена отдельная
|
||||
заливка `var(--color-danger-solid)` вместо `var(--color-danger)` (см.
|
||||
таблицу выше); белый текст кнопки не менялся.
|
||||
3. **`.copy-toast`** (`my-conferences.html`) — фон был `var(--color-ink-900)`
|
||||
(тёмный в светлой теме → стал бы светло-серым в тёмной, ломая тёмный
|
||||
тултип); заменён на буквальный `#333333` (= `--color-room-surface-raised`),
|
||||
текст остаётся `var(--color-ink-900)` (теперь светлый) — тултип снова
|
||||
тёмный чип со светлым текстом.
|
||||
4. **Декоративные градиенты/rgba-подложки** (`login.html`
|
||||
`.brand-panel`/`.brand-panel::after`, `lobby.html` фон `body`,
|
||||
`calendar.html` `.day-col.is-today`/`.cancel-alert`, `login.html`/
|
||||
`join.html`/`calendar.html` box-shadow фокуса и ошибки, glass-обводка
|
||||
`rgba(255,255,255,.7)` в `login.html`/`admin.html`, disabled-заливка
|
||||
кнопок) — старые rgba были построены на индиго/старом danger-hex;
|
||||
заменены на тональные аналоги новой палитры (мятное свечение вместо
|
||||
индигового/мятного на белом, янтарный focus-glow вместо индигового,
|
||||
розовый error-glow, `rgba(255,255,255,.08)` вместо `.7` для тёмного
|
||||
стекла).
|
||||
5. **`color-scheme: dark`** добавлен в блок `:root`, чтобы нативные
|
||||
элементы форм (скроллбар, чекбоксы без кастомной стилизации) тоже
|
||||
рендерились в тёмной палитре браузера.
|
||||
|
||||
## Доступность (проверено при подборе палитры)
|
||||
|
||||
- Текст ≥ 4.5:1 везде, кроме крупных/декоративных элементов (аналогично
|
||||
правилу §5 `DESIGN_SYSTEM.md` для светлой темы, порог 3:1).
|
||||
- Статус не передаётся только цветом: бейджи конференций — иконка + текст
|
||||
(как в светлой теме), «скопировано» — смена иконки `Copy → Check` +
|
||||
текстовый тултип, ошибки полей — иконка `AlertCircle` + текст под полем,
|
||||
`:focus-visible` — везде видимое кольцо (`--color-focus-ring`, тот же
|
||||
янтарь, что и в комнате).
|
||||
- Палитра пастельная (мята/роза/янтарь той же светлоты, что уже утверждена
|
||||
для комнаты), неоновых/кислотных акцентов не вводилось.
|
||||
303
design/mockups/dark/admin.html
Normal file
303
design/mockups/dark/admin.html
Normal file
@@ -0,0 +1,303 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-theme="shell-dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Админка — тёмная тема, НА СОГЛАСОВАНИИ</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../../tokens.css">
|
||||
<style>
|
||||
/* =====================================================================
|
||||
* ТЁМНЫЙ ВАРИАНТ ОБОЛОЧКИ — ПРЕДЛОЖЕНИЕ, НЕ УТВЕРЖДЕНО.
|
||||
* Разметка и контент идентичны design/mockups/admin.html 1:1, меняется
|
||||
* только цветовая схема — палитра переиспользует токены комнаты
|
||||
* конференции. Обоснование цветов — design/mockups/dark/README.md.
|
||||
* ===================================================================== */
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
--color-bg: #1E1E1E;
|
||||
--color-bg-alt: #242424;
|
||||
--color-surface: #2A2A2A;
|
||||
--color-surface-glass: rgba(51, 51, 51, .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, .14);
|
||||
--color-success-dot: #7FDDA8;
|
||||
|
||||
--color-danger: #EB93A1;
|
||||
--color-danger-bg: rgba(235, 147, 161, .14);
|
||||
--color-danger-dot: #EB93A1;
|
||||
--color-danger-solid: #B85468;
|
||||
--color-danger-solid-hover: #B9495F;
|
||||
|
||||
--color-warning: #D6A83D;
|
||||
--color-warning-bg: rgba(214, 168, 61, .16);
|
||||
--color-warning-dot: #D6A83D;
|
||||
|
||||
--color-focus-ring: #D6A83D;
|
||||
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
|
||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, .4);
|
||||
--shadow-lg: 0 12px 32px rgba(0, 0, 0, .5);
|
||||
--shadow-glass: 0 8px 24px rgba(0, 0, 0, .45);
|
||||
}
|
||||
|
||||
.theme-toggle { display: inline-flex; gap: 2px; background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); border: 1px solid var(--color-border); }
|
||||
.theme-toggle-btn { width: 32px; height: 32px; border-radius: 50%; border: none; background: transparent; color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; }
|
||||
.theme-toggle-btn .icon { width: 16px; height: 16px; }
|
||||
.theme-toggle-btn:hover { color: var(--color-ink-900); }
|
||||
.theme-toggle-btn.is-active { background: var(--color-surface); color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
|
||||
html { min-width: 1280px; }
|
||||
|
||||
.app-shell { display: flex; min-height: 100vh; }
|
||||
|
||||
/* ---------- Сайдбар ---------- */
|
||||
.sidebar { width: 260px; flex-shrink: 0; background: var(--color-surface); border-right: 1px solid var(--color-border); padding: var(--space-6) var(--space-4); display: flex; flex-direction: column; }
|
||||
.sidebar-head { display: flex; align-items: center; justify-content: space-between; padding: 0 var(--space-2); margin-bottom: var(--space-8); }
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
|
||||
.side-nav { display: flex; flex-direction: column; gap: 2px; }
|
||||
.side-link {
|
||||
display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: var(--radius-md);
|
||||
font: var(--text-body); font-weight: 600; color: var(--color-ink-500); text-decoration: none;
|
||||
}
|
||||
.side-link:hover { background: var(--color-bg-alt); color: var(--color-ink-900); }
|
||||
.side-link.is-active { background: var(--color-bg-alt); color: var(--color-ink-700); }
|
||||
.side-link .icon { color: inherit; }
|
||||
|
||||
.side-footer { margin-top: auto; padding: var(--space-3) var(--space-2); border-top: 1px solid var(--color-border); }
|
||||
.avatar-btn { display: flex; align-items: center; gap: 8px; padding: 8px 0; width: 100%; background: none; border: none; text-align: left; }
|
||||
.avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--color-ink-700); color: var(--color-accent-text); display:flex; align-items:center; justify-content:center; font: var(--text-caption); text-transform: none; letter-spacing: 0; flex-shrink: 0; }
|
||||
.avatar-btn div strong { display: block; font: var(--text-body); color: var(--color-ink-900); }
|
||||
.avatar-btn div span { font: 12px var(--font-body); color: var(--color-ink-500); }
|
||||
|
||||
/* ---------- Контент ---------- */
|
||||
main { flex: 1; padding: var(--space-8); max-width: 1220px; }
|
||||
.page-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: var(--space-6); }
|
||||
.page-head h1 { font: var(--text-display-lg); font-family: var(--font-display); color: var(--color-ink-700); margin: 0 0 6px; }
|
||||
.page-head p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0; }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; border: none; cursor: pointer; font-family: var(--font-body); white-space: nowrap; transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary { background: var(--color-accent); color: var(--color-accent-text); font: var(--text-body); font-weight: 700; padding: 11px 22px; border-radius: var(--radius-full); }
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-secondary { background: transparent; color: var(--color-ink-700); border: 1.5px solid var(--color-border-pill); font: var(--text-body); font-weight: 600; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); }
|
||||
.btn-danger { background: var(--color-danger); color: #fff; font: var(--text-body); font-weight: 700; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
|
||||
/* Стат-виджеты (glass) */
|
||||
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); margin-bottom: var(--space-8); }
|
||||
.stat-glass {
|
||||
background: var(--color-surface-glass); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
|
||||
border: 1px solid rgba(255,255,255,.08); box-shadow: var(--shadow-glass); border-radius: var(--radius-xl);
|
||||
padding: var(--space-5); background-color: var(--color-bg-alt);
|
||||
}
|
||||
.stat-glass strong { display: block; font: var(--text-display-xl); font-family: var(--font-display); font-size: 36px; color: var(--color-ink-700); }
|
||||
.stat-glass span { font: var(--text-body); color: var(--color-ink-500); }
|
||||
|
||||
/* Табы разделов */
|
||||
.section-tabs { display: flex; gap: var(--space-2); margin-bottom: var(--space-5); border-bottom: 1px solid var(--color-border); }
|
||||
.section-tab { padding: 10px 4px; margin-right: var(--space-6); background: none; border: none; border-bottom: 2px solid transparent; font: var(--text-body-lg); font-weight: 600; color: var(--color-ink-500); }
|
||||
.section-tab.is-active { color: var(--color-ink-700); border-color: var(--color-accent-active); }
|
||||
|
||||
.toolbar-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-5); gap: var(--space-4); }
|
||||
.search-wrap { position: relative; width: 320px; }
|
||||
.search-wrap .icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--color-ink-400); }
|
||||
.search-wrap input { width: 100%; font: var(--text-body); padding: 9px 12px 9px 38px; border-radius: var(--radius-full); border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-ink-900); }
|
||||
.search-wrap input::placeholder { color: var(--color-ink-300); }
|
||||
.search-wrap input:focus { outline: none; border-color: var(--color-focus-ring); }
|
||||
|
||||
/* Таблица */
|
||||
.table-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); overflow: hidden; margin-bottom: var(--space-8); }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
thead th { text-align: left; background: var(--color-bg-alt); font: var(--text-caption); color: var(--color-ink-500); padding: 12px 20px; text-transform: uppercase; }
|
||||
tbody td { padding: 14px 20px; font: var(--text-body-lg); color: var(--color-ink-900); border-top: 1px solid var(--color-border); }
|
||||
tbody tr:hover { background: var(--color-bg-alt); }
|
||||
|
||||
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: var(--radius-full); font: var(--text-caption); white-space: nowrap; }
|
||||
.badge-free { background: var(--color-success-bg); color: var(--color-success); }
|
||||
.badge-busy { background: var(--color-danger-bg); color: var(--color-danger); }
|
||||
.badge-booked { background: var(--color-warning-bg); color: var(--color-warning); }
|
||||
.badge-locked { background: var(--color-bg-alt); color: var(--color-ink-700); }
|
||||
.badge-role-admin { background: var(--color-ink-700); color: var(--color-accent-text); }
|
||||
.badge-role-user { background: var(--color-bg-alt); color: var(--color-ink-500); }
|
||||
|
||||
.row-actions { display: flex; gap: 6px; }
|
||||
.icon-btn { width: 32px; height: 32px; border-radius: var(--radius-md); border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-ink-500); display:flex; align-items:center; justify-content:center; }
|
||||
.icon-btn:hover { border-color: var(--color-border-strong); color: var(--color-ink-900); }
|
||||
.icon-btn.danger:hover { border-color: var(--color-danger); color: var(--color-danger); background: var(--color-danger-bg); }
|
||||
|
||||
.user-cell { display: flex; align-items: center; gap: 10px; }
|
||||
.user-cell .avatar { width: 32px; height: 32px; font-size: 12px; }
|
||||
.user-cell div span { display: block; font: 13px var(--font-body); color: var(--color-ink-500); }
|
||||
|
||||
/* Секция рассылки */
|
||||
.invite-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); display: grid; grid-template-columns: 1fr 320px; gap: var(--space-8); }
|
||||
.invite-card h2 { font: var(--text-h2); margin: 0 0 4px; color: var(--color-ink-900); }
|
||||
.invite-card p.desc { font: var(--text-body); color: var(--color-ink-500); margin: 0 0 var(--space-5); }
|
||||
.invite-card textarea {
|
||||
width: 100%; min-height: 140px; font: var(--text-body-lg); color: var(--color-ink-900); font-family: var(--font-mono);
|
||||
padding: 14px; border-radius: var(--radius-md); border: 1px solid var(--color-border); background: var(--color-surface); resize: vertical;
|
||||
}
|
||||
.invite-card textarea:focus { outline: none; border-color: var(--color-focus-ring); }
|
||||
.invite-side { background: var(--color-bg-alt); border-radius: var(--radius-xl); padding: var(--space-5); }
|
||||
.invite-side h3 { font: var(--text-h3); margin: 0 0 var(--space-3); color: var(--color-ink-900); }
|
||||
.invite-side ul { margin: 0 0 var(--space-5); padding-left: 18px; font: var(--text-body); color: var(--color-ink-500); }
|
||||
.invite-side li { margin-bottom: 6px; }
|
||||
|
||||
/* ---------- Патчи тёмной темы: заливка mint требует тёмного текста, а не белого ---------- */
|
||||
.btn-danger { background: var(--color-danger-solid); }
|
||||
.btn-danger:hover { filter: none; background: var(--color-danger-solid-hover); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-dashboard" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="9" rx="1"/><rect x="14" y="3" width="7" height="5" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/><rect x="3" y="16" width="7" height="5" rx="1"/></symbol>
|
||||
<symbol id="i-video" viewBox="0 0 24 24"><rect x="2" y="6" width="14" height="12" rx="2"/><path d="m22 8-6 4 6 4V8Z"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-users" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>
|
||||
<symbol id="i-mail" viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 6 10 7 10-7"/></symbol>
|
||||
<symbol id="i-search" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></symbol>
|
||||
<symbol id="i-plus" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></symbol>
|
||||
<symbol id="i-pencil" viewBox="0 0 24 24"><path d="M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></symbol>
|
||||
<symbol id="i-trash" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></symbol>
|
||||
<symbol id="i-send" viewBox="0 0 24 24"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></symbol>
|
||||
<symbol id="i-check-circle" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></symbol>
|
||||
<symbol id="i-ban" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="4.9" y1="4.9" x2="19.1" y2="19.1"/></symbol>
|
||||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
||||
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></symbol>
|
||||
<symbol id="i-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<div class="app-shell">
|
||||
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-head">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
<div class="theme-toggle" role="group" aria-label="Переключить тему оформления">
|
||||
<button class="theme-toggle-btn" type="button" aria-pressed="false" aria-label="Светлая тема"><svg class="icon"><use href="#i-sun"/></svg></button>
|
||||
<button class="theme-toggle-btn is-active" type="button" aria-pressed="true" aria-label="Тёмная тема"><svg class="icon"><use href="#i-moon"/></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="side-nav">
|
||||
<a class="side-link is-active" href="#rooms"><svg class="icon" style="width:18px;height:18px"><use href="#i-video"/></svg>Конференции</a>
|
||||
<a class="side-link" href="#closed"><svg class="icon" style="width:18px;height:18px"><use href="#i-lock"/></svg>Закрытые конференции</a>
|
||||
<a class="side-link" href="#users"><svg class="icon" style="width:18px;height:18px"><use href="#i-users"/></svg>Пользователи</a>
|
||||
<a class="side-link" href="#invites"><svg class="icon" style="width:18px;height:18px"><use href="#i-mail"/></svg>Рассылка приглашений</a>
|
||||
</nav>
|
||||
<div class="side-footer">
|
||||
<button class="avatar-btn"><span class="avatar">АИ</span><div><strong>Анна Иванова</strong><span>Администратор</span></div></button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main>
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>Администрирование</h1>
|
||||
<p>Управление конференциями, доступом и пользователями VidConf</p>
|
||||
</div>
|
||||
<button class="btn btn-primary"><svg class="icon" style="width:16px;height:16px"><use href="#i-plus"/></svg>Добавить конференцию</button>
|
||||
</div>
|
||||
|
||||
<section class="stat-grid">
|
||||
<div class="stat-glass"><strong>100</strong><span>Всего конференций</span></div>
|
||||
<div class="stat-glass"><strong>12</strong><span>Активны сейчас</span></div>
|
||||
<div class="stat-glass"><strong>34</strong><span>Забронировано сегодня</span></div>
|
||||
<div class="stat-glass"><strong>248</strong><span>Пользователей</span></div>
|
||||
</section>
|
||||
|
||||
<div class="section-tabs">
|
||||
<button class="section-tab is-active">Конференции</button>
|
||||
<button class="section-tab">Закрытые конференции</button>
|
||||
<button class="section-tab">Пользователи</button>
|
||||
<button class="section-tab">Рассылка приглашений</button>
|
||||
</div>
|
||||
|
||||
<!-- ===================== КОНФЕРЕНЦИИ ===================== -->
|
||||
<div class="toolbar-row">
|
||||
<div class="search-wrap"><svg class="icon"><use href="#i-search"/></svg><input type="text" placeholder="Поиск конференции…"></div>
|
||||
<span style="font:14px var(--font-body); color:var(--color-ink-500)">Показано 6 из 100</span>
|
||||
</div>
|
||||
|
||||
<div class="table-card">
|
||||
<table>
|
||||
<thead><tr><th>Конференция</th><th>Вместимость</th><th>Статус</th><th>Тип</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>Переговорная №01</td><td>8 мест</td><td><span class="badge badge-free"><svg class="icon" style="width:12px;height:12px"><use href="#i-check-circle"/></svg>Свободна</span></td><td>Открытая</td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td></tr>
|
||||
<tr><td>Переговорная №02</td><td>10 мест</td><td><span class="badge badge-busy"><svg class="icon" style="width:12px;height:12px"><use href="#i-ban"/></svg>Занята</span></td><td>Открытая</td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td></tr>
|
||||
<tr><td>Переговорная №04</td><td>12 мест</td><td><span class="badge badge-locked"><svg class="icon" style="width:12px;height:12px"><use href="#i-lock"/></svg>По паролю</span></td><td>Закрытая</td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td></tr>
|
||||
<tr><td>Переговорная №42</td><td>16 мест</td><td><span class="badge badge-booked"><svg class="icon" style="width:12px;height:12px"><use href="#i-clock"/></svg>Забронирована</span></td><td>Открытая</td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- ===================== ПОЛЬЗОВАТЕЛИ ===================== -->
|
||||
<div class="page-head" style="margin-bottom: var(--space-4)"><h2 style="font:var(--text-h2); color:var(--color-ink-900); margin:0">Пользователи</h2></div>
|
||||
<div class="table-card">
|
||||
<table>
|
||||
<thead><tr><th>Пользователь</th><th>Роль</th><th>Регистрация</th><th>Статус</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><div class="user-cell"><span class="avatar">АИ</span><div>Анна Иванова<span>a.ivanova@vidconf.dev</span></div></div></td>
|
||||
<td><span class="badge badge-role-admin">Администратор</span></td>
|
||||
<td>03.02.2026</td>
|
||||
<td><span class="badge badge-free"><svg class="icon" style="width:12px;height:12px"><use href="#i-check-circle"/></svg>Активен</span></td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><div class="user-cell"><span class="avatar">МК</span><div>Мария Кузнецова<span>m.kuznetsova@company.ru</span></div></div></td>
|
||||
<td><span class="badge badge-role-user">Пользователь</span></td>
|
||||
<td>15.07.2026</td>
|
||||
<td><span class="badge badge-booked"><svg class="icon" style="width:12px;height:12px"><use href="#i-clock"/></svg>Ждёт подтверждения</span></td>
|
||||
<td><div class="row-actions"><button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:16px;height:16px"><use href="#i-pencil"/></svg></button><button class="icon-btn danger" aria-label="Удалить"><svg class="icon" style="width:16px;height:16px"><use href="#i-trash"/></svg></button></div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- ===================== РАССЫЛКА ПРИГЛАШЕНИЙ ===================== -->
|
||||
<div class="page-head" style="margin-bottom: var(--space-4)"><h2 style="font:var(--text-h2); color:var(--color-ink-900); margin:0">Рассылка приглашений</h2></div>
|
||||
<div class="invite-card">
|
||||
<div>
|
||||
<h2>Пригласить новых пользователей</h2>
|
||||
<p class="desc">Каждый адрес получит письмо со ссылкой регистрации, действительной 7 дней.</p>
|
||||
<textarea placeholder="i.sokolov@company.ru o.panina@company.ru v.sedykh@company.ru">i.sokolov@company.ru
|
||||
o.panina@company.ru
|
||||
v.sedykh@company.ru</textarea>
|
||||
<button class="btn btn-primary" style="margin-top: var(--space-4)"><svg class="icon" style="width:16px;height:16px"><use href="#i-send"/></svg>Отправить приглашения (3)</button>
|
||||
</div>
|
||||
<div class="invite-side">
|
||||
<h3>Последняя рассылка</h3>
|
||||
<ul>
|
||||
<li>28.06.2026 · 12 приглашений</li>
|
||||
<li>9 приняли, 3 ожидают</li>
|
||||
</ul>
|
||||
<button class="btn btn-secondary" style="width:100%; justify-content:center">Посмотреть журнал</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
558
design/mockups/dark/calendar.html
Normal file
558
design/mockups/dark/calendar.html
Normal file
@@ -0,0 +1,558 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-theme="shell-dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Календарь конференций — тёмная тема, НА СОГЛАСОВАНИИ</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../../tokens.css">
|
||||
<style>
|
||||
/* =====================================================================
|
||||
* ТЁМНЫЙ ВАРИАНТ ОБОЛОЧКИ — ПРЕДЛОЖЕНИЕ, НЕ УТВЕРЖДЕНО.
|
||||
* Разметка и контент идентичны design/mockups/calendar.html 1:1, меняется
|
||||
* только цветовая схема — палитра переиспользует токены комнаты
|
||||
* конференции. Обоснование цветов — design/mockups/dark/README.md.
|
||||
* ===================================================================== */
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
--color-bg: #1E1E1E;
|
||||
--color-bg-alt: #242424;
|
||||
--color-surface: #2A2A2A;
|
||||
--color-surface-glass: rgba(51, 51, 51, .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, .14);
|
||||
--color-success-dot: #7FDDA8;
|
||||
|
||||
--color-danger: #EB93A1;
|
||||
--color-danger-bg: rgba(235, 147, 161, .14);
|
||||
--color-danger-dot: #EB93A1;
|
||||
--color-danger-solid: #B85468;
|
||||
--color-danger-solid-hover: #B9495F;
|
||||
|
||||
--color-warning: #D6A83D;
|
||||
--color-warning-bg: rgba(214, 168, 61, .16);
|
||||
--color-warning-dot: #D6A83D;
|
||||
|
||||
--color-focus-ring: #D6A83D;
|
||||
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
|
||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, .4);
|
||||
--shadow-lg: 0 12px 32px rgba(0, 0, 0, .5);
|
||||
--shadow-glass: 0 8px 24px rgba(0, 0, 0, .45);
|
||||
}
|
||||
|
||||
.theme-toggle { display: inline-flex; gap: 2px; background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); border: 1px solid var(--color-border); }
|
||||
.theme-toggle-btn { width: 32px; height: 32px; border-radius: 50%; border: none; background: transparent; color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; }
|
||||
.theme-toggle-btn .icon { width: 16px; height: 16px; }
|
||||
.theme-toggle-btn:hover { color: var(--color-ink-900); }
|
||||
.theme-toggle-btn.is-active { background: var(--color-surface); color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
|
||||
html { min-width: 1280px; }
|
||||
|
||||
.topbar {
|
||||
position: sticky; top: 0; z-index: 20;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: var(--space-4) var(--space-8);
|
||||
background: var(--color-surface);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
.topbar-right { display: flex; align-items: center; gap: var(--space-5); }
|
||||
.nav-link { font: var(--text-body); font-weight: 600; color: var(--color-ink-500); text-decoration: none; }
|
||||
.nav-link.is-active { color: var(--color-ink-700); }
|
||||
.avatar-btn { display: flex; align-items: center; gap: 8px; background: var(--color-bg-alt); border: 1px solid var(--color-border); border-radius: var(--radius-full); padding: 6px 14px 6px 6px; }
|
||||
.avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--color-ink-700); color: var(--color-accent-text); display:flex; align-items:center; justify-content:center; font: var(--text-caption); text-transform: none; letter-spacing: 0; }
|
||||
.avatar-btn .user-name { font: var(--text-body); font-weight: 600; color: var(--color-ink-900); }
|
||||
|
||||
main { padding: var(--space-8); max-width: 1440px; margin: 0 auto; }
|
||||
|
||||
.page-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: var(--space-6); }
|
||||
.page-head h1 { font: var(--text-display-lg); font-family: var(--font-display); color: var(--color-ink-700); margin: 0 0 6px; }
|
||||
.page-head p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0; max-width: 560px; }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; border: none; cursor: pointer; font-family: var(--font-body); white-space: nowrap; transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary { background: var(--color-accent); color: var(--color-accent-text); font: var(--text-body); font-weight: 700; padding: 11px 22px; border-radius: var(--radius-full); }
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-primary:active { background: var(--color-accent-active); }
|
||||
.btn-primary:disabled { background: rgba(122,122,122,.3); color: var(--color-ink-300); cursor: not-allowed; }
|
||||
.btn-secondary { background: transparent; color: var(--color-ink-700); border: 1.5px solid var(--color-border-pill); font: var(--text-body); font-weight: 600; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); }
|
||||
.btn-danger { background: var(--color-danger); color: #fff; font: var(--text-body); font-weight: 700; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
.btn-danger:hover { filter: brightness(0.92); }
|
||||
.btn-text { background: none; border: none; color: var(--color-danger); font: var(--text-body); font-weight: 600; padding: 4px; }
|
||||
.btn-text:hover { text-decoration: underline; }
|
||||
.btn.full { width: 100%; justify-content: center; }
|
||||
:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
|
||||
|
||||
/* ---------- Основной грид: неделя + карточка создания ---------- */
|
||||
.layout-grid { display: grid; grid-template-columns: 1fr 400px; gap: var(--space-6); align-items: start; }
|
||||
|
||||
.week-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); }
|
||||
.week-toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-5); }
|
||||
.date-nav { display: flex; align-items: center; gap: var(--space-3); }
|
||||
.date-nav button { width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-ink-500); display:flex; align-items:center; justify-content:center; }
|
||||
.date-nav button:hover { border-color: var(--color-border-strong); color: var(--color-ink-900); }
|
||||
.date-nav span { font: var(--text-h3); color: var(--color-ink-900); min-width: 200px; text-align: center; }
|
||||
.view-toggle { display: flex; gap: 4px; background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); }
|
||||
.view-toggle button { padding: 7px 16px; border-radius: var(--radius-full); border: none; background: transparent; font: var(--text-body); font-weight: 600; color: var(--color-ink-500); }
|
||||
.view-toggle button.is-active { background: var(--color-surface); color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
|
||||
.week-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--space-4); }
|
||||
.day-col { background: var(--color-bg-alt); border-radius: var(--radius-lg); padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); min-height: 460px; }
|
||||
.day-col.is-today { background: rgba(127,221,168,.10); }
|
||||
.day-col-head { text-align: center; padding-bottom: var(--space-2); margin-bottom: var(--space-1); border-bottom: 1px solid var(--color-border); }
|
||||
.day-col-head .dow { display: block; font: var(--text-caption); color: var(--color-ink-500); }
|
||||
.day-col-head .dom { display: block; font: var(--text-h3); color: var(--color-ink-900); margin-top: 2px; }
|
||||
.day-col.is-today .day-col-head .dom { color: var(--color-ink-700); }
|
||||
|
||||
.conf-chip { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--space-3); display: flex; flex-direction: column; gap: 4px; cursor: pointer; transition: box-shadow var(--transition-fast), border-color var(--transition-fast); text-align: left; }
|
||||
.conf-chip:hover { box-shadow: var(--shadow-sm); border-color: var(--color-border-strong); }
|
||||
.chip-time { display: flex; align-items: center; gap: 4px; font: var(--text-caption); color: var(--color-ink-500); text-transform: none; letter-spacing: normal; }
|
||||
.chip-title { display: flex; align-items: center; gap: 6px; font: var(--text-body); font-weight: 700; color: var(--color-ink-900); }
|
||||
.chip-meta { display: flex; align-items: center; gap: 10px; font: 12px var(--font-body); color: var(--color-ink-500); }
|
||||
.chip-meta .meta-item { display: flex; align-items: center; gap: 4px; }
|
||||
|
||||
.conf-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: var(--radius-full); font: var(--text-caption); font-size: 11px; width: fit-content; }
|
||||
.conf-badge.scheduled { background: var(--color-warning-bg); color: var(--color-warning); }
|
||||
.conf-badge.pinned { background: var(--color-bg-alt); color: var(--color-ink-700); border: 1px solid var(--color-border-strong); }
|
||||
.conf-badge.live { background: var(--color-success-bg); color: var(--color-success); }
|
||||
.conf-badge.cancelled { background: var(--color-danger-bg); color: var(--color-danger); }
|
||||
|
||||
.conf-chip.is-cancelled { opacity: .6; }
|
||||
.conf-chip.is-cancelled .chip-title { text-decoration: line-through; color: var(--color-ink-500); }
|
||||
|
||||
.day-empty { flex: 1; display: flex; align-items: center; justify-content: center; text-align: center; font: var(--text-body); color: var(--color-ink-300); padding: var(--space-4) 0; }
|
||||
|
||||
/* ---------- Карточка создания / редактирования ---------- */
|
||||
.create-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); position: sticky; top: 96px; }
|
||||
.create-card h2 { font: var(--text-h2); color: var(--color-ink-900); margin: 0 0 var(--space-5); display: flex; align-items: center; gap: 8px; }
|
||||
|
||||
.field { margin-bottom: var(--space-5); }
|
||||
.field label { display: flex; align-items: center; gap: 6px; font: var(--text-body); font-weight: 600; color: var(--color-ink-900); margin-bottom: var(--space-2); }
|
||||
.field input, .field textarea, .field select {
|
||||
width: 100%; font: var(--text-body-lg); color: var(--color-ink-900);
|
||||
padding: 10px 14px; border-radius: var(--radius-md); border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
}
|
||||
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--color-focus-ring); box-shadow: 0 0 0 3px rgba(214,168,61,.18); }
|
||||
.field-row { display: flex; gap: var(--space-3); }
|
||||
.field-row .field { flex: 1; }
|
||||
.field-hint { font: 12px var(--font-body); color: var(--color-ink-500); margin: 6px 2px 0; }
|
||||
|
||||
/* Тумблер (используется и для «закрытая по паролю», и для «закрепить») */
|
||||
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) 0; border-top: 1px solid var(--color-border); }
|
||||
.toggle-copy strong { display: block; font: var(--text-body); color: var(--color-ink-900); }
|
||||
.toggle-copy span { font: 12px var(--font-body); color: var(--color-ink-500); }
|
||||
.switch { position: relative; width: 44px; height: 24px; flex-shrink: 0; }
|
||||
.switch input { opacity: 0; width: 0; height: 0; }
|
||||
.slider { position: absolute; inset: 0; background: var(--color-border-strong); border-radius: var(--radius-full); transition: background var(--transition-fast); cursor: pointer; }
|
||||
.slider::before { content:""; position:absolute; width:18px; height:18px; left:3px; top:3px; background:#fff; border-radius:50%; transition: transform var(--transition-fast); }
|
||||
.switch input:checked + .slider { background: var(--color-accent-active); }
|
||||
.switch input:checked + .slider::before { transform: translateX(20px); }
|
||||
.switch input:focus-visible + .slider { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
|
||||
|
||||
.password-block { display: none; margin-top: var(--space-4); }
|
||||
.toggle-block:has(#pw-toggle:checked) .password-block { display: block; }
|
||||
|
||||
/* ---------- Блок повторений (recurrence) ---------- */
|
||||
.pin-block .recurrence-panel { display: none; }
|
||||
.pin-block:has(input[type="checkbox"]:checked) .recurrence-panel {
|
||||
display: flex; flex-direction: column; gap: var(--space-2);
|
||||
margin-top: var(--space-4); padding-top: var(--space-4);
|
||||
border-top: 1px dashed var(--color-border);
|
||||
}
|
||||
|
||||
.recurrence-option-row {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 10px 12px; border: 1px solid var(--color-border); border-radius: var(--radius-md);
|
||||
cursor: pointer; font: var(--text-body); font-weight: 600; color: var(--color-ink-900);
|
||||
transition: border-color var(--transition-fast), background var(--transition-fast);
|
||||
}
|
||||
.recurrence-option-row input[type="radio"] { width: 16px; height: 16px; accent-color: var(--color-ink-700); flex-shrink: 0; }
|
||||
.recurrence-option:has(input:checked) .recurrence-option-row { border-color: var(--color-ink-700); background: var(--color-bg-alt); }
|
||||
|
||||
.recurrence-sub { display: none; padding: var(--space-3) 12px 4px 38px; }
|
||||
.recurrence-option:has(input:checked) .recurrence-sub { display: block; }
|
||||
|
||||
.weekday-toggles { display: flex; gap: 6px; flex-wrap: wrap; }
|
||||
.weekday-chip {
|
||||
width: 34px; height: 34px; border-radius: 50%;
|
||||
border: 1.5px solid var(--color-border); background: var(--color-surface);
|
||||
font: var(--text-caption); color: var(--color-ink-500);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.weekday-chip.is-selected { background: var(--color-ink-700); border-color: var(--color-ink-700); color: var(--color-accent-text); }
|
||||
|
||||
.recurrence-hint { font: 12px var(--font-body); color: var(--color-ink-500); margin-top: 8px; }
|
||||
|
||||
/* ---------- Доп. состояния (ниже основного грида) ---------- */
|
||||
.states-section { margin-top: var(--space-10); }
|
||||
.states-head { margin-bottom: var(--space-5); }
|
||||
.states-head h2 { font: var(--text-h1); color: var(--color-ink-900); margin: 0 0 4px; }
|
||||
.states-head p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0; }
|
||||
.states-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); align-items: start; }
|
||||
|
||||
.state-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); }
|
||||
.screen-label { font: var(--text-caption); color: var(--color-ink-400); margin: 0 0 var(--space-4); }
|
||||
.screen-label b { color: var(--color-ink-700); }
|
||||
|
||||
.next-occurrence { display: flex; align-items: center; gap: 8px; background: var(--color-bg-alt); border-radius: var(--radius-md); padding: 10px 14px; font: var(--text-body); color: var(--color-ink-700); font-weight: 600; margin-bottom: var(--space-5); }
|
||||
|
||||
.btn-row { display: flex; gap: var(--space-3); margin-top: var(--space-5); }
|
||||
.btn-row .btn { flex: 1; justify-content: center; }
|
||||
.danger-link-row { text-align: center; margin-top: var(--space-4); }
|
||||
|
||||
.cancel-alert { display: flex; gap: 10px; background: var(--color-warning-bg); border: 1px solid rgba(214,168,61,.35); color: var(--color-warning); border-radius: var(--radius-md); padding: var(--space-4); font: var(--text-body); margin-bottom: var(--space-5); }
|
||||
.cancel-alert strong { display: block; margin-bottom: 2px; color: var(--color-ink-900); }
|
||||
.cancel-options { display: flex; flex-direction: column; gap: var(--space-3); }
|
||||
.cancel-options .btn { width: 100%; justify-content: center; }
|
||||
|
||||
/* ---------- Патч: заливка danger-кнопок отдельным «глубоким» тоном (не совпадает
|
||||
с pastel-текстовым --color-danger, чтобы белый текст держал контраст) ---------- */
|
||||
.btn-danger { background: var(--color-danger-solid); }
|
||||
.btn-danger:hover { background: var(--color-danger-solid-hover); filter: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-chevron-left" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></symbol>
|
||||
<symbol id="i-chevron-right" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></symbol>
|
||||
<symbol id="i-calendar" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></symbol>
|
||||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-alert" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></symbol>
|
||||
<symbol id="i-plus" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></symbol>
|
||||
<symbol id="i-repeat" viewBox="0 0 24 24"><path d="m17 2 4 4-4 4"/><path d="M3 11v-1a4 4 0 0 1 4-4h14"/><path d="m7 22-4-4 4-4"/><path d="M21 13v1a4 4 0 0 1-4 4H3"/></symbol>
|
||||
<symbol id="i-play" viewBox="0 0 24 24"><polygon points="6 3 20 12 6 21 6 3"/></symbol>
|
||||
<symbol id="i-users" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>
|
||||
<symbol id="i-x" viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></symbol>
|
||||
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></symbol>
|
||||
<symbol id="i-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
<nav class="topbar-right">
|
||||
<a href="lobby.html" class="nav-link">Лобби</a>
|
||||
<a href="calendar.html" class="nav-link is-active">Календарь</a>
|
||||
<a href="my-conferences.html" class="nav-link">Мои конференции</a>
|
||||
<a href="admin.html" class="nav-link">Админка</a>
|
||||
<div class="theme-toggle" role="group" aria-label="Переключить тему оформления">
|
||||
<button class="theme-toggle-btn" type="button" aria-pressed="false" aria-label="Светлая тема"><svg class="icon"><use href="#i-sun"/></svg></button>
|
||||
<button class="theme-toggle-btn is-active" type="button" aria-pressed="true" aria-label="Тёмная тема"><svg class="icon"><use href="#i-moon"/></svg></button>
|
||||
</div>
|
||||
<button class="avatar-btn"><span class="avatar">АИ</span><span class="user-name">Анна Иванова</span></button>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>Календарь конференций</h1>
|
||||
<p>Запланируйте разовую встречу или закрепите постоянную конференцию с повторением — рабочая неделя 14–18 июля</p>
|
||||
</div>
|
||||
<button class="btn btn-primary"><svg class="icon" style="width:16px;height:16px"><use href="#i-plus"/></svg>Новая конференция</button>
|
||||
</div>
|
||||
|
||||
<div class="layout-grid">
|
||||
|
||||
<!-- ===================== СЕТКА КОНФЕРЕНЦИЙ ПО ДНЯМ ===================== -->
|
||||
<section class="week-card">
|
||||
<div class="week-toolbar">
|
||||
<div class="date-nav">
|
||||
<button aria-label="Предыдущая неделя"><svg class="icon" style="width:16px;height:16px"><use href="#i-chevron-left"/></svg></button>
|
||||
<span>14 — 18 июля 2026</span>
|
||||
<button aria-label="Следующая неделя"><svg class="icon" style="width:16px;height:16px"><use href="#i-chevron-right"/></svg></button>
|
||||
</div>
|
||||
<div class="view-toggle">
|
||||
<button class="is-active">Неделя</button>
|
||||
<button>Месяц</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="week-grid">
|
||||
|
||||
<div class="day-col">
|
||||
<div class="day-col-head"><span class="dow">ПН</span><span class="dom">14</span></div>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge scheduled"><svg class="icon" style="width:11px;height:11px"><use href="#i-clock"/></svg>Запланирована</span>
|
||||
<span class="chip-time">09:00–09:15</span>
|
||||
<span class="chip-title">Дейли команды</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>6</span></span>
|
||||
</button>
|
||||
<div class="day-empty">Свободный день</div>
|
||||
</div>
|
||||
|
||||
<div class="day-col is-today">
|
||||
<div class="day-col-head"><span class="dow">ВТ</span><span class="dom">15</span></div>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:11px;height:11px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
<span class="chip-time">11:00–11:45</span>
|
||||
<span class="chip-title">Ревью спринта</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>8</span></span>
|
||||
</button>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge live"><svg class="icon" style="width:11px;height:11px"><use href="#i-play"/></svg>Идёт сейчас</span>
|
||||
<span class="chip-time">14:00–…</span>
|
||||
<span class="chip-title"><svg class="icon" style="width:13px;height:13px;flex-shrink:0"><use href="#i-lock"/></svg>Синк по релизу 2.4</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>4</span></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="day-col">
|
||||
<div class="day-col-head"><span class="dow">СР</span><span class="dom">16</span></div>
|
||||
<button class="conf-chip is-cancelled">
|
||||
<span class="conf-badge cancelled"><svg class="icon" style="width:11px;height:11px"><use href="#i-x"/></svg>Отменена</span>
|
||||
<span class="chip-time">10:00–10:30</span>
|
||||
<span class="chip-title">Собес: Frontend</span>
|
||||
</button>
|
||||
<div class="day-empty">Свободный день</div>
|
||||
</div>
|
||||
|
||||
<div class="day-col">
|
||||
<div class="day-col-head"><span class="dow">ЧТ</span><span class="dom">17</span></div>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:11px;height:11px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
<span class="chip-time">11:00–11:45</span>
|
||||
<span class="chip-title">Ревью спринта</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>8</span></span>
|
||||
</button>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge scheduled"><svg class="icon" style="width:11px;height:11px"><use href="#i-clock"/></svg>Запланирована</span>
|
||||
<span class="chip-time">15:00–15:30</span>
|
||||
<span class="chip-title">1:1 с руководителем</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>2</span></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="day-col">
|
||||
<div class="day-col-head"><span class="dow">ПТ</span><span class="dom">18</span></div>
|
||||
<button class="conf-chip">
|
||||
<span class="conf-badge scheduled"><svg class="icon" style="width:11px;height:11px"><use href="#i-clock"/></svg>Запланирована</span>
|
||||
<span class="chip-time">12:00–13:00</span>
|
||||
<span class="chip-title"><svg class="icon" style="width:13px;height:13px;flex-shrink:0"><use href="#i-lock"/></svg>Итоги квартала</span>
|
||||
<span class="chip-meta"><span class="meta-item"><svg class="icon" style="width:12px;height:12px"><use href="#i-users"/></svg>14</span></span>
|
||||
</button>
|
||||
<div class="day-empty">Ещё нет конференций</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ===================== КАРТОЧКА СОЗДАНИЯ (состояние: создание, пусто) ===================== -->
|
||||
<aside class="create-card" id="create-card">
|
||||
<h2><svg class="icon"><use href="#i-calendar"/></svg>Новая конференция</h2>
|
||||
|
||||
<form>
|
||||
<div class="field">
|
||||
<label>Название</label>
|
||||
<input type="text" placeholder="Например, Синк по релизу 2.4">
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>Дата</label><input type="text" value="21.07.2026"></div>
|
||||
<div class="field"><label>Время</label><input type="text" value="10:00–10:30"></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Участники (email через запятую)</label>
|
||||
<textarea rows="2" placeholder="i.sokolov@company.ru, m.kuznetsova@company.ru"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="toggle-block">
|
||||
<div class="toggle-row" style="border-top:none; padding-top:0">
|
||||
<div class="toggle-copy"><strong>Закрытая по паролю</strong><span>Вход только по паролю, включая гостей</span></div>
|
||||
<label class="switch"><input type="checkbox" id="pw-toggle"><span class="slider"></span></label>
|
||||
</div>
|
||||
<div class="password-block field">
|
||||
<label><svg class="icon" style="width:14px;height:14px"><use href="#i-lock"/></svg>Пароль конференции</label>
|
||||
<input type="password" placeholder="Минимум 6 символов">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pin-block">
|
||||
<div class="toggle-row">
|
||||
<div class="toggle-copy"><strong>Закрепить постоянную конференцию</strong><span>Сохранится и попадёт в «Мои конференции», не исчезнет после встречи</span></div>
|
||||
<label class="switch"><input type="checkbox" id="pin-toggle"><span class="slider"></span></label>
|
||||
</div>
|
||||
|
||||
<!-- Раскрывается по клику на тумблер выше (CSS :has(), без JS) -->
|
||||
<div class="recurrence-panel">
|
||||
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence" checked>
|
||||
По дням недели, еженедельно
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="weekday-toggles">
|
||||
<span class="weekday-chip">ПН</span>
|
||||
<span class="weekday-chip is-selected">ВТ</span>
|
||||
<span class="weekday-chip">СР</span>
|
||||
<span class="weekday-chip is-selected">ЧТ</span>
|
||||
<span class="weekday-chip">ПТ</span>
|
||||
<span class="weekday-chip">СБ</span>
|
||||
<span class="weekday-chip">ВС</span>
|
||||
</div>
|
||||
<p class="recurrence-hint">Ближайшие: вторник 21 июля, четверг 23 июля</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence">
|
||||
Раз в 2 недели
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="field-row">
|
||||
<div class="field" style="margin-bottom:0"><label>Начиная с</label><input type="text" value="21.07.2026"></div>
|
||||
<div class="field" style="margin-bottom:0"><label>День недели</label><select><option>Вторник</option><option>Среда</option></select></div>
|
||||
</div>
|
||||
<p class="recurrence-hint">Следующие: 4 августа, 18 августа</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence">
|
||||
Раз в месяц
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="field"><label>Число месяца</label><input type="text" value="31" inputmode="numeric"></div>
|
||||
<p class="recurrence-hint">Если в месяце нет такого числа — переносится на последний день месяца (напр. 28/29 февраля)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence">
|
||||
Каждые N дней
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="field-row">
|
||||
<div class="field" style="margin-bottom:0"><label>N (дней)</label><input type="text" value="10" inputmode="numeric"></div>
|
||||
<div class="field" style="margin-bottom:0"><label>Начиная с</label><input type="text" value="21.07.2026"></div>
|
||||
</div>
|
||||
<p class="recurrence-hint">Ближайшие: через 10, 20, 30 дней</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary full" style="margin-top: var(--space-5)">Создать конференцию</button>
|
||||
</form>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ===================== ДОП. СОСТОЯНИЯ: РЕДАКТИРОВАНИЕ И ОТМЕНА ===================== -->
|
||||
<section class="states-section">
|
||||
<div class="states-head">
|
||||
<h2>Другие состояния карточки</h2>
|
||||
<p>Раскрытая карточка с закреплением, редактирование существующей закреплённой конференции и отмена вхождения/всех повторений.</p>
|
||||
</div>
|
||||
|
||||
<div class="states-grid">
|
||||
|
||||
<!-- Состояние: редактирование существующей закреплённой конференции -->
|
||||
<div class="state-card">
|
||||
<p class="screen-label">Состояние: <b>редактирование закреплённой конференции</b></p>
|
||||
|
||||
<div class="next-occurrence">
|
||||
<svg class="icon" style="width:16px;height:16px"><use href="#i-clock"/></svg>
|
||||
Следующее вхождение: вторник, 22 июля, 11:00
|
||||
</div>
|
||||
|
||||
<form>
|
||||
<div class="field"><label>Название</label><input type="text" value="Ревью спринта"></div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label>Время</label><input type="text" value="11:00–11:45"></div>
|
||||
<div class="field"><label>Участники</label><input type="text" value="8 человек"></div>
|
||||
</div>
|
||||
|
||||
<div class="pin-block">
|
||||
<div class="toggle-row" style="border-top:none; padding-top:0">
|
||||
<div class="toggle-copy"><strong>Закреплена</strong><span>Повторяется по расписанию</span></div>
|
||||
<label class="switch"><input type="checkbox" id="pin-toggle-edit" checked><span class="slider"></span></label>
|
||||
</div>
|
||||
<div class="recurrence-panel">
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row">
|
||||
<input type="radio" name="recurrence-edit" checked>
|
||||
По дням недели, еженедельно
|
||||
</label>
|
||||
<div class="recurrence-sub">
|
||||
<div class="weekday-toggles">
|
||||
<span class="weekday-chip">ПН</span>
|
||||
<span class="weekday-chip is-selected">ВТ</span>
|
||||
<span class="weekday-chip">СР</span>
|
||||
<span class="weekday-chip is-selected">ЧТ</span>
|
||||
<span class="weekday-chip">ПТ</span>
|
||||
<span class="weekday-chip">СБ</span>
|
||||
<span class="weekday-chip">ВС</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row"><input type="radio" name="recurrence-edit">Раз в 2 недели</label>
|
||||
</div>
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row"><input type="radio" name="recurrence-edit">Раз в месяц</label>
|
||||
</div>
|
||||
<div class="recurrence-option">
|
||||
<label class="recurrence-option-row"><input type="radio" name="recurrence-edit">Каждые N дней</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-row">
|
||||
<button type="submit" class="btn btn-primary">Сохранить изменения</button>
|
||||
<button type="button" class="btn btn-secondary">Открепить</button>
|
||||
</div>
|
||||
<div class="danger-link-row">
|
||||
<button type="button" class="btn-text">Удалить конференцию навсегда</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Состояние: отмена одной / всех повторяющихся -->
|
||||
<div class="state-card">
|
||||
<p class="screen-label">Состояние: <b>отмена вхождения повторяющейся конференции</b></p>
|
||||
|
||||
<div class="cancel-alert">
|
||||
<svg class="icon" style="width:18px;height:18px;flex-shrink:0;margin-top:1px"><use href="#i-alert"/></svg>
|
||||
<div><strong>«Ревью спринта» — вторник, 22 июля, 11:00</strong>Это повторяющаяся конференция (по вторникам и четвергам). Что отменить?</div>
|
||||
</div>
|
||||
|
||||
<div class="cancel-options">
|
||||
<button class="btn btn-secondary"><svg class="icon" style="width:16px;height:16px"><use href="#i-x"/></svg>Отменить только это вхождение</button>
|
||||
<button class="btn btn-danger"><svg class="icon" style="width:16px;height:16px"><use href="#i-x"/></svg>Отменить все повторения</button>
|
||||
</div>
|
||||
<div class="danger-link-row">
|
||||
<button type="button" class="btn-text" style="color: var(--color-ink-500)">Оставить как есть</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
253
design/mockups/dark/join.html
Normal file
253
design/mockups/dark/join.html
Normal file
@@ -0,0 +1,253 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-theme="shell-dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Подключение к конференции — тёмная тема, НА СОГЛАСОВАНИИ</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../../tokens.css">
|
||||
<style>
|
||||
/* =====================================================================
|
||||
* ТЁМНЫЙ ВАРИАНТ ОБОЛОЧКИ — ПРЕДЛОЖЕНИЕ, НЕ УТВЕРЖДЕНО.
|
||||
* Разметка и контент идентичны design/mockups/join.html 1:1, меняется
|
||||
* только цветовая схема — палитра переиспользует токены комнаты
|
||||
* конференции. Обоснование цветов — design/mockups/dark/README.md.
|
||||
* ===================================================================== */
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
--color-bg: #1E1E1E;
|
||||
--color-bg-alt: #242424;
|
||||
--color-surface: #2A2A2A;
|
||||
--color-surface-glass: rgba(51, 51, 51, .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, .14);
|
||||
--color-success-dot: #7FDDA8;
|
||||
|
||||
--color-danger: #EB93A1;
|
||||
--color-danger-bg: rgba(235, 147, 161, .14);
|
||||
--color-danger-dot: #EB93A1;
|
||||
--color-danger-solid: #B85468;
|
||||
--color-danger-solid-hover: #B9495F;
|
||||
|
||||
--color-warning: #D6A83D;
|
||||
--color-warning-bg: rgba(214, 168, 61, .16);
|
||||
--color-warning-dot: #D6A83D;
|
||||
|
||||
--color-focus-ring: #D6A83D;
|
||||
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
|
||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, .4);
|
||||
--shadow-lg: 0 12px 32px rgba(0, 0, 0, .5);
|
||||
--shadow-glass: 0 8px 24px rgba(0, 0, 0, .45);
|
||||
}
|
||||
|
||||
.theme-toggle { display: inline-flex; gap: 2px; background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); border: 1px solid var(--color-border); }
|
||||
.theme-toggle-btn { width: 32px; height: 32px; border-radius: 50%; border: none; background: transparent; color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; }
|
||||
.theme-toggle-btn .icon { width: 16px; height: 16px; }
|
||||
.theme-toggle-btn:hover { color: var(--color-ink-900); }
|
||||
.theme-toggle-btn.is-active { background: var(--color-surface); color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
|
||||
/*
|
||||
* Подключение к конференции (фаза R1, пивот) — три состояния одного flow:
|
||||
* (а) ввод ссылки/номера, (б) «представиться» для гостя (имя обязательно,
|
||||
* email факультативно — для саммари), (в) пароль закрытой конференции.
|
||||
*/
|
||||
|
||||
html { min-width: 1280px; }
|
||||
body { min-height: 100vh; display: flex; flex-direction: column; background: var(--color-bg); }
|
||||
|
||||
.topbar { display: flex; align-items: center; justify-content: space-between; padding: var(--space-5) var(--space-8); }
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); text-decoration: none; }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
|
||||
main { flex: 1; display: flex; flex-direction: column; align-items: center; padding: var(--space-6) var(--space-8) var(--space-16); gap: var(--space-16); }
|
||||
|
||||
.screen-block { width: 100%; max-width: 440px; }
|
||||
.screen-label { font: var(--text-caption); color: var(--color-ink-400); margin: 0 0 var(--space-3); text-align: center; }
|
||||
.screen-label b { color: var(--color-ink-700); }
|
||||
|
||||
.flow-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-8); }
|
||||
.flow-icon { width: 52px; height: 52px; border-radius: var(--radius-full); background: var(--color-bg-alt); color: var(--color-ink-700); display: flex; align-items: center; justify-content: center; margin: 0 auto var(--space-5); }
|
||||
.flow-icon .icon { width: 24px; height: 24px; }
|
||||
.flow-card h1 { font: var(--text-h1); color: var(--color-ink-900); margin: 0 0 var(--space-2); text-align: center; }
|
||||
.flow-card .flow-sub { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0 0 var(--space-6); text-align: center; }
|
||||
|
||||
.field { margin-bottom: var(--space-5); }
|
||||
.field label { display: flex; align-items: center; gap: 6px; font: var(--text-body); font-weight: 600; color: var(--color-ink-900); margin-bottom: var(--space-2); }
|
||||
.field-optional { font-weight: 400; color: var(--color-ink-400); }
|
||||
.input-wrap { position: relative; }
|
||||
.input-wrap .icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--color-ink-400); }
|
||||
.input-wrap input {
|
||||
width: 100%; font: var(--text-body-lg); color: var(--color-ink-900);
|
||||
padding: 11px 14px 11px 42px; border-radius: var(--radius-md); border: 1px solid var(--color-border);
|
||||
background: var(--color-surface); outline: none;
|
||||
}
|
||||
.input-wrap input::placeholder { color: var(--color-ink-300); }
|
||||
.input-wrap input:hover { border-color: var(--color-border-strong); }
|
||||
.input-wrap input:focus { border-color: var(--color-focus-ring); box-shadow: 0 0 0 3px rgba(214,168,61,.18); }
|
||||
.input-wrap .toggle-eye { left: auto; right: 14px; background: none; border: none; padding: 0; cursor: pointer; }
|
||||
.field-hint { margin-top: var(--space-2); font: var(--text-body); color: var(--color-ink-500); }
|
||||
.field.has-error input { border-color: var(--color-danger); box-shadow: 0 0 0 3px rgba(235,147,161,.18); }
|
||||
.error-msg { display: flex; align-items: center; gap: 6px; margin-top: var(--space-2); font: var(--text-body); color: var(--color-danger); }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; border: none; cursor: pointer; font-family: var(--font-body); transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary { background: var(--color-accent); color: var(--color-accent-text); font: var(--text-body-lg); font-weight: 700; padding: 13px 24px; border-radius: var(--radius-full); }
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-primary:active { background: var(--color-accent-active); }
|
||||
.btn-primary[disabled] { background: rgba(122,122,122,.35); color: var(--color-ink-300); cursor: not-allowed; }
|
||||
.btn-secondary { background: transparent; color: var(--color-ink-700); border: 1.5px solid var(--color-border-pill); font: var(--text-body-lg); font-weight: 600; padding: 12px 24px; border-radius: var(--radius-full); }
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); }
|
||||
:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
|
||||
|
||||
.link-back { display: block; text-align: center; margin-top: var(--space-5); font: var(--text-body); font-weight: 600; color: var(--color-ink-500); text-decoration: none; }
|
||||
.link-back:hover { color: var(--color-ink-700); }
|
||||
|
||||
/* Плашка целевой конференции (состояния б/в) */
|
||||
.target-conf { display: flex; align-items: center; gap: 12px; background: var(--color-bg-alt); border-radius: var(--radius-lg); padding: var(--space-4); margin-bottom: var(--space-6); }
|
||||
.target-conf .icon-wrap { width: 40px; height: 40px; border-radius: 50%; background: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-ink-700); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
|
||||
.target-conf strong { display: block; font: var(--text-body); color: var(--color-ink-900); }
|
||||
.target-conf span { font: var(--text-mono-sm); color: var(--color-ink-500); }
|
||||
|
||||
.divider { border: none; border-top: 1px solid var(--color-border); width: 100%; max-width: 720px; margin: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-link2" viewBox="0 0 24 24"><path d="M9 17H7A5 5 0 0 1 7 7h2"/><path d="M15 7h2a5 5 0 1 1 0 10h-2"/><line x1="8" y1="12" x2="16" y2="12"/></symbol>
|
||||
<symbol id="i-hash" viewBox="0 0 24 24"><line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/><line x1="10" y1="3" x2="8" y2="21"/><line x1="16" y1="3" x2="14" y2="21"/></symbol>
|
||||
<symbol id="i-user" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M6 21v-2a6 6 0 0 1 12 0v2"/></symbol>
|
||||
<symbol id="i-mail" viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 6 10 7 10-7"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-eye" viewBox="0 0 24 24"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></symbol>
|
||||
<symbol id="i-eye-off" viewBox="0 0 24 24"><path d="M3 3l18 18"/><path d="M10.58 10.58a2 2 0 0 0 2.83 2.83"/><path d="M9.88 5.09A9.77 9.77 0 0 1 12 5c6.5 0 10 7 10 7a13.16 13.16 0 0 1-3.06 4.06M6.1 6.1A13.16 13.16 0 0 0 2 12s3.5 7 10 7a9.77 9.77 0 0 0 4.9-1.3"/></symbol>
|
||||
<symbol id="i-arrow-right" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></symbol>
|
||||
<symbol id="i-alert" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></symbol>
|
||||
<symbol id="i-video" viewBox="0 0 24 24"><path d="M15 6H4a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-2.5l5 3.5V7l-5 3.5V8a2 2 0 0 0-2-2z"/></symbol>
|
||||
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></symbol>
|
||||
<symbol id="i-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="topbar">
|
||||
<a class="brand-mark" href="lobby.html"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</a>
|
||||
<div class="theme-toggle" role="group" aria-label="Переключить тему оформления">
|
||||
<button class="theme-toggle-btn" type="button" aria-pressed="false" aria-label="Светлая тема"><svg class="icon"><use href="#i-sun"/></svg></button>
|
||||
<button class="theme-toggle-btn is-active" type="button" aria-pressed="true" aria-label="Тёмная тема"><svg class="icon"><use href="#i-moon"/></svg></button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
|
||||
<!-- ===================== (а) ВВОД ССЫЛКИ ИЛИ НОМЕРА ===================== -->
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>ввод ссылки или номера</b></p>
|
||||
<div class="flow-card">
|
||||
<div class="flow-icon" aria-hidden="true"><svg class="icon"><use href="#i-link2"/></svg></div>
|
||||
<h1>Подключиться к конференции</h1>
|
||||
<p class="flow-sub">Вставьте ссылку-приглашение или введите номер конференции</p>
|
||||
|
||||
<form>
|
||||
<div class="field">
|
||||
<label for="join-input">Ссылка или номер</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-hash"/></svg>
|
||||
<input id="join-input" type="text" placeholder="vidconf.ru/j/... или 8842 104" value="8842 104">
|
||||
</div>
|
||||
<p class="field-hint">Найдите номер или ссылку в приглашении организатора</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Продолжить <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</form>
|
||||
<a href="lobby.html" class="link-back">Назад в лобби</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<!-- ===================== (б) ПРЕДСТАВИТЬСЯ (ГОСТЬ) ===================== -->
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>представиться (гость)</b></p>
|
||||
<div class="flow-card">
|
||||
<div class="target-conf">
|
||||
<span class="icon-wrap" aria-hidden="true"><svg class="icon" style="width:18px;height:18px"><use href="#i-video"/></svg></span>
|
||||
<div><strong>Синк по релизу 2.4</strong><span>№ 8842 104</span></div>
|
||||
</div>
|
||||
|
||||
<div class="flow-icon" aria-hidden="true"><svg class="icon"><use href="#i-user"/></svg></div>
|
||||
<h1>Как вас зовут?</h1>
|
||||
<p class="flow-sub">У вас нет аккаунта VidConf — представьтесь, чтобы войти как гость</p>
|
||||
|
||||
<form>
|
||||
<div class="field">
|
||||
<label for="guest-name">Имя<span class="field-optional">· обязательно</span></label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-user"/></svg>
|
||||
<input id="guest-name" type="text" placeholder="Как к вам обращаться" value="Пётр Волков">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="guest-email">Email<span class="field-optional">· необязательно</span></label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-mail"/></svg>
|
||||
<input id="guest-email" type="email" placeholder="you@mail.ru">
|
||||
</div>
|
||||
<p class="field-hint">Укажите, если хотите получить саммари конференции на почту</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Войти в конференцию <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</form>
|
||||
<a href="join.html" class="link-back">Назад</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<!-- ===================== (в) ПАРОЛЬ ЗАКРЫТОЙ КОНФЕРЕНЦИИ ===================== -->
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>пароль закрытой конференции</b> (с состоянием ошибки)</p>
|
||||
<div class="flow-card">
|
||||
<div class="target-conf">
|
||||
<span class="icon-wrap" aria-hidden="true"><svg class="icon" style="width:18px;height:18px"><use href="#i-lock"/></svg></span>
|
||||
<div><strong>Итоги квартала</strong><span>№ 4471 208 · закрытая</span></div>
|
||||
</div>
|
||||
|
||||
<div class="flow-icon" aria-hidden="true"><svg class="icon"><use href="#i-lock"/></svg></div>
|
||||
<h1>Введите пароль</h1>
|
||||
<p class="flow-sub">Эта конференция закрыта — доступ только по паролю от организатора</p>
|
||||
|
||||
<form>
|
||||
<div class="field has-error">
|
||||
<label for="join-pass">Пароль конференции</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-lock"/></svg>
|
||||
<input id="join-pass" type="password" placeholder="••••••••" value="wrongpass">
|
||||
<button type="button" class="toggle-eye" aria-label="Показать пароль">
|
||||
<svg class="icon"><use href="#i-eye"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="error-msg"><svg class="icon" style="width:16px;height:16px"><use href="#i-alert"/></svg> Неверный пароль, попробуйте ещё раз</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Войти <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</form>
|
||||
<a href="join.html" class="link-back">Назад</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
403
design/mockups/dark/lobby.html
Normal file
403
design/mockups/dark/lobby.html
Normal file
@@ -0,0 +1,403 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-theme="shell-dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Лобби (хаб действий) — тёмная тема, НА СОГЛАСОВАНИИ</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../../tokens.css">
|
||||
<style>
|
||||
/* =====================================================================
|
||||
* ТЁМНЫЙ ВАРИАНТ ОБОЛОЧКИ — ПРЕДЛОЖЕНИЕ, НЕ УТВЕРЖДЕНО.
|
||||
* Разметка и контент идентичны design/mockups/lobby.html 1:1, меняется
|
||||
* только цветовая схема — палитра переиспользует токены комнаты
|
||||
* конференции. Обоснование цветов — design/mockups/dark/README.md.
|
||||
* ===================================================================== */
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
--color-bg: #1E1E1E;
|
||||
--color-bg-alt: #242424;
|
||||
--color-surface: #2A2A2A;
|
||||
--color-surface-glass: rgba(51, 51, 51, .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, .14);
|
||||
--color-success-dot: #7FDDA8;
|
||||
|
||||
--color-danger: #EB93A1;
|
||||
--color-danger-bg: rgba(235, 147, 161, .14);
|
||||
--color-danger-dot: #EB93A1;
|
||||
--color-danger-solid: #B85468;
|
||||
--color-danger-solid-hover: #B9495F;
|
||||
|
||||
--color-warning: #D6A83D;
|
||||
--color-warning-bg: rgba(214, 168, 61, .16);
|
||||
--color-warning-dot: #D6A83D;
|
||||
|
||||
--color-focus-ring: #D6A83D;
|
||||
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
|
||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, .4);
|
||||
--shadow-lg: 0 12px 32px rgba(0, 0, 0, .5);
|
||||
--shadow-glass: 0 8px 24px rgba(0, 0, 0, .45);
|
||||
}
|
||||
|
||||
.theme-toggle { display: inline-flex; gap: 2px; background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); border: 1px solid var(--color-border); }
|
||||
.theme-toggle-btn { width: 32px; height: 32px; border-radius: 50%; border: none; background: transparent; color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; }
|
||||
.theme-toggle-btn .icon { width: 16px; height: 16px; }
|
||||
.theme-toggle-btn:hover { color: var(--color-ink-900); }
|
||||
.theme-toggle-btn.is-active { background: var(--color-surface); color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
|
||||
html { height: 100%; min-width: 1280px; }
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background:
|
||||
radial-gradient(1100px 520px at 10% -10%, rgba(214, 168, 61, 0.05), transparent 60%),
|
||||
radial-gradient(900px 480px at 105% 110%, rgba(127, 221, 168, 0.14), transparent 55%),
|
||||
var(--color-bg);
|
||||
}
|
||||
|
||||
/* ---------- Верхняя панель ---------- */
|
||||
.topbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: var(--space-5) var(--space-8);
|
||||
}
|
||||
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
|
||||
.topbar-right { display: flex; align-items: center; gap: var(--space-4); }
|
||||
|
||||
.burger {
|
||||
width: 44px; height: 44px;
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--color-ink-700);
|
||||
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
.burger:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-sm); }
|
||||
.burger[aria-expanded="true"] { border-color: var(--color-ink-700); }
|
||||
|
||||
.menu-wrap { position: relative; }
|
||||
.menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 10px);
|
||||
right: 0;
|
||||
min-width: 236px;
|
||||
padding: var(--space-2);
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-lg);
|
||||
display: none;
|
||||
z-index: 30;
|
||||
}
|
||||
.menu.is-open { display: block; }
|
||||
.menu a {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 10px 14px;
|
||||
border-radius: var(--radius-sm);
|
||||
font: var(--text-body-lg); font-weight: 600;
|
||||
color: var(--color-ink-900);
|
||||
text-decoration: none;
|
||||
}
|
||||
.menu a:hover { background: var(--color-bg-alt); color: var(--color-ink-700); }
|
||||
.menu a .icon { color: var(--color-ink-400); }
|
||||
.menu-divider { height: 1px; background: var(--color-border); margin: var(--space-2) 6px; }
|
||||
.menu a.danger { color: var(--color-danger); }
|
||||
.menu a.danger .icon { color: var(--color-danger); }
|
||||
|
||||
.user-pill {
|
||||
display: inline-flex; align-items: center; gap: 10px;
|
||||
padding: 6px 16px 6px 6px;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-full);
|
||||
font: var(--text-body); font-weight: 600; color: var(--color-ink-900);
|
||||
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
.user-pill:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-sm); }
|
||||
.user-pill .avatar {
|
||||
width: 30px; height: 30px; border-radius: 50%;
|
||||
background: var(--color-ink-700); color: var(--color-accent-text);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font: var(--text-caption);
|
||||
}
|
||||
|
||||
/* ---------- Мозаика действий ---------- */
|
||||
main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: var(--space-6) var(--space-8) var(--space-12);
|
||||
}
|
||||
|
||||
.hub-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--space-8); width: 100%; }
|
||||
.hub-intro { text-align: center; max-width: 560px; }
|
||||
.hub-intro .eyebrow { font: var(--text-caption); color: var(--color-ink-400); margin: 0 0 var(--space-2); }
|
||||
.hub-intro h1 { font: var(--text-display-lg); font-family: var(--font-display); color: var(--color-ink-700); margin: 0; }
|
||||
|
||||
.hub {
|
||||
position: relative;
|
||||
width: min(1420px, 100%);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-rows: repeat(2, 340px);
|
||||
gap: var(--space-8);
|
||||
}
|
||||
|
||||
.action {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
gap: var(--space-3);
|
||||
padding: var(--space-10) var(--space-12) var(--space-8);
|
||||
margin-top: 34px;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-3xl);
|
||||
text-decoration: none;
|
||||
color: var(--color-ink-900);
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition:
|
||||
transform var(--transition-base),
|
||||
box-shadow var(--transition-base),
|
||||
border-color var(--transition-base);
|
||||
}
|
||||
.action:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
border-color: var(--color-border-strong);
|
||||
}
|
||||
.action:active { transform: translateY(-1px); }
|
||||
|
||||
.action-icon {
|
||||
position: absolute;
|
||||
top: -34px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 68px; height: 68px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-surface);
|
||||
border: var(--border-thick) solid var(--color-ink-700);
|
||||
color: var(--color-ink-700);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
.action-icon .icon { width: 30px; height: 30px; }
|
||||
|
||||
.action-title {
|
||||
margin: 0;
|
||||
font: 600 40px/1.2 var(--font-display);
|
||||
letter-spacing: 0.01em;
|
||||
color: var(--color-ink-700);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.action-object { margin: 0; font: 600 21px/1.35 var(--font-body); color: var(--color-ink-900); }
|
||||
.action-note { margin: 0; font: 400 17px/1.5 var(--font-body); color: var(--color-ink-500); }
|
||||
|
||||
.action--create {
|
||||
background: var(--color-accent);
|
||||
border-color: transparent;
|
||||
}
|
||||
.action--create:hover { background: var(--color-accent-hover); border-color: transparent; }
|
||||
.action--create:active { background: var(--color-accent-active); }
|
||||
.action--create .action-title { font: 700 54px/1.1 var(--font-display); }
|
||||
.action--create .action-title,
|
||||
.action--create .action-object { color: var(--color-accent-text); }
|
||||
.action--create .action-note { color: var(--color-ink-700); }
|
||||
.action--create .action-icon {
|
||||
background: var(--color-accent);
|
||||
border-color: var(--color-accent-text);
|
||||
color: var(--color-accent-text);
|
||||
}
|
||||
|
||||
/* ---------- Медальон VidConf в центре мозаики ---------- */
|
||||
.hub-logo {
|
||||
position: absolute;
|
||||
top: 373px; left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 156px; height: 156px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-surface);
|
||||
border: var(--border-thick) solid var(--color-ink-700);
|
||||
box-shadow: var(--shadow-lg);
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
gap: 6px;
|
||||
z-index: 20;
|
||||
pointer-events: none;
|
||||
}
|
||||
.hub-logo .logo-mark {
|
||||
width: 56px; height: 56px;
|
||||
color: var(--color-ink-700);
|
||||
}
|
||||
.hub-logo .logo-word {
|
||||
font: 600 16px/1 var(--font-display);
|
||||
color: var(--color-ink-700);
|
||||
}
|
||||
|
||||
/* ---------- Появление ---------- */
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.action, .hub-logo {
|
||||
animation: rise 480ms cubic-bezier(0.22, 0.9, 0.3, 1) backwards;
|
||||
}
|
||||
.action--create { animation-delay: 60ms; }
|
||||
.action--calendar { animation-delay: 140ms; }
|
||||
.action--join { animation-delay: 220ms; }
|
||||
.action--mine { animation-delay: 300ms; }
|
||||
.hub-logo { animation-delay: 420ms; }
|
||||
@keyframes rise {
|
||||
from { opacity: 0; transform: translateY(14px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
.hub-logo { animation-name: rise-logo; }
|
||||
@keyframes rise-logo {
|
||||
from { opacity: 0; transform: translate(-50%, calc(-50% + 14px)); }
|
||||
to { opacity: 1; transform: translate(-50%, -50%); }
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none" aria-hidden="true">
|
||||
<symbol id="i-video" viewBox="0 0 24 24"><path d="M15 6H4a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-2.5l5 3.5V7l-5 3.5V8a2 2 0 0 0-2-2z"/></symbol>
|
||||
<symbol id="i-calendar" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></symbol>
|
||||
<symbol id="i-link2" viewBox="0 0 24 24"><path d="M9 17H7A5 5 0 0 1 7 7h2"/><path d="M15 7h2a5 5 0 1 1 0 10h-2"/><line x1="8" y1="12" x2="16" y2="12"/></symbol>
|
||||
<symbol id="i-user" viewBox="0 0 24 24"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></symbol>
|
||||
<symbol id="i-download" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></symbol>
|
||||
<symbol id="i-info" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></symbol>
|
||||
<symbol id="i-layout-dashboard" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="9" rx="1"/><rect x="14" y="3" width="7" height="5" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/><rect x="3" y="16" width="7" height="5" rx="1"/></symbol>
|
||||
<symbol id="i-logout" viewBox="0 0 24 24"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></symbol>
|
||||
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></symbol>
|
||||
<symbol id="i-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
|
||||
<div class="topbar-right">
|
||||
<div class="theme-toggle" role="group" aria-label="Переключить тему оформления">
|
||||
<button class="theme-toggle-btn" type="button" aria-pressed="false" aria-label="Светлая тема"><svg class="icon"><use href="#i-sun"/></svg></button>
|
||||
<button class="theme-toggle-btn is-active" type="button" aria-pressed="true" aria-label="Тёмная тема"><svg class="icon"><use href="#i-moon"/></svg></button>
|
||||
</div>
|
||||
<button class="user-pill">
|
||||
<span class="avatar" aria-hidden="true">ИИ</span>
|
||||
Иванов Иван
|
||||
</button>
|
||||
<div class="menu-wrap">
|
||||
<button class="burger" id="burger" aria-expanded="false" aria-controls="main-menu" aria-label="Открыть меню">
|
||||
<svg class="icon" viewBox="0 0 24 24"><line x1="4" y1="7" x2="20" y2="7"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="17" x2="20" y2="17"/></svg>
|
||||
</button>
|
||||
<nav class="menu" id="main-menu" aria-label="Основное меню">
|
||||
<a href="#"><svg class="icon"><use href="#i-user"/></svg> Профиль</a>
|
||||
<a href="admin.html"><svg class="icon"><use href="#i-layout-dashboard"/></svg> Админка</a>
|
||||
<a href="#"><svg class="icon"><use href="#i-download"/></svg> Скачать приложение</a>
|
||||
<a href="#"><svg class="icon"><use href="#i-info"/></svg> О сервисе</a>
|
||||
<div class="menu-divider"></div>
|
||||
<a href="login.html" class="danger"><svg class="icon"><use href="#i-logout"/></svg> Выйти</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="hub-wrap">
|
||||
<div class="hub-intro">
|
||||
<p class="eyebrow">[ ДОБРО ПОЖАЛОВАТЬ В VIDCONF ]</p>
|
||||
<h1>Что делаем сегодня?</h1>
|
||||
</div>
|
||||
|
||||
<div class="hub">
|
||||
|
||||
<a class="action action--create" href="../room.html">
|
||||
<span class="action-icon" aria-hidden="true"><svg class="icon"><use href="#i-video"/></svg></span>
|
||||
<h2 class="action-title">Создать</h2>
|
||||
<p class="action-object">конференцию</p>
|
||||
<p class="action-note">начнётся сразу — вы первый участник</p>
|
||||
</a>
|
||||
|
||||
<a class="action action--calendar" href="calendar.html">
|
||||
<span class="action-icon" aria-hidden="true"><svg class="icon"><use href="#i-calendar"/></svg></span>
|
||||
<h2 class="action-title">Календарь</h2>
|
||||
<p class="action-object">конференций</p>
|
||||
<p class="action-note">запланировать · закрепить · повторять</p>
|
||||
</a>
|
||||
|
||||
<a class="action action--join" href="join.html">
|
||||
<span class="action-icon" aria-hidden="true"><svg class="icon"><use href="#i-link2"/></svg></span>
|
||||
<h2 class="action-title">Подключиться</h2>
|
||||
<p class="action-object">к конференции</p>
|
||||
<p class="action-note">по ссылке или номеру</p>
|
||||
</a>
|
||||
|
||||
<a class="action action--mine" href="my-conferences.html">
|
||||
<span class="action-icon" aria-hidden="true"><svg class="icon"><use href="#i-user"/></svg></span>
|
||||
<h2 class="action-title">Мои</h2>
|
||||
<p class="action-object">конференции</p>
|
||||
<p class="action-note">закреплённые и предстоящие</p>
|
||||
</a>
|
||||
|
||||
<div class="hub-logo" aria-hidden="true">
|
||||
<svg class="logo-mark" viewBox="0 0 64 64" fill="none" aria-hidden="true">
|
||||
<polygon points="41,32 36.5,39.8 27.5,39.8 23,32 27.5,24.2 36.5,24.2" fill="currentColor"/>
|
||||
<circle cx="32" cy="32" r="15" stroke="currentColor" stroke-width="3" stroke-dasharray="16 7 28 9 12 16" stroke-dashoffset="5"/>
|
||||
<circle cx="32" cy="32" r="20" stroke="currentColor" stroke-width="2" stroke-dasharray="22 10 8 14 34 12 6 10" stroke-dashoffset="40"/>
|
||||
<circle cx="32" cy="32" r="25" stroke="currentColor" stroke-width="3.5" stroke-dasharray="40 14 12 10 26 16 20 8" stroke-dashoffset="80"/>
|
||||
<circle cx="32" cy="32" r="29" stroke="currentColor" stroke-width="1.6" stroke-dasharray="10 6 60 20 30 10 24 8" stroke-dashoffset="120"/>
|
||||
</svg>
|
||||
<span class="logo-word">VidConf</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Бургер-меню: открытие/закрытие, клик мимо и Escape закрывают.
|
||||
const burger = document.getElementById('burger');
|
||||
const menu = document.getElementById('main-menu');
|
||||
|
||||
function setMenu(open) {
|
||||
menu.classList.toggle('is-open', open);
|
||||
burger.setAttribute('aria-expanded', String(open));
|
||||
burger.setAttribute('aria-label', open ? 'Закрыть меню' : 'Открыть меню');
|
||||
}
|
||||
|
||||
burger.addEventListener('click', () => setMenu(!menu.classList.contains('is-open')));
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!e.target.closest('.menu-wrap')) setMenu(false);
|
||||
});
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') { setMenu(false); burger.focus(); }
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
401
design/mockups/dark/login.html
Normal file
401
design/mockups/dark/login.html
Normal file
@@ -0,0 +1,401 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-theme="shell-dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Вход / Регистрация / Подтверждение email (тёмная тема, НА СОГЛАСОВАНИИ)</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../../tokens.css">
|
||||
<style>
|
||||
/* =====================================================================
|
||||
* ТЁМНЫЙ ВАРИАНТ ОБОЛОЧКИ — ПРЕДЛОЖЕНИЕ, НЕ УТВЕРЖДЕНО.
|
||||
* Разметка и контент идентичны design/mockups/auth.html 1:1, меняется
|
||||
* только цветовая схема. Палитра переиспользует токены комнаты
|
||||
* конференции (tokens.css, [data-theme="room"]) — единая тёмная гамма:
|
||||
* графит + пастельная мята/розово-красный/жёлто-оранжевый.
|
||||
* Происхождение цветов и обоснование — design/mockups/dark/README.md.
|
||||
* Технически: блок :root ниже переопределяет одноимённые переменные
|
||||
* оболочки из tokens.css (та же специфичность :root, но позже в
|
||||
* источнике — выигрывает), поэтому весь остальной CSS ниже скопирован
|
||||
* из auth.html БЕЗ ИЗМЕНЕНИЙ и автоматически перекрашивается.
|
||||
* ===================================================================== */
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
--color-bg: #1E1E1E; /* = --color-room-bg */
|
||||
--color-bg-alt: #242424; /* новый: между bg и surface */
|
||||
--color-surface: #2A2A2A; /* = --color-room-surface */
|
||||
--color-surface-glass: rgba(51, 51, 51, .55); /* на основе --color-room-surface-raised */
|
||||
|
||||
--color-border: #3F3F3F; /* = --color-room-tile-border */
|
||||
--color-border-strong: #585858; /* новый, hover-обводка */
|
||||
--color-border-pill: #7FDDA8; /* = --color-room-mic-on */
|
||||
|
||||
--color-ink-900: #E8E8E8; /* = --color-room-text-primary */
|
||||
--color-ink-700: #7FDDA8; /* = --color-room-mic-on — бренд/заголовки/ссылки */
|
||||
--color-ink-500: #B0B0B0; /* = --color-room-text-secondary */
|
||||
--color-ink-400: #5D9A78; /* новый, приглушённая мята, крупный текст ⚠︎ */
|
||||
--color-ink-300: #7A7A7A; /* = --color-room-text-tertiary */
|
||||
|
||||
--color-accent: #7FDDA8; /* = --color-room-mic-on */
|
||||
--color-accent-hover: #75CA9A; /* новый */
|
||||
--color-accent-active: #6CB78C; /* новый */
|
||||
--color-accent-text: #10331F; /* новый, тёмный ink (прецедент room.html) */
|
||||
|
||||
--color-success: #7FDDA8;
|
||||
--color-success-bg: rgba(127, 221, 168, .14);
|
||||
--color-success-dot: #7FDDA8;
|
||||
|
||||
--color-danger: #EB93A1; /* = --color-room-mic-off */
|
||||
--color-danger-bg: rgba(235, 147, 161, .14);
|
||||
--color-danger-dot: #EB93A1;
|
||||
--color-danger-solid: #B85468; /* = --color-room-danger-bg, заливка danger-кнопок */
|
||||
--color-danger-solid-hover: #B9495F;
|
||||
|
||||
--color-warning: #D6A83D; /* = --color-room-speaker-ring */
|
||||
--color-warning-bg: rgba(214, 168, 61, .16);
|
||||
--color-warning-dot: #D6A83D;
|
||||
|
||||
--color-focus-ring: #D6A83D; /* = --color-room-focus-ring */
|
||||
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
|
||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, .4);
|
||||
--shadow-lg: 0 12px 32px rgba(0, 0, 0, .5);
|
||||
--shadow-glass: 0 8px 24px rgba(0, 0, 0, .45);
|
||||
}
|
||||
|
||||
/* Переключатель темы (солнце/луна) — статичная демонстрация, не функциональна в макете */
|
||||
.theme-toggle { position: fixed; top: 24px; right: 32px; z-index: 50; display: inline-flex; gap: 2px; background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); border: 1px solid var(--color-border); box-shadow: var(--shadow-md); }
|
||||
.theme-toggle-btn { width: 32px; height: 32px; border-radius: 50%; border: none; background: transparent; color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; }
|
||||
.theme-toggle-btn .icon { width: 16px; height: 16px; }
|
||||
.theme-toggle-btn:hover { color: var(--color-ink-900); }
|
||||
.theme-toggle-btn.is-active { background: var(--color-surface); color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
|
||||
html { min-width: 1280px; }
|
||||
body { min-height: 100vh; }
|
||||
|
||||
.layout { display: flex; min-height: 100vh; }
|
||||
|
||||
/* ---------- Брендовая панель ---------- */
|
||||
.brand-panel {
|
||||
width: 42%;
|
||||
background: linear-gradient(160deg, #242424 0%, #1E1E1E 55%, #1A1A1A 100%);
|
||||
padding: var(--space-12) var(--space-12);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-right: 1px solid var(--color-border);
|
||||
}
|
||||
.brand-panel::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -120px; bottom: -120px;
|
||||
width: 380px; height: 380px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 30% 30%, rgba(127,221,168,.16), rgba(127,221,168,0) 70%);
|
||||
}
|
||||
.brand-mark {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
font: var(--text-h3);
|
||||
color: var(--color-ink-700);
|
||||
z-index: 1;
|
||||
}
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
|
||||
.brand-copy { z-index: 1; }
|
||||
.eyebrow {
|
||||
font: var(--text-caption);
|
||||
letter-spacing: .08em;
|
||||
color: var(--color-ink-400);
|
||||
margin: 0 0 var(--space-4);
|
||||
}
|
||||
.brand-headline {
|
||||
font: var(--text-display-lg);
|
||||
font-family: var(--font-display);
|
||||
color: var(--color-ink-700);
|
||||
margin: 0 0 var(--space-4);
|
||||
max-width: 460px;
|
||||
}
|
||||
.brand-sub {
|
||||
font: var(--text-body-lg);
|
||||
color: var(--color-ink-500);
|
||||
max-width: 420px;
|
||||
margin: 0;
|
||||
}
|
||||
.brand-stats { display: flex; gap: var(--space-4); z-index: 1; margin-top: var(--space-8); }
|
||||
.stat-glass {
|
||||
background: var(--color-surface-glass);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
border: 1px solid rgba(255,255,255,.08);
|
||||
box-shadow: var(--shadow-glass);
|
||||
border-radius: var(--radius-xl);
|
||||
padding: var(--space-4) var(--space-5);
|
||||
min-width: 140px;
|
||||
}
|
||||
.stat-glass strong { display: block; font: var(--text-h1); font-family: var(--font-display); color: var(--color-ink-700); }
|
||||
.stat-glass span { font: var(--text-caption); color: var(--color-ink-500); text-transform: none; letter-spacing: normal; }
|
||||
|
||||
/* ---------- Форма-панель ---------- */
|
||||
.form-panel {
|
||||
width: 58%;
|
||||
padding: var(--space-12) var(--space-16);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-16);
|
||||
}
|
||||
.screen-block { max-width: 440px; }
|
||||
.screen-label {
|
||||
font: var(--text-caption);
|
||||
color: var(--color-ink-400);
|
||||
margin: 0 0 var(--space-3);
|
||||
}
|
||||
.screen-label b { color: var(--color-ink-700); }
|
||||
.screen-title { font: var(--text-h1); color: var(--color-ink-900); margin: 0 0 var(--space-8); }
|
||||
|
||||
.divider { border: none; border-top: 1px solid var(--color-border); max-width: 720px; margin: 0; }
|
||||
|
||||
.tabs { display: flex; gap: var(--space-2); margin-bottom: var(--space-6); background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); width: fit-content; }
|
||||
.tab { padding: 8px 20px; border-radius: var(--radius-full); border: none; background: transparent; font: var(--text-body); color: var(--color-ink-500); }
|
||||
.tab.is-active { background: var(--color-surface); color: var(--color-ink-700); font-weight: 600; box-shadow: var(--shadow-sm); }
|
||||
|
||||
.field { margin-bottom: var(--space-5); }
|
||||
.field label { display: block; font: var(--text-body); font-weight: 600; color: var(--color-ink-900); margin-bottom: var(--space-2); }
|
||||
.input-wrap { position: relative; }
|
||||
.input-wrap .icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--color-ink-400); }
|
||||
.input-wrap input {
|
||||
width: 100%;
|
||||
font: var(--text-body-lg);
|
||||
color: var(--color-ink-900);
|
||||
padding: 11px 14px 11px 42px;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
outline: none;
|
||||
}
|
||||
.input-wrap input::placeholder { color: var(--color-ink-300); }
|
||||
.input-wrap input:hover { border-color: var(--color-border-strong); }
|
||||
.input-wrap input:focus { border-color: var(--color-focus-ring); box-shadow: 0 0 0 3px rgba(214,168,61,.18); }
|
||||
.input-wrap .toggle-eye { left: auto; right: 14px; background: none; border: none; padding: 0; cursor: pointer; }
|
||||
|
||||
.field.has-error input { border-color: var(--color-danger); box-shadow: 0 0 0 3px rgba(235,147,161,.18); }
|
||||
.error-msg { display: flex; align-items: center; gap: 6px; margin-top: var(--space-2); font: var(--text-body); color: var(--color-danger); }
|
||||
.hint-msg { margin-top: var(--space-2); font: var(--text-body); color: var(--color-ink-500); }
|
||||
|
||||
.field-disabled input { background: var(--color-bg-alt); color: var(--color-ink-300); cursor: not-allowed; }
|
||||
|
||||
.row-between { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-6); }
|
||||
.checkbox-row { display: flex; align-items: center; gap: 8px; font: var(--text-body); color: var(--color-ink-500); }
|
||||
.link { color: var(--color-ink-700); font-weight: 600; text-decoration: none; }
|
||||
.link:hover { text-decoration: underline; }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; border: none; cursor: pointer; font-family: var(--font-body); transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary {
|
||||
width: 100%;
|
||||
background: var(--color-accent);
|
||||
color: var(--color-accent-text);
|
||||
font: var(--text-body-lg);
|
||||
font-weight: 700;
|
||||
padding: 13px 24px;
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-primary:active { background: var(--color-accent-active); }
|
||||
.btn-primary[disabled] { background: rgba(122,122,122,.35); color: var(--color-ink-300); cursor: not-allowed; }
|
||||
|
||||
.btn-secondary {
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
color: var(--color-ink-700);
|
||||
border: 1.5px solid var(--color-border-pill);
|
||||
font: var(--text-body-lg);
|
||||
font-weight: 600;
|
||||
padding: 12px 24px;
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); border-color: var(--color-ink-700); }
|
||||
|
||||
.oauth-row { display: flex; gap: var(--space-3); margin-top: var(--space-5); }
|
||||
.oauth-row .btn-secondary { flex: 1; }
|
||||
|
||||
.separator { display: flex; align-items: center; gap: 12px; color: var(--color-ink-400); font: var(--text-caption); margin: var(--space-6) 0; text-transform: none; letter-spacing: normal; }
|
||||
.separator::before, .separator::after { content: ""; flex: 1; height: 1px; background: var(--color-border); }
|
||||
|
||||
/* ---------- Подтверждение email ---------- */
|
||||
.confirm-card {
|
||||
max-width: 440px;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-2xl);
|
||||
padding: var(--space-8);
|
||||
text-align: left;
|
||||
}
|
||||
.confirm-icon {
|
||||
width: 56px; height: 56px; border-radius: var(--radius-full);
|
||||
background: var(--color-success-bg); color: var(--color-success);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
margin-bottom: var(--space-5);
|
||||
}
|
||||
.confirm-icon .icon { width: 28px; height: 28px; }
|
||||
.confirm-card h3 { font: var(--text-h2); color: var(--color-ink-900); margin: 0 0 var(--space-2); }
|
||||
.confirm-card p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0 0 var(--space-6); }
|
||||
.confirm-card .mail-chip {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
background: var(--color-bg-alt); border-radius: var(--radius-full);
|
||||
padding: 6px 14px; font: var(--text-mono-sm); color: var(--color-ink-700);
|
||||
margin-bottom: var(--space-6);
|
||||
}
|
||||
|
||||
/* pending confirmation state variant */
|
||||
.confirm-card.pending .confirm-icon { background: var(--color-warning-bg); color: var(--color-warning); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-mail" viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 6 10 7 10-7"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-user" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M6 21v-2a6 6 0 0 1 12 0v2"/></symbol>
|
||||
<symbol id="i-eye" viewBox="0 0 24 24"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></symbol>
|
||||
<symbol id="i-eye-off" viewBox="0 0 24 24"><path d="M3 3l18 18"/><path d="M10.58 10.58a2 2 0 0 0 2.83 2.83"/><path d="M9.88 5.09A9.77 9.77 0 0 1 12 5c6.5 0 10 7 10 7a13.16 13.16 0 0 1-3.06 4.06M6.1 6.1A13.16 13.16 0 0 0 2 12s3.5 7 10 7a9.77 9.77 0 0 0 4.9-1.3"/></symbol>
|
||||
<symbol id="i-check-circle" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></symbol>
|
||||
<symbol id="i-arrow-right" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></symbol>
|
||||
<symbol id="i-alert" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></symbol>
|
||||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
||||
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></symbol>
|
||||
<symbol id="i-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<div class="theme-toggle" role="group" aria-label="Переключить тему оформления">
|
||||
<button class="theme-toggle-btn" type="button" aria-pressed="false" aria-label="Светлая тема"><svg class="icon"><use href="#i-sun"/></svg></button>
|
||||
<button class="theme-toggle-btn is-active" type="button" aria-pressed="true" aria-label="Тёмная тема"><svg class="icon"><use href="#i-moon"/></svg></button>
|
||||
</div>
|
||||
|
||||
<div class="layout">
|
||||
|
||||
<!-- ===================== БРЕНД-ПАНЕЛЬ ===================== -->
|
||||
<aside class="brand-panel">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
<div class="brand-copy">
|
||||
<p class="eyebrow">[ SELF-HOSTED ВИДЕОКОНФЕРЕНЦИИ ]</p>
|
||||
<h1 class="brand-headline">Ваши встречи.<br>Ваша инфраструктура.</h1>
|
||||
<p class="brand-sub">Видео, записи и AI-саммари обрабатываются на ваших серверах - данные не уходят
|
||||
за пределы вашей инфраструктуры. Гости подключаются по ссылке или номеру, без регистрации.</p>
|
||||
<div class="brand-stats">
|
||||
<div class="stat-glass"><strong>100%</strong><span>данных - в вашем контуре</span></div>
|
||||
<div class="stat-glass"><strong>AI-саммари</strong><span>на почту после встречи</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="hint-msg" style="z-index:1">© 2026 VidConf · self-hosted</p>
|
||||
</aside>
|
||||
|
||||
<!-- ===================== ФОРМА: ВХОД / РЕГИСТРАЦИЯ ===================== -->
|
||||
<main class="form-panel">
|
||||
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>вход в аккаунт</b></p>
|
||||
<div class="tabs" role="tablist" aria-label="Способ авторизации">
|
||||
<button class="tab is-active" role="tab" aria-selected="true">Вход</button>
|
||||
<button class="tab" role="tab" aria-selected="false">Регистрация</button>
|
||||
</div>
|
||||
|
||||
<form>
|
||||
<div class="field">
|
||||
<label for="login-email">Рабочая почта</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-mail"/></svg>
|
||||
<input id="login-email" type="email" placeholder="you@company.ru" value="a.ivanova@vidconf.dev">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field has-error">
|
||||
<label for="login-pass">Пароль</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-lock"/></svg>
|
||||
<input id="login-pass" type="password" placeholder="••••••••" value="wrongpass">
|
||||
<button type="button" class="toggle-eye" aria-label="Показать пароль">
|
||||
<svg class="icon"><use href="#i-eye"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="error-msg"><svg class="icon" style="width:16px;height:16px"><use href="#i-alert"/></svg> Неверный email или пароль</p>
|
||||
</div>
|
||||
|
||||
<div class="row-between">
|
||||
<label class="checkbox-row"><input type="checkbox" checked> Запомнить меня</label>
|
||||
<a href="#" class="link">Забыли пароль?</a>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Войти <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>регистрация</b></p>
|
||||
<h2 class="screen-title">Создать аккаунт</h2>
|
||||
<form>
|
||||
<div class="field">
|
||||
<label for="reg-name">Имя и фамилия</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-user"/></svg>
|
||||
<input id="reg-name" type="text" placeholder="Мария Кузнецова">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="reg-email">Рабочая почта</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-mail"/></svg>
|
||||
<input id="reg-email" type="email" placeholder="you@company.ru">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="reg-pass">Пароль</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-lock"/></svg>
|
||||
<input id="reg-pass" type="password" placeholder="Минимум 8 символов">
|
||||
<button type="button" class="toggle-eye" aria-label="Скрыть пароль">
|
||||
<svg class="icon"><use href="#i-eye-off"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="hint-msg">Минимум 8 символов, буквы и цифры</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" style="margin-top:8px">Зарегистрироваться</button>
|
||||
<div class="separator">или</div>
|
||||
<div class="field field-disabled" style="margin-bottom:0">
|
||||
<label for="reg-invite">Код приглашения (недоступно без администратора)</label>
|
||||
<div class="input-wrap">
|
||||
<input id="reg-invite" type="text" placeholder="INVITE-XXXX-XXXX" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>подтверждение email</b></p>
|
||||
|
||||
<div class="confirm-card" style="margin-bottom: var(--space-6);">
|
||||
<div class="confirm-icon"><svg class="icon"><use href="#i-check-circle"/></svg></div>
|
||||
<h3>Почта подтверждена</h3>
|
||||
<p>Аккаунт <strong>a.ivanova@vidconf.dev</strong> активирован. Теперь
|
||||
доступно бронирование переговорных и вход в конференции.</p>
|
||||
<button class="btn btn-primary">Перейти в лобби <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</div>
|
||||
|
||||
<div class="confirm-card pending">
|
||||
<div class="confirm-icon"><svg class="icon"><use href="#i-clock"/></svg></div>
|
||||
<h3>Подтвердите почту</h3>
|
||||
<p>Мы отправили письмо со ссылкой на <span class="mail-chip"><svg class="icon" style="width:14px;height:14px"><use href="#i-mail"/></svg>m.kuznetsova@company.ru</span></p>
|
||||
<button class="btn btn-secondary">Отправить письмо повторно</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
403
design/mockups/dark/my-conferences.html
Normal file
403
design/mockups/dark/my-conferences.html
Normal file
@@ -0,0 +1,403 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-theme="shell-dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Мои конференции — тёмная тема, НА СОГЛАСОВАНИИ</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../../tokens.css">
|
||||
<style>
|
||||
/* =====================================================================
|
||||
* ТЁМНЫЙ ВАРИАНТ ОБОЛОЧКИ — ПРЕДЛОЖЕНИЕ, НЕ УТВЕРЖДЕНО.
|
||||
* Разметка и контент идентичны design/mockups/my-conferences.html 1:1,
|
||||
* меняется только цветовая схема — палитра переиспользует токены
|
||||
* комнаты конференции. Обоснование цветов — design/mockups/dark/README.md.
|
||||
* ===================================================================== */
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
--color-bg: #1E1E1E;
|
||||
--color-bg-alt: #242424;
|
||||
--color-surface: #2A2A2A;
|
||||
--color-surface-glass: rgba(51, 51, 51, .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, .14);
|
||||
--color-success-dot: #7FDDA8;
|
||||
|
||||
--color-danger: #EB93A1;
|
||||
--color-danger-bg: rgba(235, 147, 161, .14);
|
||||
--color-danger-dot: #EB93A1;
|
||||
--color-danger-solid: #B85468;
|
||||
--color-danger-solid-hover: #B9495F;
|
||||
|
||||
--color-warning: #D6A83D;
|
||||
--color-warning-bg: rgba(214, 168, 61, .16);
|
||||
--color-warning-dot: #D6A83D;
|
||||
|
||||
--color-focus-ring: #D6A83D;
|
||||
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
|
||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, .4);
|
||||
--shadow-lg: 0 12px 32px rgba(0, 0, 0, .5);
|
||||
--shadow-glass: 0 8px 24px rgba(0, 0, 0, .45);
|
||||
}
|
||||
|
||||
.theme-toggle { display: inline-flex; gap: 2px; background: var(--color-bg-alt); padding: 4px; border-radius: var(--radius-full); border: 1px solid var(--color-border); }
|
||||
.theme-toggle-btn { width: 32px; height: 32px; border-radius: 50%; border: none; background: transparent; color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; }
|
||||
.theme-toggle-btn .icon { width: 16px; height: 16px; }
|
||||
.theme-toggle-btn:hover { color: var(--color-ink-900); }
|
||||
.theme-toggle-btn.is-active { background: var(--color-surface); color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
|
||||
html { min-width: 1280px; }
|
||||
|
||||
.topbar {
|
||||
position: sticky; top: 0; z-index: 20;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: var(--space-4) var(--space-8);
|
||||
background: var(--color-surface);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
.topbar-right { display: flex; align-items: center; gap: var(--space-5); }
|
||||
.nav-link { font: var(--text-body); font-weight: 600; color: var(--color-ink-500); text-decoration: none; }
|
||||
.nav-link.is-active { color: var(--color-ink-700); }
|
||||
.avatar-btn { display: flex; align-items: center; gap: 8px; background: var(--color-bg-alt); border: 1px solid var(--color-border); border-radius: var(--radius-full); padding: 6px 14px 6px 6px; }
|
||||
.avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--color-ink-700); color: var(--color-accent-text); display:flex; align-items:center; justify-content:center; font: var(--text-caption); text-transform: none; letter-spacing: 0; }
|
||||
.avatar-btn .user-name { font: var(--text-body); font-weight: 600; color: var(--color-ink-900); }
|
||||
|
||||
main { padding: var(--space-8); max-width: 1280px; margin: 0 auto; }
|
||||
|
||||
.page-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: var(--space-6); }
|
||||
.page-head h1 { font: var(--text-display-lg); font-family: var(--font-display); color: var(--color-ink-700); margin: 0 0 6px; }
|
||||
.page-head p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0; }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; border: none; cursor: pointer; font-family: var(--font-body); white-space: nowrap; transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary { background: var(--color-accent); color: var(--color-accent-text); font: var(--text-body); font-weight: 700; padding: 11px 22px; border-radius: var(--radius-full); }
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-primary:active { background: var(--color-accent-active); }
|
||||
.btn-secondary { background: transparent; color: var(--color-ink-700); border: 1.5px solid var(--color-border-pill); font: var(--text-body); font-weight: 600; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); }
|
||||
:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
|
||||
|
||||
.filters { display: flex; gap: 8px; margin-bottom: var(--space-6); }
|
||||
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 9px 16px; border-radius: var(--radius-full); border: 1.5px solid var(--color-border); background: var(--color-surface); font: var(--text-body); font-weight: 600; color: var(--color-ink-500); }
|
||||
.chip.is-active { border-color: var(--color-ink-700); color: var(--color-ink-700); background: var(--color-bg-alt); }
|
||||
|
||||
.conf-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-5); }
|
||||
|
||||
.conf-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-4); transition: box-shadow var(--transition-base), border-color var(--transition-base); }
|
||||
.conf-card:hover { box-shadow: var(--shadow-md); border-color: var(--color-border-strong); }
|
||||
.conf-card.is-ended { opacity: .85; }
|
||||
|
||||
.conf-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
|
||||
.conf-title-wrap h3 { margin: 0 0 4px; font: var(--text-h3); color: var(--color-ink-900); display: flex; align-items: center; gap: 6px; }
|
||||
.conf-title-wrap p { margin: 0; font: var(--text-body); color: var(--color-ink-500); }
|
||||
|
||||
.conf-badge { display: inline-flex; align-items: center; gap: 5px; padding: 4px 12px; border-radius: var(--radius-full); font: var(--text-caption); white-space: nowrap; }
|
||||
.conf-badge.pinned { background: var(--color-bg-alt); color: var(--color-ink-700); border: 1px solid var(--color-border-strong); }
|
||||
.conf-badge.scheduled { background: var(--color-warning-bg); color: var(--color-warning); }
|
||||
.conf-badge.ended { background: var(--color-bg-alt); color: var(--color-ink-500); }
|
||||
|
||||
.conf-meta-row { display: flex; align-items: center; gap: var(--space-4); font: var(--text-body); color: var(--color-ink-500); }
|
||||
.conf-meta-row .meta-item { display: flex; align-items: center; gap: 6px; }
|
||||
|
||||
.pills-row { display: flex; gap: var(--space-3); }
|
||||
.pill-group { flex: 1; min-width: 0; }
|
||||
.pill-label { display: block; font: var(--text-caption); color: var(--color-ink-400); margin-bottom: 4px; }
|
||||
.code-pill { display: flex; align-items: center; gap: 6px; background: var(--color-bg-alt); border: 1px solid var(--color-border); border-radius: var(--radius-full); padding: 6px 6px 6px 14px; }
|
||||
.pill-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--text-mono-sm); color: var(--color-ink-700); }
|
||||
.copy-btn { position: relative; width: 28px; height: 28px; flex-shrink: 0; border-radius: 50%; border: none; background: var(--color-surface); color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; transition: color var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.copy-btn:hover { color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
.copy-btn .icon-check { display: none; color: var(--color-success); }
|
||||
.copy-btn.is-copied .icon-copy { display: none; }
|
||||
.copy-btn.is-copied .icon-check { display: block; }
|
||||
.copy-toast {
|
||||
position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
|
||||
background: #333333; color: var(--color-ink-900); font: var(--text-caption); text-transform: none; letter-spacing: normal;
|
||||
padding: 4px 10px; border-radius: var(--radius-sm); white-space: nowrap;
|
||||
opacity: 0; pointer-events: none; transition: opacity var(--transition-fast);
|
||||
}
|
||||
.copy-btn.is-copied .copy-toast { opacity: 1; }
|
||||
|
||||
.conf-card-footer { display: flex; gap: var(--space-3); margin-top: auto; }
|
||||
.conf-card-footer .btn { flex: 1; justify-content: center; }
|
||||
.icon-btn { width: 40px; height: 40px; flex-shrink: 0; border-radius: 50%; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; }
|
||||
.icon-btn:hover { border-color: var(--color-border-strong); color: var(--color-ink-900); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-repeat" viewBox="0 0 24 24"><path d="m17 2 4 4-4 4"/><path d="M3 11v-1a4 4 0 0 1 4-4h14"/><path d="m7 22-4-4 4-4"/><path d="M21 13v1a4 4 0 0 1-4 4H3"/></symbol>
|
||||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
||||
<symbol id="i-check-circle" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-users" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>
|
||||
<symbol id="i-copy" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></symbol>
|
||||
<symbol id="i-check" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></symbol>
|
||||
<symbol id="i-play" viewBox="0 0 24 24"><polygon points="6 3 20 12 6 21 6 3"/></symbol>
|
||||
<symbol id="i-pencil" viewBox="0 0 24 24"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></symbol>
|
||||
<symbol id="i-file-text" viewBox="0 0 24 24"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="16" y2="17"/></symbol>
|
||||
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></symbol>
|
||||
<symbol id="i-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
<nav class="topbar-right">
|
||||
<a href="lobby.html" class="nav-link">Лобби</a>
|
||||
<a href="calendar.html" class="nav-link">Календарь</a>
|
||||
<a href="my-conferences.html" class="nav-link is-active">Мои конференции</a>
|
||||
<a href="admin.html" class="nav-link">Админка</a>
|
||||
<div class="theme-toggle" role="group" aria-label="Переключить тему оформления">
|
||||
<button class="theme-toggle-btn" type="button" aria-pressed="false" aria-label="Светлая тема"><svg class="icon"><use href="#i-sun"/></svg></button>
|
||||
<button class="theme-toggle-btn is-active" type="button" aria-pressed="true" aria-label="Тёмная тема"><svg class="icon"><use href="#i-moon"/></svg></button>
|
||||
</div>
|
||||
<button class="avatar-btn"><span class="avatar">АИ</span><span class="user-name">Анна Иванова</span></button>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>Мои конференции</h1>
|
||||
<p>5 конференций · 3 закреплённые с повторением</p>
|
||||
</div>
|
||||
<a href="calendar.html" class="btn btn-primary">Запланировать новую</a>
|
||||
</div>
|
||||
|
||||
<div class="filters">
|
||||
<button class="chip is-active">Все</button>
|
||||
<button class="chip"><svg class="icon" style="width:14px;height:14px"><use href="#i-repeat"/></svg>Закреплённые</button>
|
||||
<button class="chip"><svg class="icon" style="width:14px;height:14px"><use href="#i-clock"/></svg>Предстоящие</button>
|
||||
<button class="chip">Завершённые</button>
|
||||
</div>
|
||||
|
||||
<section class="conf-grid">
|
||||
|
||||
<!-- Закреплена, еженедельно -->
|
||||
<article class="conf-card">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3>Ревью спринта</h3>
|
||||
<p>По вторникам и четвергам, 11:00–11:45</p>
|
||||
</div>
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:12px;height:12px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-clock"/></svg>Ближайшее: вт, 22 июля, 11:00</span>
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>8 участников</span>
|
||||
</div>
|
||||
<div class="pills-row">
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Ссылка</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">vidconf.ru/j/sprint-review</span>
|
||||
<button class="copy-btn" data-copy="https://vidconf.ru/j/sprint-review" aria-label="Скопировать ссылку">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Номер</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">8842 104</span>
|
||||
<button class="copy-btn" data-copy="8842 104" aria-label="Скопировать номер">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<a href="../room.html" class="btn btn-primary"><svg class="icon" style="width:16px;height:16px"><use href="#i-play"/></svg>Войти</a>
|
||||
<button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:17px;height:17px"><use href="#i-pencil"/></svg></button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Закреплена, ежемесячно, закрытая паролем -->
|
||||
<article class="conf-card">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3><svg class="icon" style="width:15px;height:15px;flex-shrink:0"><use href="#i-lock"/></svg>Синк по релизу 2.4</h3>
|
||||
<p>Раз в месяц, 15-го числа, 14:00–15:00</p>
|
||||
</div>
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:12px;height:12px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-clock"/></svg>Ближайшее: 15 августа, 14:00</span>
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>4 участника</span>
|
||||
</div>
|
||||
<div class="pills-row">
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Ссылка</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">vidconf.ru/j/release-sync</span>
|
||||
<button class="copy-btn" data-copy="https://vidconf.ru/j/release-sync" aria-label="Скопировать ссылку">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Номер</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">5217 933</span>
|
||||
<button class="copy-btn" data-copy="5217 933" aria-label="Скопировать номер">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<a href="join.html" class="btn btn-primary"><svg class="icon" style="width:16px;height:16px"><use href="#i-lock"/></svg>Войти по паролю</a>
|
||||
<button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:17px;height:17px"><use href="#i-pencil"/></svg></button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Предстоящая, разовая -->
|
||||
<article class="conf-card">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3>1:1 с руководителем</h3>
|
||||
<p>Разовая · 21 июля, 15:00–15:30</p>
|
||||
</div>
|
||||
<span class="conf-badge scheduled"><svg class="icon" style="width:12px;height:12px"><use href="#i-clock"/></svg>Предстоящая</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>2 участника</span>
|
||||
</div>
|
||||
<div class="pills-row">
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Ссылка</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">vidconf.ru/j/one-on-one</span>
|
||||
<button class="copy-btn" data-copy="https://vidconf.ru/j/one-on-one" aria-label="Скопировать ссылку">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Номер</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">2094 471</span>
|
||||
<button class="copy-btn" data-copy="2094 471" aria-label="Скопировать номер">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<button class="btn btn-secondary" style="flex:1" disabled><svg class="icon" style="width:16px;height:16px"><use href="#i-clock"/></svg>Начнётся через 3 дня</button>
|
||||
<button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:17px;height:17px"><use href="#i-pencil"/></svg></button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Завершена (незакреплённая — повторный вход недоступен, только саммари) -->
|
||||
<article class="conf-card is-ended">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3>Итоги квартала</h3>
|
||||
<p>Разовая · 29 июня, 12:00–13:00</p>
|
||||
</div>
|
||||
<span class="conf-badge ended"><svg class="icon" style="width:12px;height:12px"><use href="#i-check-circle"/></svg>Завершена</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>14 участников</span>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<a href="../email-summary.html" class="btn btn-secondary" style="flex:1"><svg class="icon" style="width:16px;height:16px"><use href="#i-file-text"/></svg>Открыть саммари</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Закреплена, каждые N дней -->
|
||||
<article class="conf-card">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3>Ежеквартальный отчёт</h3>
|
||||
<p>Каждые 90 дней, 10:00–11:00</p>
|
||||
</div>
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:12px;height:12px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-clock"/></svg>Ближайшее: 3 октября, 10:00</span>
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>22 участника</span>
|
||||
</div>
|
||||
<div class="pills-row">
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Ссылка</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">vidconf.ru/j/q-report</span>
|
||||
<button class="copy-btn" data-copy="https://vidconf.ru/j/q-report" aria-label="Скопировать ссылку">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Номер</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">6630 812</span>
|
||||
<button class="copy-btn" data-copy="6630 812" aria-label="Скопировать номер">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<button class="btn btn-secondary" style="flex:1" disabled><svg class="icon" style="width:16px;height:16px"><use href="#i-clock"/></svg>Начнётся 3 октября</button>
|
||||
<button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:17px;height:17px"><use href="#i-pencil"/></svg></button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Копирование ссылки/номера в буфер обмена + временная подсказка «Скопировано».
|
||||
document.querySelectorAll('.copy-btn').forEach((btn) => {
|
||||
const originalLabel = btn.getAttribute('aria-label');
|
||||
btn.addEventListener('click', () => {
|
||||
const text = btn.dataset.copy || '';
|
||||
if (navigator.clipboard) { navigator.clipboard.writeText(text).catch(() => {}); }
|
||||
btn.classList.add('is-copied');
|
||||
btn.setAttribute('aria-label', 'Скопировано');
|
||||
setTimeout(() => {
|
||||
btn.classList.remove('is-copied');
|
||||
btn.setAttribute('aria-label', originalLabel);
|
||||
}, 1500);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
245
design/mockups/email-summary.html
Normal file
245
design/mockups/email-summary.html
Normal file
@@ -0,0 +1,245 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Саммари встречи — Спринт-ревью команды платформы</title>
|
||||
<!--[if mso]>
|
||||
<style type="text/css">
|
||||
table { border-collapse: collapse; }
|
||||
.fallback-font { font-family: Arial, sans-serif !important; }
|
||||
</style>
|
||||
<![endif]-->
|
||||
<style>
|
||||
/* Только @media — всё остальное продублировано инлайн для совместимости
|
||||
с почтовыми клиентами (Outlook/Gmail игнорируют <style> в <head>). */
|
||||
@media (max-width: 640px) {
|
||||
.container { width: 100% !important; }
|
||||
.stack { display: block !important; width: 100% !important; }
|
||||
.px-32 { padding-left: 20px !important; padding-right: 20px !important; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="margin:0; padding:0; background-color:#F1F1F1; font-family:Helvetica, Arial, sans-serif;">
|
||||
<!-- Preheader (скрытый текст предпросмотра письма) -->
|
||||
<div style="display:none; max-height:0; overflow:hidden; opacity:0;">
|
||||
Саммари встречи «Спринт-ревью команды платформы»: 3 решения, 2 открытых вопроса, запись доступна 30 дней.
|
||||
</div>
|
||||
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:#F1F1F1;">
|
||||
<tr><td align="center" style="padding: 32px 16px;">
|
||||
|
||||
<table role="presentation" class="container" width="600" cellpadding="0" cellspacing="0" border="0" style="width:600px; max-width:600px; background-color:#FFFFFF; border-radius:24px; overflow:hidden; border:1px solid #E1E3E9;">
|
||||
|
||||
<!-- ===================== ШАПКА ===================== -->
|
||||
<tr>
|
||||
<td class="px-32" style="padding: 32px 32px 24px 32px; background-color:#F7F7F8;">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; font-weight:bold; color:#3B4D95; letter-spacing:.04em;">
|
||||
<!-- Логотип «объектив» (design/logo.svg). SVG — только для HTML-макета:
|
||||
почтовые клиенты (Outlook/большинство Gmail) не рендерят инлайн-SVG.
|
||||
В продакшен-письме заменить растровым PNG (24×24, @2x/@3x для
|
||||
ретины, тот же рисунок, цвет #3B4D95) с атрибутами width/height. -->
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="display:inline-block; vertical-align:middle;"><tr><td style="vertical-align:middle; padding-right:6px;">
|
||||
<svg width="16" height="16" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg" style="display:block;">
|
||||
<polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="#3B4D95"/>
|
||||
<circle cx="16" cy="16" r="13" stroke="#3B4D95" stroke-width="2.6" stroke-dasharray="12 6"/>
|
||||
</svg>
|
||||
</td></tr></table><span style="vertical-align:middle;">VIDCONF</span>
|
||||
</td>
|
||||
<td align="right" style="font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#535F94;">
|
||||
Саммари сформировано AI
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p style="margin: 20px 0 6px; font-family:Helvetica, Arial, sans-serif; font-size:12px; font-weight:bold; letter-spacing:.06em; text-transform:uppercase; color:#6976AC;">
|
||||
Саммари встречи
|
||||
</p>
|
||||
<h1 style="margin:0 0 12px; font-family:Helvetica, Arial, sans-serif; font-size:26px; line-height:1.25; font-weight:bold; color:#2E3454;">
|
||||
Спринт-ревью команды платформы
|
||||
</h1>
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; color:#535F94; padding-right:18px;">
|
||||
📅 15 июля 2026, вт
|
||||
</td>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; color:#535F94; padding-right:18px;">
|
||||
⌛ 45 минут
|
||||
</td>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; color:#535F94;">
|
||||
📍 Переговорная №42
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- ===================== УЧАСТНИКИ ===================== -->
|
||||
<tr>
|
||||
<td class="px-32" style="padding: 24px 32px 8px 32px;">
|
||||
<p style="margin:0 0 12px; font-family:Helvetica, Arial, sans-serif; font-size:12px; font-weight:bold; letter-spacing:.06em; text-transform:uppercase; color:#A6AECB;">
|
||||
Участники (8)
|
||||
</p>
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td style="padding-right:6px;"><table cellpadding="0" cellspacing="0" border="0"><tr><td width="30" height="30" align="center" valign="middle" bgcolor="#3B4D95" style="border-radius:15px; font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#FFFFFF; font-weight:bold;">ИС</td></tr></table></td>
|
||||
<td style="padding-right:6px;"><table cellpadding="0" cellspacing="0" border="0"><tr><td width="30" height="30" align="center" valign="middle" bgcolor="#535F94" style="border-radius:15px; font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#FFFFFF; font-weight:bold;">МК</td></tr></table></td>
|
||||
<td style="padding-right:6px;"><table cellpadding="0" cellspacing="0" border="0"><tr><td width="30" height="30" align="center" valign="middle" bgcolor="#535F94" style="border-radius:15px; font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#FFFFFF; font-weight:bold;">ВС</td></tr></table></td>
|
||||
<td style="padding-right:6px;"><table cellpadding="0" cellspacing="0" border="0"><tr><td width="30" height="30" align="center" valign="middle" bgcolor="#535F94" style="border-radius:15px; font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#FFFFFF; font-weight:bold;">ОП</td></tr></table></td>
|
||||
<td><table cellpadding="0" cellspacing="0" border="0"><tr><td width="30" height="30" align="center" valign="middle" bgcolor="#F7F7F8" style="border-radius:15px; font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#535F94; font-weight:bold; border:1px solid #E1E3E9;">+4</td></tr></table></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr><td class="px-32" style="padding: 16px 32px;"><hr style="border:none; border-top:1px solid #E1E3E9; margin:0;"></td></tr>
|
||||
|
||||
<!-- ===================== ТЕЗИСЫ ===================== -->
|
||||
<tr>
|
||||
<td class="px-32" style="padding: 8px 32px 24px 32px;">
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin-bottom:12px;">
|
||||
<tr>
|
||||
<td width="24" valign="middle">📝</td>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:16px; font-weight:bold; color:#2E3454; padding-left:6px;">Тезисы</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; line-height:1.6; color:#2E3454; padding: 6px 0;">
|
||||
• Бэкенд-команда завершила миграцию бронирования на EXCLUDE-констрейнт PostgreSQL, конфликтов брони в проде не зафиксировано за 2 недели.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; line-height:1.6; color:#2E3454; padding: 6px 0;">
|
||||
• Транскрайбер на faster-whisper (CPU) укладывается в SLA 10 минут для встреч до часа.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; line-height:1.6; color:#2E3454; padding: 6px 0;">
|
||||
• Дизайн-система для комнаты конференции утверждена, фронтенд начинает интеграцию LiveKit на следующей неделе.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- ===================== РЕШЕНИЯ ===================== -->
|
||||
<tr>
|
||||
<td class="px-32" style="padding: 8px 32px 24px 32px; background-color:#E4F7ED;">
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin-bottom:12px; padding-top:16px;">
|
||||
<tr>
|
||||
<td width="24" valign="middle" style="color:#0A7A4C;">✅</td>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:16px; font-weight:bold; color:#0A7A4C; padding-left:6px;">Принятые решения</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; line-height:1.6; color:#2E3454; padding: 6px 0;">
|
||||
1. Перейти на Qwen2.5-3B Q4_K_M как модель по умолчанию для саммаризации (ответственный: Виктор Седых, до 22.07).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; line-height:1.6; color:#2E3454; padding: 6px 0;">
|
||||
2. Хранить пароли комнат только в виде argon2-хэшей, ротацию делать через админку (ответственный: Ольга Панина).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; line-height:1.6; color:#2E3454; padding: 6px 0;">
|
||||
3. Запись конференций хранить 30 дней, затем удалять по расписанию Celery beat.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- ===================== ОТКРЫТЫЕ ВОПРОСЫ ===================== -->
|
||||
<tr>
|
||||
<td class="px-32" style="padding: 24px 32px; background-color:#FBF0DC;">
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin-bottom:12px;">
|
||||
<tr>
|
||||
<td width="24" valign="middle" style="color:#7F560D;">❓</td>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:16px; font-weight:bold; color:#7F560D; padding-left:6px;">Открытые вопросы</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; line-height:1.6; color:#2E3454; padding: 6px 0;">
|
||||
• Кто согласует лимиты Celery worker concurrency для транскрайбера на проде — DevOps или бэкенд-лид?
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:14px; line-height:1.6; color:#2E3454; padding: 6px 0;">
|
||||
• Нужна ли поддержка GPU-инференса как отдельный плагин Transcriber уже в Фазе 3, или отложить до масштабирования?
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- ===================== ЦИФРЫ И ФАКТЫ ===================== -->
|
||||
<tr>
|
||||
<td class="px-32" style="padding: 24px 32px;">
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin-bottom:16px;">
|
||||
<tr>
|
||||
<td width="24" valign="middle">📊</td>
|
||||
<td style="font-family:Helvetica, Arial, sans-serif; font-size:16px; font-weight:bold; color:#2E3454; padding-left:6px;">Цифры и факты</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border:1px solid #E1E3E9; border-radius:12px;">
|
||||
<tr>
|
||||
<td width="33%" align="center" style="padding:18px 8px; border-right:1px solid #E1E3E9;">
|
||||
<div style="font-family:Helvetica, Arial, sans-serif; font-size:28px; font-weight:bold; color:#3B4D95;">45 мин</div>
|
||||
<div style="font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#535F94; margin-top:4px;">длительность</div>
|
||||
</td>
|
||||
<td width="33%" align="center" style="padding:18px 8px; border-right:1px solid #E1E3E9;">
|
||||
<div style="font-family:Helvetica, Arial, sans-serif; font-size:28px; font-weight:bold; color:#3B4D95;">3</div>
|
||||
<div style="font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#535F94; margin-top:4px;">решения</div>
|
||||
</td>
|
||||
<td width="34%" align="center" style="padding:18px 8px;">
|
||||
<div style="font-family:Helvetica, Arial, sans-serif; font-size:28px; font-weight:bold; color:#3B4D95;">8</div>
|
||||
<div style="font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#535F94; margin-top:4px;">участников</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- ===================== CTA ===================== -->
|
||||
<tr>
|
||||
<td class="px-32" align="center" style="padding: 8px 32px 32px 32px;">
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%">
|
||||
<tr>
|
||||
<!-- #D4F2E3 --color-accent (осветлено на 50% от #A9E4C6, фаза R1 итерация) -->
|
||||
<td align="center" bgcolor="#D4F2E3" style="border-radius:999px;">
|
||||
<!-- #2E3454 --color-accent-text -->
|
||||
<a href="#" style="display:block; padding:14px 28px; font-family:Helvetica, Arial, sans-serif; font-size:15px; font-weight:bold; color:#2E3454; text-decoration:none;">
|
||||
Смотреть полную расшифровку →
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- ===================== ФУТЕР ===================== -->
|
||||
<tr>
|
||||
<td class="px-32" style="padding: 20px 32px 32px 32px; background-color:#F7F7F8; border-top:1px solid #E1E3E9;">
|
||||
<p style="margin:0 0 8px; font-family:Helvetica, Arial, sans-serif; font-size:12px; line-height:1.6; color:#A6AECB;">
|
||||
Письмо сформировано автоматически по итогам конференции в VidConf (self-hosted). Запись и полная расшифровка доступны 30 дней.
|
||||
</p>
|
||||
<p style="margin:0; font-family:Helvetica, Arial, sans-serif; font-size:12px; color:#A6AECB;">
|
||||
<a href="#" style="color:#535F94; text-decoration:underline;">Настройки уведомлений</a>
|
||||
·
|
||||
<a href="#" style="color:#535F94; text-decoration:underline;">Отписаться от саммари</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
193
design/mockups/join.html
Normal file
193
design/mockups/join.html
Normal file
@@ -0,0 +1,193 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Подключение к конференции</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../tokens.css">
|
||||
<style>
|
||||
/*
|
||||
* Подключение к конференции (фаза R1, пивот) — три состояния одного flow:
|
||||
* (а) ввод ссылки/номера, (б) «представиться» для гостя (имя обязательно,
|
||||
* email факультативно — для саммари), (в) пароль закрытой конференции.
|
||||
* Вход по ссылке/номеру доступен любому, включая гостей без аккаунта —
|
||||
* поэтому экран не требует авторизации и не показывает брендовую
|
||||
* sales-панель auth.html, только компактный центрированный поток.
|
||||
*/
|
||||
|
||||
html { min-width: 1280px; }
|
||||
body { min-height: 100vh; display: flex; flex-direction: column; background: var(--color-bg); }
|
||||
|
||||
.topbar { display: flex; align-items: center; padding: var(--space-5) var(--space-8); }
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); text-decoration: none; }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
|
||||
main { flex: 1; display: flex; flex-direction: column; align-items: center; padding: var(--space-6) var(--space-8) var(--space-16); gap: var(--space-16); }
|
||||
|
||||
.screen-block { width: 100%; max-width: 440px; }
|
||||
.screen-label { font: var(--text-caption); color: var(--color-ink-400); margin: 0 0 var(--space-3); text-align: center; }
|
||||
.screen-label b { color: var(--color-ink-700); }
|
||||
|
||||
.flow-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-8); }
|
||||
.flow-icon { width: 52px; height: 52px; border-radius: var(--radius-full); background: var(--color-bg-alt); color: var(--color-ink-700); display: flex; align-items: center; justify-content: center; margin: 0 auto var(--space-5); }
|
||||
.flow-icon .icon { width: 24px; height: 24px; }
|
||||
.flow-card h1 { font: var(--text-h1); color: var(--color-ink-900); margin: 0 0 var(--space-2); text-align: center; }
|
||||
.flow-card .flow-sub { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0 0 var(--space-6); text-align: center; }
|
||||
|
||||
.field { margin-bottom: var(--space-5); }
|
||||
.field label { display: flex; align-items: center; gap: 6px; font: var(--text-body); font-weight: 600; color: var(--color-ink-900); margin-bottom: var(--space-2); }
|
||||
.field-optional { font-weight: 400; color: var(--color-ink-400); }
|
||||
.input-wrap { position: relative; }
|
||||
.input-wrap .icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--color-ink-400); }
|
||||
.input-wrap input {
|
||||
width: 100%; font: var(--text-body-lg); color: var(--color-ink-900);
|
||||
padding: 11px 14px 11px 42px; border-radius: var(--radius-md); border: 1px solid var(--color-border);
|
||||
background: var(--color-surface); outline: none;
|
||||
}
|
||||
.input-wrap input::placeholder { color: var(--color-ink-300); }
|
||||
.input-wrap input:hover { border-color: var(--color-border-strong); }
|
||||
.input-wrap input:focus { border-color: var(--color-focus-ring); box-shadow: 0 0 0 3px rgba(59,77,149,.12); }
|
||||
.input-wrap .toggle-eye { left: auto; right: 14px; background: none; border: none; padding: 0; cursor: pointer; }
|
||||
.field-hint { margin-top: var(--space-2); font: var(--text-body); color: var(--color-ink-500); }
|
||||
.field.has-error input { border-color: var(--color-danger); box-shadow: 0 0 0 3px rgba(199,54,79,.1); }
|
||||
.error-msg { display: flex; align-items: center; gap: 6px; margin-top: var(--space-2); font: var(--text-body); color: var(--color-danger); }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; border: none; cursor: pointer; font-family: var(--font-body); transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary { background: var(--color-accent); color: var(--color-accent-text); font: var(--text-body-lg); font-weight: 700; padding: 13px 24px; border-radius: var(--radius-full); }
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-primary:active { background: var(--color-accent-active); }
|
||||
.btn-primary[disabled] { background: rgba(166,174,203,.4); color: var(--color-surface); cursor: not-allowed; }
|
||||
.btn-secondary { background: transparent; color: var(--color-ink-700); border: 1.5px solid var(--color-border-pill); font: var(--text-body-lg); font-weight: 600; padding: 12px 24px; border-radius: var(--radius-full); }
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); }
|
||||
:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
|
||||
|
||||
.link-back { display: block; text-align: center; margin-top: var(--space-5); font: var(--text-body); font-weight: 600; color: var(--color-ink-500); text-decoration: none; }
|
||||
.link-back:hover { color: var(--color-ink-700); }
|
||||
|
||||
/* Плашка целевой конференции (состояния б/в) */
|
||||
.target-conf { display: flex; align-items: center; gap: 12px; background: var(--color-bg-alt); border-radius: var(--radius-lg); padding: var(--space-4); margin-bottom: var(--space-6); }
|
||||
.target-conf .icon-wrap { width: 40px; height: 40px; border-radius: 50%; background: var(--color-surface); border: 1px solid var(--color-border); color: var(--color-ink-700); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
|
||||
.target-conf strong { display: block; font: var(--text-body); color: var(--color-ink-900); }
|
||||
.target-conf span { font: var(--text-mono-sm); color: var(--color-ink-500); }
|
||||
|
||||
.divider { border: none; border-top: 1px solid var(--color-border); width: 100%; max-width: 720px; margin: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-link2" viewBox="0 0 24 24"><path d="M9 17H7A5 5 0 0 1 7 7h2"/><path d="M15 7h2a5 5 0 1 1 0 10h-2"/><line x1="8" y1="12" x2="16" y2="12"/></symbol>
|
||||
<symbol id="i-hash" viewBox="0 0 24 24"><line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/><line x1="10" y1="3" x2="8" y2="21"/><line x1="16" y1="3" x2="14" y2="21"/></symbol>
|
||||
<symbol id="i-user" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M6 21v-2a6 6 0 0 1 12 0v2"/></symbol>
|
||||
<symbol id="i-mail" viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 6 10 7 10-7"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-eye" viewBox="0 0 24 24"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></symbol>
|
||||
<symbol id="i-eye-off" viewBox="0 0 24 24"><path d="M3 3l18 18"/><path d="M10.58 10.58a2 2 0 0 0 2.83 2.83"/><path d="M9.88 5.09A9.77 9.77 0 0 1 12 5c6.5 0 10 7 10 7a13.16 13.16 0 0 1-3.06 4.06M6.1 6.1A13.16 13.16 0 0 0 2 12s3.5 7 10 7a9.77 9.77 0 0 0 4.9-1.3"/></symbol>
|
||||
<symbol id="i-arrow-right" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></symbol>
|
||||
<symbol id="i-alert" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></symbol>
|
||||
<symbol id="i-video" viewBox="0 0 24 24"><path d="M15 6H4a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-2.5l5 3.5V7l-5 3.5V8a2 2 0 0 0-2-2z"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="topbar">
|
||||
<a class="brand-mark" href="lobby.html"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</a>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
|
||||
<!-- ===================== (а) ВВОД ССЫЛКИ ИЛИ НОМЕРА ===================== -->
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>ввод ссылки или номера</b></p>
|
||||
<div class="flow-card">
|
||||
<div class="flow-icon" aria-hidden="true"><svg class="icon"><use href="#i-link2"/></svg></div>
|
||||
<h1>Подключиться к конференции</h1>
|
||||
<p class="flow-sub">Вставьте ссылку-приглашение или введите номер конференции</p>
|
||||
|
||||
<form>
|
||||
<div class="field">
|
||||
<label for="join-input">Ссылка или номер</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-hash"/></svg>
|
||||
<input id="join-input" type="text" placeholder="vidconf.ru/j/... или 8842 104" value="8842 104">
|
||||
</div>
|
||||
<p class="field-hint">Найдите номер или ссылку в приглашении организатора</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Продолжить <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</form>
|
||||
<a href="lobby.html" class="link-back">Назад в лобби</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<!-- ===================== (б) ПРЕДСТАВИТЬСЯ (ГОСТЬ) ===================== -->
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>представиться (гость)</b></p>
|
||||
<div class="flow-card">
|
||||
<div class="target-conf">
|
||||
<span class="icon-wrap" aria-hidden="true"><svg class="icon" style="width:18px;height:18px"><use href="#i-video"/></svg></span>
|
||||
<div><strong>Синк по релизу 2.4</strong><span>№ 8842 104</span></div>
|
||||
</div>
|
||||
|
||||
<div class="flow-icon" aria-hidden="true"><svg class="icon"><use href="#i-user"/></svg></div>
|
||||
<h1>Как вас зовут?</h1>
|
||||
<p class="flow-sub">У вас нет аккаунта VidConf — представьтесь, чтобы войти как гость</p>
|
||||
|
||||
<form>
|
||||
<div class="field">
|
||||
<label for="guest-name">Имя<span class="field-optional">· обязательно</span></label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-user"/></svg>
|
||||
<input id="guest-name" type="text" placeholder="Как к вам обращаться" value="Пётр Волков">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="guest-email">Email<span class="field-optional">· необязательно</span></label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-mail"/></svg>
|
||||
<input id="guest-email" type="email" placeholder="you@mail.ru">
|
||||
</div>
|
||||
<p class="field-hint">Укажите, если хотите получить саммари конференции на почту</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Войти в конференцию <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</form>
|
||||
<a href="join.html" class="link-back">Назад</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="divider">
|
||||
|
||||
<!-- ===================== (в) ПАРОЛЬ ЗАКРЫТОЙ КОНФЕРЕНЦИИ ===================== -->
|
||||
<section class="screen-block">
|
||||
<p class="screen-label">Экран: <b>пароль закрытой конференции</b> (с состоянием ошибки)</p>
|
||||
<div class="flow-card">
|
||||
<div class="target-conf">
|
||||
<span class="icon-wrap" aria-hidden="true"><svg class="icon" style="width:18px;height:18px"><use href="#i-lock"/></svg></span>
|
||||
<div><strong>Итоги квартала</strong><span>№ 4471 208 · закрытая</span></div>
|
||||
</div>
|
||||
|
||||
<div class="flow-icon" aria-hidden="true"><svg class="icon"><use href="#i-lock"/></svg></div>
|
||||
<h1>Введите пароль</h1>
|
||||
<p class="flow-sub">Эта конференция закрыта — доступ только по паролю от организатора</p>
|
||||
|
||||
<form>
|
||||
<div class="field has-error">
|
||||
<label for="join-pass">Пароль конференции</label>
|
||||
<div class="input-wrap">
|
||||
<svg class="icon"><use href="#i-lock"/></svg>
|
||||
<input id="join-pass" type="password" placeholder="••••••••" value="wrongpass">
|
||||
<button type="button" class="toggle-eye" aria-label="Показать пароль">
|
||||
<svg class="icon"><use href="#i-eye"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<p class="error-msg"><svg class="icon" style="width:16px;height:16px"><use href="#i-alert"/></svg> Неверный пароль, попробуйте ещё раз</p>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Войти <svg class="icon"><use href="#i-arrow-right"/></svg></button>
|
||||
</form>
|
||||
<a href="join.html" class="link-back">Назад</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
414
design/mockups/lobby.html
Normal file
414
design/mockups/lobby.html
Normal file
@@ -0,0 +1,414 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Лобби (хаб действий)</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../tokens.css">
|
||||
<style>
|
||||
/*
|
||||
* Лобби — «хаб действий» (фаза R1, пивот). Заменяет список комнат:
|
||||
* предустановленных комнат больше нет, конференции создаются динамически.
|
||||
* По мотивам alternative_design/lobby.html, с правками фазы R1:
|
||||
* - 4 плитки СТРОГО одинакового размера (фиксированная высота, не min-height,
|
||||
* чтобы сетка была симметричной вне зависимости от длины текста внутри);
|
||||
* - симметричная сетка 2×2 без grid-template-areas (порядок в DOM = порядок
|
||||
* чтения = порядок задачи: Создать → Календарь → Подключиться → Мои);
|
||||
* - плитки крупнее референсного эскиза (высота 340px против ~220px в alt);
|
||||
* - медальон VidConf на пересечении рядов/колонок (без магических % как
|
||||
* в alt-версии; точную формулу положения см. в правке 2-й волны ниже —
|
||||
* после неё центр уже не буквально 50%/50%, а зеркально-симметричная
|
||||
* точка равного перекрытия всех 4 карточек).
|
||||
* Токены — только новые имена (--color-accent*), см. tokens.css §1.1/1.3.
|
||||
*
|
||||
* Итерация правок (2026-07-16, гейт утверждения, 1-я волна): плитки
|
||||
* расширены в 1.5 раза (тайл 544px → 816px, контейнер 1120px → 1664px,
|
||||
* gap не менялся — ширина реально выросла, а не растянулась через gap);
|
||||
* типографика внутри плиток укрупнена пропорционально (см.
|
||||
* .action-icon/.action-title/.action-object/.action-note/.hub-logo ниже).
|
||||
* Высота ряда (340px) сохранена без изменений — просили шире, не крупнее
|
||||
* по высоте.
|
||||
*
|
||||
* Итерация правок (2026-07-16, гейт утверждения, 2-я волна): медальон
|
||||
* заменён на знак-объектив (design/logo.svg, см. DESIGN_SYSTEM.md §1.4) и
|
||||
* теперь ЛЕЖИТ ПОВЕРХ равных частей видимых углов всех 4 карточек (было —
|
||||
* просто сидел в промежутке сетки на пересечении 50%/50%). Точная
|
||||
* геометрия и обоснование смещения центра медальона — в комментарии перед
|
||||
* `.hub-logo` и в DESIGN_SYSTEM.md §4.12.
|
||||
*
|
||||
* Итерация правок (2026-07-16, гейт утверждения, 3-я волна): плитки сужены
|
||||
* на 15% (тайл 816px → 694px, контейнер 1664px → 1420px); высота (340px)
|
||||
* и gap (32px) не менялись, типографика не менялась. Перекрытие медальона
|
||||
* зависит только от gap/margin-top (не от ширины тайла) — геометрия и
|
||||
* величина перекрытия (29.2px) остаются теми же, см. `.hub-logo` ниже;
|
||||
* пересчёт подтверждён headless-рендером на 1280/1440/1728px.
|
||||
*/
|
||||
|
||||
html { height: 100%; min-width: 1280px; }
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background:
|
||||
radial-gradient(1100px 520px at 10% -10%, rgba(59, 77, 149, 0.06), transparent 60%),
|
||||
radial-gradient(900px 480px at 105% 110%, rgba(212, 242, 227, 0.28), transparent 55%),
|
||||
var(--color-bg);
|
||||
}
|
||||
|
||||
/* ---------- Верхняя панель ---------- */
|
||||
.topbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: var(--space-5) var(--space-8);
|
||||
}
|
||||
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
|
||||
.topbar-right { display: flex; align-items: center; gap: var(--space-4); }
|
||||
|
||||
.burger {
|
||||
width: 44px; height: 44px;
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--color-ink-700);
|
||||
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
.burger:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-sm); }
|
||||
.burger[aria-expanded="true"] { border-color: var(--color-ink-700); }
|
||||
|
||||
.menu-wrap { position: relative; }
|
||||
.menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 10px);
|
||||
right: 0;
|
||||
min-width: 236px;
|
||||
padding: var(--space-2);
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-lg);
|
||||
display: none;
|
||||
z-index: 30;
|
||||
}
|
||||
.menu.is-open { display: block; }
|
||||
.menu a {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 10px 14px;
|
||||
border-radius: var(--radius-sm);
|
||||
font: var(--text-body-lg); font-weight: 600;
|
||||
color: var(--color-ink-900);
|
||||
text-decoration: none;
|
||||
}
|
||||
.menu a:hover { background: var(--color-bg-alt); color: var(--color-ink-700); }
|
||||
.menu a .icon { color: var(--color-ink-400); }
|
||||
.menu-divider { height: 1px; background: var(--color-border); margin: var(--space-2) 6px; }
|
||||
.menu a.danger { color: var(--color-danger); }
|
||||
.menu a.danger .icon { color: var(--color-danger); }
|
||||
|
||||
.user-pill {
|
||||
display: inline-flex; align-items: center; gap: 10px;
|
||||
padding: 6px 16px 6px 6px;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-full);
|
||||
font: var(--text-body); font-weight: 600; color: var(--color-ink-900);
|
||||
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
.user-pill:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-sm); }
|
||||
.user-pill .avatar {
|
||||
width: 30px; height: 30px; border-radius: 50%;
|
||||
background: var(--color-ink-700); color: #fff;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font: var(--text-caption);
|
||||
}
|
||||
|
||||
/* ---------- Мозаика действий ---------- */
|
||||
main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: var(--space-6) var(--space-8) var(--space-12);
|
||||
}
|
||||
|
||||
.hub-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--space-8); width: 100%; }
|
||||
/* width:100% — обязателен: без явной ширины .hub-wrap как flex-item без
|
||||
flex-grow сжимается по контенту (max-content), и width: min(…, 100%)
|
||||
у .hub не может резолвиться от неопределённого контейнера (циклическая
|
||||
зависимость) — контейнер сетки фактически игнорировал заданный кап.
|
||||
С width:100% контейнер .hub-wrap получает определённую ширину от
|
||||
<main>, и .hub реально расширяется до заданного max-width. */
|
||||
.hub-intro { text-align: center; max-width: 560px; }
|
||||
.hub-intro .eyebrow { font: var(--text-caption); color: var(--color-ink-400); margin: 0 0 var(--space-2); }
|
||||
.hub-intro h1 { font: var(--text-display-lg); font-family: var(--font-display); color: var(--color-ink-700); margin: 0; }
|
||||
|
||||
.hub {
|
||||
position: relative;
|
||||
width: min(1420px, 100%); /* тайл 694px × 2 + gap 32px. Правка гейта
|
||||
(2026-07-16, 3-я итерация): тайл ×0.85 от предыдущих 816px (816×0.85=
|
||||
693.6≈694px, контейнер 1664px→1420px); высота (340px) и gap (32px) не
|
||||
менялись — сужение только по горизонтали. */
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-rows: repeat(2, 340px); /* фиксированная высота — гарантирует
|
||||
строгую симметрию сетки 2×2 независимо от длины текста в плитках */
|
||||
gap: var(--space-8);
|
||||
}
|
||||
|
||||
/* Карточка-действие. Медальон с иконкой «сидит» на верхней кромке. */
|
||||
.action {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
gap: var(--space-3);
|
||||
padding: var(--space-10) var(--space-12) var(--space-8);
|
||||
margin-top: 34px; /* место под выступающий медальон (68px / 2) */
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-3xl);
|
||||
text-decoration: none;
|
||||
color: var(--color-ink-900);
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition:
|
||||
transform var(--transition-base),
|
||||
box-shadow var(--transition-base),
|
||||
border-color var(--transition-base);
|
||||
}
|
||||
.action:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
border-color: var(--color-border-strong);
|
||||
}
|
||||
.action:active { transform: translateY(-1px); }
|
||||
|
||||
.action-icon {
|
||||
position: absolute;
|
||||
top: -34px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 68px; height: 68px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-surface);
|
||||
border: var(--border-thick) solid var(--color-ink-700);
|
||||
color: var(--color-ink-700);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
.action-icon .icon { width: 30px; height: 30px; }
|
||||
|
||||
/* Типографика плиток укрупнена пропорционально расширению тайла (итерация
|
||||
правок гейта, 2026-07-16): заголовок 34px → 40px, подпись-объект
|
||||
18px → 21px, примечание 16px → 17px. Токены шкалы (--text-display-lg
|
||||
и т.д.) не подходят напрямую — берём кастомные размеры того же
|
||||
начертания/семейства для гармоничного шага. */
|
||||
.action-title {
|
||||
margin: 0;
|
||||
font: 600 40px/1.2 var(--font-display);
|
||||
letter-spacing: 0.01em;
|
||||
color: var(--color-ink-700);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.action-object { margin: 0; font: 600 21px/1.35 var(--font-body); color: var(--color-ink-900); }
|
||||
.action-note { margin: 0; font: 400 17px/1.5 var(--font-body); color: var(--color-ink-500); }
|
||||
|
||||
/* Главное действие — CTA дизайн-системы (пастельная мята) */
|
||||
.action--create {
|
||||
background: var(--color-accent);
|
||||
border-color: transparent;
|
||||
}
|
||||
.action--create:hover { background: var(--color-accent-hover); border-color: transparent; }
|
||||
.action--create:active { background: var(--color-accent-active); }
|
||||
.action--create .action-title { font: 700 54px/1.1 var(--font-display); }
|
||||
.action--create .action-title,
|
||||
.action--create .action-object { color: var(--color-accent-text); }
|
||||
.action--create .action-note { color: var(--color-ink-700); }
|
||||
.action--create .action-icon {
|
||||
background: var(--color-accent);
|
||||
border-color: var(--color-accent-text);
|
||||
color: var(--color-accent-text);
|
||||
}
|
||||
|
||||
/* ---------- Медальон VidConf в центре мозаики ---------- */
|
||||
/* Правка гейта (2026-07-16, вторая итерация): медальон должен ЛЕЖАТЬ ПОВЕРХ
|
||||
видимых углов всех 4 карточек на одинаковую величину, а не просто сидеть
|
||||
в промежутке сетки. Геометрия (числа фиксированные, не проценты — высота
|
||||
.hub всегда 2×340px + gap 32px = 712px, независимо от ширины вьюпорта):
|
||||
• по вертикали видимый низ карточек ряда 1 — на y=340px от верха .hub
|
||||
(340px трек), видимый верх карточек ряда 2 — на y=406px (грид-гап 32px
|
||||
+ margin-top 34px карточки под собственный action-icon). Равноудалённая
|
||||
от обеих точка — y=373px (33px до каждой), а не геометрический центр
|
||||
сетки 356px (712/2) — из-за несимметричного резерва под action-icon.
|
||||
• по горизонтали — строго центр колонок (gap 32px, по 16px до каждой
|
||||
карточки), там асимметрии нет.
|
||||
Медальон центрирован в (50%, 373px). Такое позиционирование даёт ТОЧНО
|
||||
одинаковое перекрытие всех 4 углов по построению (зеркальная симметрия
|
||||
по обеим осям), проверено headless-рендером: offset между углами — 0px
|
||||
(см. design/tools/ — рендер-проверка выполнялась вручную скриптом, не
|
||||
хранится в репозитории).
|
||||
Диаметр 156px (было 132px) при радиусе скругления карточек 32px
|
||||
(--radius-3xl) даёт перекрытие видимой (закруглённой) части каждой
|
||||
карточки ≈29px по диагонали — в середине требуемого диапазона 20–35px. */
|
||||
.hub-logo {
|
||||
position: absolute;
|
||||
top: 373px; left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 156px; height: 156px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-surface);
|
||||
border: var(--border-thick) solid var(--color-ink-700);
|
||||
box-shadow: var(--shadow-lg);
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
gap: 6px;
|
||||
z-index: 20;
|
||||
pointer-events: none;
|
||||
}
|
||||
.hub-logo .logo-mark {
|
||||
width: 56px; height: 56px;
|
||||
color: var(--color-ink-700);
|
||||
}
|
||||
.hub-logo .logo-word {
|
||||
font: 600 16px/1 var(--font-display);
|
||||
color: var(--color-ink-700);
|
||||
}
|
||||
|
||||
/* ---------- Появление ---------- */
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.action, .hub-logo {
|
||||
animation: rise 480ms cubic-bezier(0.22, 0.9, 0.3, 1) backwards;
|
||||
}
|
||||
.action--create { animation-delay: 60ms; }
|
||||
.action--calendar { animation-delay: 140ms; }
|
||||
.action--join { animation-delay: 220ms; }
|
||||
.action--mine { animation-delay: 300ms; }
|
||||
.hub-logo { animation-delay: 420ms; }
|
||||
@keyframes rise {
|
||||
from { opacity: 0; transform: translateY(14px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
.hub-logo { animation-name: rise-logo; }
|
||||
@keyframes rise-logo {
|
||||
from { opacity: 0; transform: translate(-50%, calc(-50% + 14px)); }
|
||||
to { opacity: 1; transform: translate(-50%, -50%); }
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none" aria-hidden="true">
|
||||
<symbol id="i-video" viewBox="0 0 24 24"><path d="M15 6H4a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-2.5l5 3.5V7l-5 3.5V8a2 2 0 0 0-2-2z"/></symbol>
|
||||
<symbol id="i-calendar" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></symbol>
|
||||
<symbol id="i-link2" viewBox="0 0 24 24"><path d="M9 17H7A5 5 0 0 1 7 7h2"/><path d="M15 7h2a5 5 0 1 1 0 10h-2"/><line x1="8" y1="12" x2="16" y2="12"/></symbol>
|
||||
<symbol id="i-user" viewBox="0 0 24 24"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></symbol>
|
||||
<symbol id="i-download" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></symbol>
|
||||
<symbol id="i-info" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></symbol>
|
||||
<symbol id="i-layout-dashboard" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="9" rx="1"/><rect x="14" y="3" width="7" height="5" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/><rect x="3" y="16" width="7" height="5" rx="1"/></symbol>
|
||||
<symbol id="i-logout" viewBox="0 0 24 24"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
|
||||
<div class="topbar-right">
|
||||
<button class="user-pill">
|
||||
<span class="avatar" aria-hidden="true">ИИ</span>
|
||||
Иванов Иван
|
||||
</button>
|
||||
<div class="menu-wrap">
|
||||
<button class="burger" id="burger" aria-expanded="false" aria-controls="main-menu" aria-label="Открыть меню">
|
||||
<svg class="icon" viewBox="0 0 24 24"><line x1="4" y1="7" x2="20" y2="7"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="17" x2="20" y2="17"/></svg>
|
||||
</button>
|
||||
<nav class="menu" id="main-menu" aria-label="Основное меню">
|
||||
<a href="#"><svg class="icon"><use href="#i-user"/></svg> Профиль</a>
|
||||
<a href="admin.html"><svg class="icon"><use href="#i-layout-dashboard"/></svg> Админка</a>
|
||||
<a href="#"><svg class="icon"><use href="#i-download"/></svg> Скачать приложение</a>
|
||||
<a href="#"><svg class="icon"><use href="#i-info"/></svg> О сервисе</a>
|
||||
<div class="menu-divider"></div>
|
||||
<a href="auth.html" class="danger"><svg class="icon"><use href="#i-logout"/></svg> Выйти</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="hub-wrap">
|
||||
<div class="hub-intro">
|
||||
<p class="eyebrow">[ ДОБРО ПОЖАЛОВАТЬ В VIDCONF ]</p>
|
||||
<h1>Что делаем сегодня?</h1>
|
||||
</div>
|
||||
|
||||
<div class="hub">
|
||||
|
||||
<a class="action action--create" href="room.html">
|
||||
<span class="action-icon" aria-hidden="true"><svg class="icon"><use href="#i-video"/></svg></span>
|
||||
<h2 class="action-title">Создать</h2>
|
||||
<p class="action-object">конференцию</p>
|
||||
<p class="action-note">начнётся сразу — вы первый участник</p>
|
||||
</a>
|
||||
|
||||
<a class="action action--calendar" href="calendar.html">
|
||||
<span class="action-icon" aria-hidden="true"><svg class="icon"><use href="#i-calendar"/></svg></span>
|
||||
<h2 class="action-title">Календарь</h2>
|
||||
<p class="action-object">конференций</p>
|
||||
<p class="action-note">запланировать · закрепить · повторять</p>
|
||||
</a>
|
||||
|
||||
<a class="action action--join" href="join.html">
|
||||
<span class="action-icon" aria-hidden="true"><svg class="icon"><use href="#i-link2"/></svg></span>
|
||||
<h2 class="action-title">Подключиться</h2>
|
||||
<p class="action-object">к конференции</p>
|
||||
<p class="action-note">по ссылке или номеру</p>
|
||||
</a>
|
||||
|
||||
<a class="action action--mine" href="my-conferences.html">
|
||||
<span class="action-icon" aria-hidden="true"><svg class="icon"><use href="#i-user"/></svg></span>
|
||||
<h2 class="action-title">Мои</h2>
|
||||
<p class="action-object">конференции</p>
|
||||
<p class="action-note">закреплённые и предстоящие</p>
|
||||
</a>
|
||||
|
||||
<div class="hub-logo" aria-hidden="true">
|
||||
<svg class="logo-mark" viewBox="0 0 64 64" fill="none" aria-hidden="true">
|
||||
<polygon points="41,32 36.5,39.8 27.5,39.8 23,32 27.5,24.2 36.5,24.2" fill="currentColor"/>
|
||||
<circle cx="32" cy="32" r="15" stroke="currentColor" stroke-width="3" stroke-dasharray="16 7 28 9 12 16" stroke-dashoffset="5"/>
|
||||
<circle cx="32" cy="32" r="20" stroke="currentColor" stroke-width="2" stroke-dasharray="22 10 8 14 34 12 6 10" stroke-dashoffset="40"/>
|
||||
<circle cx="32" cy="32" r="25" stroke="currentColor" stroke-width="3.5" stroke-dasharray="40 14 12 10 26 16 20 8" stroke-dashoffset="80"/>
|
||||
<circle cx="32" cy="32" r="29" stroke="currentColor" stroke-width="1.6" stroke-dasharray="10 6 60 20 30 10 24 8" stroke-dashoffset="120"/>
|
||||
</svg>
|
||||
<span class="logo-word">VidConf</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Бургер-меню: открытие/закрытие, клик мимо и Escape закрывают.
|
||||
const burger = document.getElementById('burger');
|
||||
const menu = document.getElementById('main-menu');
|
||||
|
||||
function setMenu(open) {
|
||||
menu.classList.toggle('is-open', open);
|
||||
burger.setAttribute('aria-expanded', String(open));
|
||||
burger.setAttribute('aria-label', open ? 'Закрыть меню' : 'Открыть меню');
|
||||
}
|
||||
|
||||
burger.addEventListener('click', () => setMenu(!menu.classList.contains('is-open')));
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!e.target.closest('.menu-wrap')) setMenu(false);
|
||||
});
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') { setMenu(false); burger.focus(); }
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
354
design/mockups/my-conferences.html
Normal file
354
design/mockups/my-conferences.html
Normal file
@@ -0,0 +1,354 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Мои конференции</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../tokens.css">
|
||||
<style>
|
||||
/*
|
||||
* «Мои конференции» (фаза R1, пивот) — новый экран: список закреплённых
|
||||
* (постоянных, с повторением) и предстоящих разовых конференций
|
||||
* пользователя. У каждой — ссылка и номер с копированием, ближайшее
|
||||
* вхождение/дата и кнопка входа. Завершённые — переход к саммари, а не
|
||||
* повторный вход (незакреплённая конференция после завершения недоступна
|
||||
* для входа).
|
||||
*/
|
||||
|
||||
html { min-width: 1280px; }
|
||||
|
||||
.topbar {
|
||||
position: sticky; top: 0; z-index: 20;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: var(--space-4) var(--space-8);
|
||||
background: var(--color-surface);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
.brand-mark { display: inline-flex; align-items: center; gap: 8px; font: var(--text-h3); color: var(--color-ink-700); }
|
||||
.brand-mark .logo-mark { width: 22px; height: 22px; flex-shrink: 0; }
|
||||
.topbar-right { display: flex; align-items: center; gap: var(--space-5); }
|
||||
.nav-link { font: var(--text-body); font-weight: 600; color: var(--color-ink-500); text-decoration: none; }
|
||||
.nav-link.is-active { color: var(--color-ink-700); }
|
||||
.avatar-btn { display: flex; align-items: center; gap: 8px; background: var(--color-bg-alt); border: 1px solid var(--color-border); border-radius: var(--radius-full); padding: 6px 14px 6px 6px; }
|
||||
.avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--color-ink-700); color: #fff; display:flex; align-items:center; justify-content:center; font: var(--text-caption); text-transform: none; letter-spacing: 0; }
|
||||
/* Каскад-баг гейта (2026-07-16, 3-я итерация): было `.avatar-btn span`
|
||||
(0,1,1) — перебивало `.avatar { color:#fff }` (0,1,0), инициалы
|
||||
рендерились тёмным ink-900 на индиго-заливке (нечитаемо). Селектор имени
|
||||
сделан адресным — задевает только `.user-name`, не пересекается с
|
||||
`.avatar` ни при каком порядке правил. См. DESIGN_SYSTEM.md §1.5. */
|
||||
.avatar-btn .user-name { font: var(--text-body); font-weight: 600; color: var(--color-ink-900); }
|
||||
|
||||
main { padding: var(--space-8); max-width: 1280px; margin: 0 auto; }
|
||||
|
||||
.page-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: var(--space-6); }
|
||||
.page-head h1 { font: var(--text-display-lg); font-family: var(--font-display); color: var(--color-ink-700); margin: 0 0 6px; }
|
||||
.page-head p { font: var(--text-body-lg); color: var(--color-ink-500); margin: 0; }
|
||||
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; border: none; cursor: pointer; font-family: var(--font-body); white-space: nowrap; transition: background var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.btn-primary { background: var(--color-accent); color: var(--color-accent-text); font: var(--text-body); font-weight: 700; padding: 11px 22px; border-radius: var(--radius-full); }
|
||||
.btn-primary:hover { background: var(--color-accent-hover); box-shadow: var(--shadow-md); }
|
||||
.btn-primary:active { background: var(--color-accent-active); }
|
||||
.btn-secondary { background: transparent; color: var(--color-ink-700); border: 1.5px solid var(--color-border-pill); font: var(--text-body); font-weight: 600; padding: 9px 18px; border-radius: var(--radius-full); }
|
||||
.btn-secondary:hover { background: var(--color-bg-alt); }
|
||||
:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
|
||||
|
||||
.filters { display: flex; gap: 8px; margin-bottom: var(--space-6); }
|
||||
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 9px 16px; border-radius: var(--radius-full); border: 1.5px solid var(--color-border); background: var(--color-surface); font: var(--text-body); font-weight: 600; color: var(--color-ink-500); }
|
||||
.chip.is-active { border-color: var(--color-ink-700); color: var(--color-ink-700); background: var(--color-bg-alt); }
|
||||
|
||||
.conf-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-5); }
|
||||
|
||||
.conf-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-2xl); padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-4); transition: box-shadow var(--transition-base), border-color var(--transition-base); }
|
||||
.conf-card:hover { box-shadow: var(--shadow-md); border-color: var(--color-border-strong); }
|
||||
.conf-card.is-ended { opacity: .85; }
|
||||
|
||||
.conf-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
|
||||
.conf-title-wrap h3 { margin: 0 0 4px; font: var(--text-h3); color: var(--color-ink-900); display: flex; align-items: center; gap: 6px; }
|
||||
.conf-title-wrap p { margin: 0; font: var(--text-body); color: var(--color-ink-500); }
|
||||
|
||||
.conf-badge { display: inline-flex; align-items: center; gap: 5px; padding: 4px 12px; border-radius: var(--radius-full); font: var(--text-caption); white-space: nowrap; }
|
||||
.conf-badge.pinned { background: var(--color-bg-alt); color: var(--color-ink-700); border: 1px solid var(--color-border-strong); }
|
||||
.conf-badge.scheduled { background: var(--color-warning-bg); color: var(--color-warning); }
|
||||
.conf-badge.ended { background: var(--color-bg-alt); color: var(--color-ink-500); }
|
||||
|
||||
.conf-meta-row { display: flex; align-items: center; gap: var(--space-4); font: var(--text-body); color: var(--color-ink-500); }
|
||||
.conf-meta-row .meta-item { display: flex; align-items: center; gap: 6px; }
|
||||
|
||||
.pills-row { display: flex; gap: var(--space-3); }
|
||||
.pill-group { flex: 1; min-width: 0; }
|
||||
.pill-label { display: block; font: var(--text-caption); color: var(--color-ink-400); margin-bottom: 4px; }
|
||||
.code-pill { display: flex; align-items: center; gap: 6px; background: var(--color-bg-alt); border: 1px solid var(--color-border); border-radius: var(--radius-full); padding: 6px 6px 6px 14px; }
|
||||
.pill-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--text-mono-sm); color: var(--color-ink-700); }
|
||||
.copy-btn { position: relative; width: 28px; height: 28px; flex-shrink: 0; border-radius: 50%; border: none; background: var(--color-surface); color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; transition: color var(--transition-fast), box-shadow var(--transition-fast); }
|
||||
.copy-btn:hover { color: var(--color-ink-700); box-shadow: var(--shadow-sm); }
|
||||
.copy-btn .icon-check { display: none; color: var(--color-success); }
|
||||
.copy-btn.is-copied .icon-copy { display: none; }
|
||||
.copy-btn.is-copied .icon-check { display: block; }
|
||||
.copy-toast {
|
||||
position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
|
||||
background: var(--color-ink-900); color: #fff; font: var(--text-caption); text-transform: none; letter-spacing: normal;
|
||||
padding: 4px 10px; border-radius: var(--radius-sm); white-space: nowrap;
|
||||
opacity: 0; pointer-events: none; transition: opacity var(--transition-fast);
|
||||
}
|
||||
.copy-btn.is-copied .copy-toast { opacity: 1; }
|
||||
|
||||
.conf-card-footer { display: flex; gap: var(--space-3); margin-top: auto; }
|
||||
.conf-card-footer .btn { flex: 1; justify-content: center; }
|
||||
.icon-btn { width: 40px; height: 40px; flex-shrink: 0; border-radius: 50%; border: 1px solid var(--color-border); background: var(--color-surface); color: var(--color-ink-500); display: flex; align-items: center; justify-content: center; }
|
||||
.icon-btn:hover { border-color: var(--color-border-strong); color: var(--color-ink-900); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-repeat" viewBox="0 0 24 24"><path d="m17 2 4 4-4 4"/><path d="M3 11v-1a4 4 0 0 1 4-4h14"/><path d="m7 22-4-4 4-4"/><path d="M21 13v1a4 4 0 0 1-4 4H3"/></symbol>
|
||||
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
|
||||
<symbol id="i-check-circle" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></symbol>
|
||||
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
|
||||
<symbol id="i-users" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>
|
||||
<symbol id="i-copy" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></symbol>
|
||||
<symbol id="i-check" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></symbol>
|
||||
<symbol id="i-play" viewBox="0 0 24 24"><polygon points="6 3 20 12 6 21 6 3"/></symbol>
|
||||
<symbol id="i-pencil" viewBox="0 0 24 24"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></symbol>
|
||||
<symbol id="i-file-text" viewBox="0 0 24 24"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="16" y2="17"/></symbol>
|
||||
</svg>
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand-mark"><svg class="logo-mark" viewBox="0 0 32 32" fill="none" aria-hidden="true"><polygon points="21,16 18.5,20.3 13.5,20.3 11,16 13.5,11.7 18.5,11.7" fill="currentColor"/><circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2.6" stroke-dasharray="12 6"/></svg> VidConf</div>
|
||||
<nav class="topbar-right">
|
||||
<a href="lobby.html" class="nav-link">Лобби</a>
|
||||
<a href="calendar.html" class="nav-link">Календарь</a>
|
||||
<a href="my-conferences.html" class="nav-link is-active">Мои конференции</a>
|
||||
<a href="admin.html" class="nav-link">Админка</a>
|
||||
<button class="avatar-btn"><span class="avatar">АИ</span><span class="user-name">Анна Иванова</span></button>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="page-head">
|
||||
<div>
|
||||
<h1>Мои конференции</h1>
|
||||
<p>5 конференций · 3 закреплённые с повторением</p>
|
||||
</div>
|
||||
<a href="calendar.html" class="btn btn-primary">Запланировать новую</a>
|
||||
</div>
|
||||
|
||||
<div class="filters">
|
||||
<button class="chip is-active">Все</button>
|
||||
<button class="chip"><svg class="icon" style="width:14px;height:14px"><use href="#i-repeat"/></svg>Закреплённые</button>
|
||||
<button class="chip"><svg class="icon" style="width:14px;height:14px"><use href="#i-clock"/></svg>Предстоящие</button>
|
||||
<button class="chip">Завершённые</button>
|
||||
</div>
|
||||
|
||||
<section class="conf-grid">
|
||||
|
||||
<!-- Закреплена, еженедельно -->
|
||||
<article class="conf-card">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3>Ревью спринта</h3>
|
||||
<p>По вторникам и четвергам, 11:00–11:45</p>
|
||||
</div>
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:12px;height:12px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-clock"/></svg>Ближайшее: вт, 22 июля, 11:00</span>
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>8 участников</span>
|
||||
</div>
|
||||
<div class="pills-row">
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Ссылка</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">vidconf.ru/j/sprint-review</span>
|
||||
<button class="copy-btn" data-copy="https://vidconf.ru/j/sprint-review" aria-label="Скопировать ссылку">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Номер</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">8842 104</span>
|
||||
<button class="copy-btn" data-copy="8842 104" aria-label="Скопировать номер">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<a href="room.html" class="btn btn-primary"><svg class="icon" style="width:16px;height:16px"><use href="#i-play"/></svg>Войти</a>
|
||||
<button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:17px;height:17px"><use href="#i-pencil"/></svg></button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Закреплена, ежемесячно, закрытая паролем -->
|
||||
<article class="conf-card">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3><svg class="icon" style="width:15px;height:15px;flex-shrink:0"><use href="#i-lock"/></svg>Синк по релизу 2.4</h3>
|
||||
<p>Раз в месяц, 15-го числа, 14:00–15:00</p>
|
||||
</div>
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:12px;height:12px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-clock"/></svg>Ближайшее: 15 августа, 14:00</span>
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>4 участника</span>
|
||||
</div>
|
||||
<div class="pills-row">
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Ссылка</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">vidconf.ru/j/release-sync</span>
|
||||
<button class="copy-btn" data-copy="https://vidconf.ru/j/release-sync" aria-label="Скопировать ссылку">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Номер</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">5217 933</span>
|
||||
<button class="copy-btn" data-copy="5217 933" aria-label="Скопировать номер">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<a href="join.html" class="btn btn-primary"><svg class="icon" style="width:16px;height:16px"><use href="#i-lock"/></svg>Войти по паролю</a>
|
||||
<button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:17px;height:17px"><use href="#i-pencil"/></svg></button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Предстоящая, разовая -->
|
||||
<article class="conf-card">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3>1:1 с руководителем</h3>
|
||||
<p>Разовая · 21 июля, 15:00–15:30</p>
|
||||
</div>
|
||||
<span class="conf-badge scheduled"><svg class="icon" style="width:12px;height:12px"><use href="#i-clock"/></svg>Предстоящая</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>2 участника</span>
|
||||
</div>
|
||||
<div class="pills-row">
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Ссылка</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">vidconf.ru/j/one-on-one</span>
|
||||
<button class="copy-btn" data-copy="https://vidconf.ru/j/one-on-one" aria-label="Скопировать ссылку">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Номер</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">2094 471</span>
|
||||
<button class="copy-btn" data-copy="2094 471" aria-label="Скопировать номер">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<button class="btn btn-secondary" style="flex:1" disabled><svg class="icon" style="width:16px;height:16px"><use href="#i-clock"/></svg>Начнётся через 3 дня</button>
|
||||
<button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:17px;height:17px"><use href="#i-pencil"/></svg></button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Завершена (незакреплённая — повторный вход недоступен, только саммари) -->
|
||||
<article class="conf-card is-ended">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3>Итоги квартала</h3>
|
||||
<p>Разовая · 29 июня, 12:00–13:00</p>
|
||||
</div>
|
||||
<span class="conf-badge ended"><svg class="icon" style="width:12px;height:12px"><use href="#i-check-circle"/></svg>Завершена</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>14 участников</span>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<a href="email-summary.html" class="btn btn-secondary" style="flex:1"><svg class="icon" style="width:16px;height:16px"><use href="#i-file-text"/></svg>Открыть саммари</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Закреплена, каждые N дней -->
|
||||
<article class="conf-card">
|
||||
<div class="conf-card-head">
|
||||
<div class="conf-title-wrap">
|
||||
<h3>Ежеквартальный отчёт</h3>
|
||||
<p>Каждые 90 дней, 10:00–11:00</p>
|
||||
</div>
|
||||
<span class="conf-badge pinned"><svg class="icon" style="width:12px;height:12px"><use href="#i-repeat"/></svg>Закреплена</span>
|
||||
</div>
|
||||
<div class="conf-meta-row">
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-clock"/></svg>Ближайшее: 3 октября, 10:00</span>
|
||||
<span class="meta-item"><svg class="icon" style="width:15px;height:15px"><use href="#i-users"/></svg>22 участника</span>
|
||||
</div>
|
||||
<div class="pills-row">
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Ссылка</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">vidconf.ru/j/q-report</span>
|
||||
<button class="copy-btn" data-copy="https://vidconf.ru/j/q-report" aria-label="Скопировать ссылку">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pill-group">
|
||||
<span class="pill-label">Номер</span>
|
||||
<div class="code-pill">
|
||||
<span class="pill-value">6630 812</span>
|
||||
<button class="copy-btn" data-copy="6630 812" aria-label="Скопировать номер">
|
||||
<svg class="icon icon-copy" style="width:14px;height:14px"><use href="#i-copy"/></svg>
|
||||
<svg class="icon icon-check" style="width:14px;height:14px"><use href="#i-check"/></svg>
|
||||
<span class="copy-toast" aria-hidden="true">Скопировано</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conf-card-footer">
|
||||
<button class="btn btn-secondary" style="flex:1" disabled><svg class="icon" style="width:16px;height:16px"><use href="#i-clock"/></svg>Начнётся 3 октября</button>
|
||||
<button class="icon-btn" aria-label="Редактировать"><svg class="icon" style="width:17px;height:17px"><use href="#i-pencil"/></svg></button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Копирование ссылки/номера в буфер обмена + временная подсказка «Скопировано».
|
||||
document.querySelectorAll('.copy-btn').forEach((btn) => {
|
||||
const originalLabel = btn.getAttribute('aria-label');
|
||||
btn.addEventListener('click', () => {
|
||||
const text = btn.dataset.copy || '';
|
||||
if (navigator.clipboard) { navigator.clipboard.writeText(text).catch(() => {}); }
|
||||
btn.classList.add('is-copied');
|
||||
btn.setAttribute('aria-label', 'Скопировано');
|
||||
setTimeout(() => {
|
||||
btn.classList.remove('is-copied');
|
||||
btn.setAttribute('aria-label', originalLabel);
|
||||
}, 1500);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
336
design/mockups/room.html
Normal file
336
design/mockups/room.html
Normal file
@@ -0,0 +1,336 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-theme="room">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>VidConf — Комната конференции</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../tokens.css">
|
||||
<style>
|
||||
html { min-width: 1280px; }
|
||||
body { background: var(--color-room-bg); color: var(--color-room-text-primary); overflow-x: hidden; }
|
||||
|
||||
.room-shell { display: flex; flex-direction: column; height: 100vh; }
|
||||
|
||||
/* ---------- Топбар ---------- */
|
||||
.room-topbar {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
padding: var(--space-3) var(--space-6);
|
||||
background: var(--color-room-surface);
|
||||
border-bottom: 1px solid var(--color-room-tile-border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.room-title-block h1 { font: var(--text-h3); margin: 0 0 2px; color: var(--color-room-text-primary); }
|
||||
.room-title-block p { font: var(--text-body); margin: 0; color: var(--color-room-text-secondary); display:flex; align-items:center; gap:8px; }
|
||||
.rec-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-room-danger); box-shadow: 0 0 0 3px rgba(235,147,161,.3); }
|
||||
|
||||
.layout-switch { display: flex; align-items: center; gap: var(--space-2); }
|
||||
.icon-btn {
|
||||
width: 40px; height: 40px; border-radius: var(--radius-md);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
background: transparent; border: 1px solid transparent; color: var(--color-room-text-secondary);
|
||||
}
|
||||
.icon-btn:hover { background: var(--color-room-tile-hover); color: var(--color-room-text-primary); }
|
||||
.icon-btn.is-active { background: var(--color-room-tile); color: var(--color-room-speaker-ring); border-color: var(--color-room-speaker-ring); }
|
||||
|
||||
/* ---------- Основная область: превью + крупные плитки + чат ---------- */
|
||||
.room-main { display: flex; flex: 1; min-height: 0; }
|
||||
.stage { flex: 1; display: flex; flex-direction: column; padding: var(--space-5) var(--space-6); gap: var(--space-4); min-width: 0; }
|
||||
|
||||
.preview-row { display: flex; align-items: center; gap: var(--space-3); }
|
||||
.preview-scroll { display: flex; gap: var(--space-3); overflow-x: auto; flex: 1; padding-bottom: 4px; }
|
||||
.preview-scroll::-webkit-scrollbar { height: 6px; }
|
||||
.preview-scroll::-webkit-scrollbar-thumb { background: var(--color-room-tile-border); border-radius: 3px; }
|
||||
|
||||
.scroll-arrow {
|
||||
width: 32px; height: 32px; flex-shrink: 0; border-radius: 50%;
|
||||
background: var(--color-room-surface); border: 1px solid var(--color-room-tile-border);
|
||||
color: var(--color-room-text-secondary); display:flex; align-items:center; justify-content:center;
|
||||
}
|
||||
.scroll-arrow:hover { color: var(--color-room-text-primary); }
|
||||
|
||||
.tile {
|
||||
position: relative; background: var(--color-room-tile); border-radius: var(--radius-lg);
|
||||
border: 1px solid var(--color-room-tile-border); overflow: hidden;
|
||||
}
|
||||
.tile-preview { width: 160px; height: 100px; flex-shrink: 0; }
|
||||
.tile-name {
|
||||
position: absolute; top: 8px; left: 8px; font: var(--text-body);
|
||||
font-weight: 600; color: var(--color-room-text-primary);
|
||||
background: rgba(0,0,0,.35); padding: 2px 8px; border-radius: var(--radius-sm);
|
||||
max-width: calc(100% - 16px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
.tile-preview .tile-name { font-size: 12px; padding: 1px 6px; }
|
||||
.tile-avatar {
|
||||
position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.tile-avatar svg { width: 38%; height: 38%; color: #555; }
|
||||
.tile-preview .tile-avatar svg { width: 30%; height: 30%; }
|
||||
|
||||
.mic-indicator {
|
||||
position: absolute; bottom: 8px; left: 8px; width: 26px; height: 26px; border-radius: 50%;
|
||||
background: rgba(0,0,0,.4); display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.mic-indicator.on { color: var(--color-room-mic-on); }
|
||||
.mic-indicator.off { color: var(--color-room-mic-off); }
|
||||
.mic-indicator .icon { width: 15px; height: 15px; }
|
||||
.tile-preview .mic-indicator { width: 20px; height: 20px; bottom: 6px; left: 6px; }
|
||||
.tile-preview .mic-indicator .icon { width: 12px; height: 12px; }
|
||||
|
||||
.tile.is-speaking { border: var(--border-speaker) solid var(--color-room-speaker-ring); box-shadow: var(--shadow-speaker-glow); }
|
||||
|
||||
.stage-tiles { flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); min-height: 0; }
|
||||
.tile-large { min-height: 0; }
|
||||
.tile-corner-actions { position: absolute; top: 10px; right: 10px; display: flex; gap: 6px; opacity: .85; }
|
||||
.tile-corner-actions button { width: 30px; height: 30px; border-radius: var(--radius-sm); background: rgba(0,0,0,.35); border: none; color: var(--color-room-text-primary); display:flex; align-items:center; justify-content:center; }
|
||||
.tile-corner-actions button:hover { background: rgba(0,0,0,.55); }
|
||||
|
||||
.video-off-badge {
|
||||
position: absolute; bottom: 8px; right: 8px; background: rgba(0,0,0,.4);
|
||||
border-radius: var(--radius-sm); padding: 4px 8px; display:flex; align-items:center; gap:4px;
|
||||
font: var(--text-caption); color: var(--color-room-text-secondary); text-transform:none; letter-spacing:normal;
|
||||
}
|
||||
|
||||
/* ---------- Панель чата ---------- */
|
||||
.chat-panel {
|
||||
width: 320px; flex-shrink: 0; background: var(--color-room-surface-raised);
|
||||
border-left: 1px solid var(--color-room-tile-border);
|
||||
display: flex; flex-direction: column; box-shadow: var(--shadow-room-panel);
|
||||
}
|
||||
.chat-head { display:flex; align-items:center; justify-content:space-between; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--color-room-tile-border); }
|
||||
.chat-head h2 { font: var(--text-h3); margin: 0; }
|
||||
.chat-head button { background: none; border: none; color: var(--color-room-text-secondary); }
|
||||
.chat-head button:hover { color: var(--color-room-text-primary); }
|
||||
|
||||
.chat-messages { flex: 1; overflow-y: auto; padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-4); }
|
||||
.msg .msg-meta { display:flex; align-items:baseline; gap: 8px; margin-bottom: 4px; }
|
||||
.msg .msg-author { font: var(--text-body); font-weight: 700; color: var(--color-room-mic-on); }
|
||||
.msg .msg-time { font: 12px var(--font-body); color: var(--color-room-text-tertiary); }
|
||||
.msg .msg-bubble { background: var(--color-room-tile); border-radius: var(--radius-md); padding: 10px 14px; font: var(--text-body); color: var(--color-room-text-primary); }
|
||||
|
||||
.chat-input-row { padding: var(--space-4); border-top: 1px solid var(--color-room-tile-border); display: flex; gap: 8px; }
|
||||
.chat-input-row input {
|
||||
flex: 1; background: var(--color-room-tile); border: 1px solid var(--color-room-tile-border);
|
||||
border-radius: var(--radius-full); padding: 10px 16px; color: var(--color-room-text-primary); font: var(--text-body-lg);
|
||||
}
|
||||
.chat-input-row input::placeholder { color: var(--color-room-text-tertiary); }
|
||||
.chat-input-row button {
|
||||
width: 42px; height: 42px; border-radius: 50%; background: var(--color-room-mic-on); border: none;
|
||||
color: #10331f; display:flex; align-items:center; justify-content:center; flex-shrink:0;
|
||||
}
|
||||
|
||||
/* ---------- Нижний тулбар ---------- */
|
||||
.room-toolbar {
|
||||
display: flex; align-items: center; justify-content: center; gap: var(--space-2);
|
||||
background: var(--color-room-surface); border-top: 1px solid var(--color-room-tile-border);
|
||||
padding: var(--space-3) var(--space-6); flex-shrink: 0;
|
||||
}
|
||||
.tb-btn {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 4px;
|
||||
background: transparent; border: none; padding: 8px 18px; border-radius: var(--radius-md);
|
||||
color: var(--color-room-text-primary); min-width: 76px;
|
||||
}
|
||||
.tb-btn .icon-shell {
|
||||
width: 48px; height: 48px; border-radius: 50%; display:flex; align-items:center; justify-content:center;
|
||||
border: 1.5px solid var(--color-room-tile-border); background: var(--color-room-tile);
|
||||
}
|
||||
.tb-btn span.label { font: var(--text-caption); text-transform: none; letter-spacing: normal; color: var(--color-room-text-secondary); font-weight: 500; }
|
||||
.tb-btn:hover .icon-shell { background: var(--color-room-tile-hover); }
|
||||
|
||||
.tb-btn.is-on .icon-shell { color: var(--color-room-text-primary); }
|
||||
.tb-btn.is-off .icon-shell { background: var(--color-room-mic-off); border-color: var(--color-room-mic-off); color: #3a0f16; }
|
||||
.tb-btn.is-off span.label { color: var(--color-room-mic-off); font-weight: 700; }
|
||||
|
||||
.tb-btn.is-positive-active .icon-shell { background: var(--color-room-mic-on); border-color: var(--color-room-mic-on); color: #0e3320; }
|
||||
.tb-btn.is-positive-active span.label { color: var(--color-room-mic-on); font-weight: 700; }
|
||||
|
||||
.tb-btn.is-panel-open .icon-shell { background: var(--color-room-surface-raised); border-color: var(--color-room-speaker-ring); color: var(--color-room-speaker-ring); }
|
||||
|
||||
.tb-btn.danger .icon-shell { border-color: var(--color-room-danger); color: var(--color-room-danger); background: transparent; }
|
||||
.tb-btn.danger:hover .icon-shell { background: var(--color-room-danger-bg); color: #fff; border-color: var(--color-room-danger-bg); }
|
||||
.tb-btn.danger span.label { color: var(--color-room-danger); font-weight: 700; }
|
||||
|
||||
.badge-count {
|
||||
position: absolute; top: -2px; right: -2px; background: var(--color-room-mic-on); color: #0e3320;
|
||||
font-size: 10px; font-weight: 700; width: 16px; height: 16px; border-radius: 50%;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
|
||||
/* ---------- Демонстрация состояния "чат свёрнут" ---------- */
|
||||
.collapsed-demo {
|
||||
margin-top: var(--space-6); padding: var(--space-5) var(--space-6);
|
||||
background: var(--color-room-surface); border-top: 1px solid var(--color-room-tile-border);
|
||||
}
|
||||
.collapsed-demo p.label { font: var(--text-caption); color: var(--color-room-text-secondary); text-transform: none; letter-spacing: normal; margin: 0 0 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg style="display:none">
|
||||
<symbol id="i-mic" viewBox="0 0 24 24"><path d="M12 2a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v1a7 7 0 0 1-14 0v-1"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="8" y1="22" x2="16" y2="22"/></symbol>
|
||||
<symbol id="i-mic-off" viewBox="0 0 24 24"><path d="M9 9v3a3 3 0 0 0 4.24 2.73"/><path d="M15 9.34V5a3 3 0 0 0-5.94-.6"/><path d="M19 10v1a7 7 0 0 1-11.5 5.34"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="8" y1="22" x2="16" y2="22"/><line x1="2" y1="2" x2="22" y2="22"/></symbol>
|
||||
<symbol id="i-video" viewBox="0 0 24 24"><rect x="2" y="6" width="14" height="12" rx="2"/><path d="m22 8-6 4 6 4V8Z"/></symbol>
|
||||
<symbol id="i-video-off" viewBox="0 0 24 24"><path d="M16 16v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h1"/><path d="M9.5 6H14a2 2 0 0 1 2 2v4.5"/><path d="m22 8-6 4"/><line x1="2" y1="2" x2="22" y2="22"/></symbol>
|
||||
<symbol id="i-share" viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/><path d="M9 10.5 12 7l3 3.5"/><line x1="12" y1="7" x2="12" y2="14"/></symbol>
|
||||
<symbol id="i-chat" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="13" rx="3"/><path d="m7 17-3 4v-4"/></symbol>
|
||||
<symbol id="i-users" viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></symbol>
|
||||
<symbol id="i-logout" viewBox="0 0 24 24"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></symbol>
|
||||
<symbol id="i-user" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M6 21v-2a6 6 0 0 1 12 0v2"/></symbol>
|
||||
<symbol id="i-grid" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/></symbol>
|
||||
<symbol id="i-columns" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="3" x2="9" y2="21"/></symbol>
|
||||
<symbol id="i-grid2" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="12" y1="3" x2="12" y2="21"/><line x1="3" y1="12" x2="21" y2="12"/></symbol>
|
||||
<symbol id="i-settings" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z"/></symbol>
|
||||
<symbol id="i-maximize" viewBox="0 0 24 24"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></symbol>
|
||||
<symbol id="i-more" viewBox="0 0 24 24"><circle cx="12" cy="5" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="12" cy="19" r="1.5"/></symbol>
|
||||
<symbol id="i-chevron-left" viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></symbol>
|
||||
<symbol id="i-chevron-right" viewBox="0 0 24 24"><polyline points="9 18 15 12 9 6"/></symbol>
|
||||
<symbol id="i-send" viewBox="0 0 24 24"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></symbol>
|
||||
<symbol id="i-x" viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></symbol>
|
||||
</svg>
|
||||
|
||||
<div class="room-shell">
|
||||
|
||||
<header class="room-topbar">
|
||||
<div class="room-title-block">
|
||||
<h1>Переговорная №42 · Спринт-ревью команды платформы</h1>
|
||||
<p><span class="rec-dot" aria-hidden="true"></span> Идёт запись · 00:24:11 · 8 участников</p>
|
||||
</div>
|
||||
<div class="layout-switch">
|
||||
<button class="icon-btn is-active" aria-label="Раскладка: лента + спикер"><svg class="icon"><use href="#i-grid"/></svg></button>
|
||||
<button class="icon-btn" aria-label="Раскладка: колонки"><svg class="icon"><use href="#i-columns"/></svg></button>
|
||||
<button class="icon-btn" aria-label="Раскладка: равная сетка"><svg class="icon"><use href="#i-grid2"/></svg></button>
|
||||
<button class="icon-btn" aria-label="Настройки"><svg class="icon"><use href="#i-settings"/></svg></button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="room-main">
|
||||
<section class="stage">
|
||||
|
||||
<!-- Лента превью участников -->
|
||||
<div class="preview-row">
|
||||
<button class="scroll-arrow" aria-label="Прокрутить влево"><svg class="icon" style="width:16px;height:16px"><use href="#i-chevron-left"/></svg></button>
|
||||
<div class="preview-scroll">
|
||||
<div class="tile tile-preview">
|
||||
<div class="tile-name">Дмитрий Кошелев</div>
|
||||
<div class="tile-avatar"><svg class="icon"><use href="#i-user"/></svg></div>
|
||||
<div class="mic-indicator off"><svg class="icon"><use href="#i-mic-off"/></svg></div>
|
||||
</div>
|
||||
<div class="tile tile-preview">
|
||||
<div class="tile-name">Ольга Панина</div>
|
||||
<div class="tile-avatar"><svg class="icon"><use href="#i-user"/></svg></div>
|
||||
<div class="mic-indicator off"><svg class="icon"><use href="#i-mic-off"/></svg></div>
|
||||
</div>
|
||||
<div class="tile tile-preview">
|
||||
<div class="tile-name">Виктор Седых</div>
|
||||
<div class="tile-avatar"><svg class="icon"><use href="#i-user"/></svg></div>
|
||||
<div class="mic-indicator on"><svg class="icon"><use href="#i-mic"/></svg></div>
|
||||
</div>
|
||||
<div class="tile tile-preview">
|
||||
<div class="tile-name">Настя Титова</div>
|
||||
<div class="tile-avatar"><svg class="icon"><use href="#i-user"/></svg></div>
|
||||
<div class="mic-indicator off"><svg class="icon"><use href="#i-mic-off"/></svg></div>
|
||||
</div>
|
||||
<div class="tile tile-preview">
|
||||
<div class="tile-name">Роман Матвеев</div>
|
||||
<div class="tile-avatar"><svg class="icon"><use href="#i-user"/></svg></div>
|
||||
<div class="mic-indicator on"><svg class="icon"><use href="#i-mic"/></svg></div>
|
||||
</div>
|
||||
<div class="tile tile-preview">
|
||||
<div class="tile-name">Елена Жукова</div>
|
||||
<div class="tile-avatar"><svg class="icon"><use href="#i-user"/></svg></div>
|
||||
<div class="mic-indicator off"><svg class="icon"><use href="#i-mic-off"/></svg></div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="scroll-arrow" aria-label="Прокрутить вправо"><svg class="icon" style="width:16px;height:16px"><use href="#i-chevron-right"/></svg></button>
|
||||
</div>
|
||||
|
||||
<!-- Крупные плитки: активный спикер + участник -->
|
||||
<div class="stage-tiles">
|
||||
<div class="tile tile-large is-speaking">
|
||||
<div class="tile-name">Игорь Соколов</div>
|
||||
<div class="tile-corner-actions">
|
||||
<button aria-label="Развернуть на весь экран"><svg class="icon" style="width:16px;height:16px"><use href="#i-maximize"/></svg></button>
|
||||
<button aria-label="Ещё действия"><svg class="icon" style="width:16px;height:16px"><use href="#i-more"/></svg></button>
|
||||
</div>
|
||||
<div class="tile-avatar"><svg class="icon" style="color:#8a8a8a"><use href="#i-user"/></svg></div>
|
||||
<div class="mic-indicator on"><svg class="icon"><use href="#i-mic"/></svg></div>
|
||||
</div>
|
||||
<div class="tile tile-large">
|
||||
<div class="tile-name">Мария Кузнецова</div>
|
||||
<div class="tile-corner-actions">
|
||||
<button aria-label="Развернуть на весь экран"><svg class="icon" style="width:16px;height:16px"><use href="#i-maximize"/></svg></button>
|
||||
<button aria-label="Ещё действия"><svg class="icon" style="width:16px;height:16px"><use href="#i-more"/></svg></button>
|
||||
</div>
|
||||
<div class="tile-avatar"><svg class="icon" style="color:#8a8a8a"><use href="#i-user"/></svg></div>
|
||||
<div class="mic-indicator off"><svg class="icon"><use href="#i-mic-off"/></svg></div>
|
||||
<div class="video-off-badge"><svg class="icon" style="width:12px;height:12px"><use href="#i-video-off"/></svg>Камера выключена</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Панель чата: РАЗВЁРНУТОЕ состояние -->
|
||||
<aside class="chat-panel">
|
||||
<div class="chat-head">
|
||||
<h2>Чат встречи</h2>
|
||||
<button aria-label="Свернуть чат"><svg class="icon"><use href="#i-x"/></svg></button>
|
||||
</div>
|
||||
<div class="chat-messages">
|
||||
<div class="msg">
|
||||
<div class="msg-meta"><span class="msg-author">Виктор Седых</span><span class="msg-time">14:02</span></div>
|
||||
<div class="msg-bubble">Отправил ссылку на дизайн-макеты в описании встречи</div>
|
||||
</div>
|
||||
<div class="msg">
|
||||
<div class="msg-meta"><span class="msg-author">Ольга Панина</span><span class="msg-time">14:03</span></div>
|
||||
<div class="msg-bubble">Принято, посмотрю после демо API</div>
|
||||
</div>
|
||||
<div class="msg">
|
||||
<div class="msg-meta"><span class="msg-author">Игорь Соколов</span><span class="msg-time">14:05</span></div>
|
||||
<div class="msg-bubble">Начинаем со спринт-ревью, затем — блок вопросов</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-input-row">
|
||||
<input type="text" placeholder="Написать сообщение…">
|
||||
<button aria-label="Отправить"><svg class="icon" style="width:18px;height:18px"><use href="#i-send"/></svg></button>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<!-- Нижний тулбар -->
|
||||
<footer class="room-toolbar">
|
||||
<button class="tb-btn is-off">
|
||||
<span class="icon-shell"><svg class="icon"><use href="#i-mic-off"/></svg></span>
|
||||
<span class="label">Микрофон</span>
|
||||
</button>
|
||||
<button class="tb-btn is-on">
|
||||
<span class="icon-shell"><svg class="icon"><use href="#i-video"/></svg></span>
|
||||
<span class="label">Камера</span>
|
||||
</button>
|
||||
<button class="tb-btn is-positive-active">
|
||||
<span class="icon-shell"><svg class="icon"><use href="#i-share"/></svg></span>
|
||||
<span class="label">Демонстрация</span>
|
||||
</button>
|
||||
<button class="tb-btn is-panel-open">
|
||||
<span class="icon-shell" style="position:relative"><svg class="icon"><use href="#i-chat"/></svg><span class="badge-count">3</span></span>
|
||||
<span class="label">Чат</span>
|
||||
</button>
|
||||
<button class="tb-btn is-on">
|
||||
<span class="icon-shell"><svg class="icon"><use href="#i-users"/></svg></span>
|
||||
<span class="label">Участники</span>
|
||||
</button>
|
||||
<button class="tb-btn danger">
|
||||
<span class="icon-shell"><svg class="icon"><use href="#i-logout"/></svg></span>
|
||||
<span class="label">Выйти</span>
|
||||
</button>
|
||||
</footer>
|
||||
|
||||
<!-- Документация состояния: чат свёрнут -->
|
||||
<div class="collapsed-demo">
|
||||
<p class="label">Справочно — состояние тулбара, когда панель чата свёрнута (иконка без подсветки, счётчик непрочитанных сохраняется):</p>
|
||||
<button class="tb-btn is-on" style="display:inline-flex">
|
||||
<span class="icon-shell" style="position:relative"><svg class="icon"><use href="#i-chat"/></svg><span class="badge-count">3</span></span>
|
||||
<span class="label">Чат</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user