Копирайт целиком переехал в общий футер (решение оператора), в панели строка больше не нужна. У `.brand-panel` осталось два потомка вместо трёх, поэтому `.brand-copy` получил `margin-block: auto` — иначе `justify-content: space-between` прижал бы текст к низу панели.
278 lines
12 KiB
CSS
278 lines
12 KiB
CSS
/*
|
||
* VidConf — стили экранов auth (вход/регистрация/подтверждение email).
|
||
* 1:1 воспроизводит design/mockups/auth.html.
|
||
*/
|
||
|
||
.layout { display: flex; min-height: 100vh; }
|
||
|
||
/* ---------- Брендовая панель ---------- */
|
||
.brand-panel {
|
||
width: 42%;
|
||
background: linear-gradient(160deg, #EDEFFA 0%, #F1F1F1 55%, #F7F7F8 100%);
|
||
padding: 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, 0.45), rgba(212, 242, 227, 0) 70%);
|
||
}
|
||
/* `margin-block: auto` держит блок по центру свободной высоты панели. Нужно
|
||
с тех пор, как из панели убрали нижнюю строку копирайта (она переехала в
|
||
общий футер): у `.brand-panel` осталось два потомка вместо трёх, и
|
||
`justify-content: space-between` иначе прижал бы текст к самому низу. */
|
||
.brand-copy { z-index: 1; margin-block: auto; }
|
||
.eyebrow {
|
||
font: var(--text-caption);
|
||
letter-spacing: 0.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, 0.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;
|
||
justify-content: center;
|
||
}
|
||
.screen-block { max-width: 440px; width: 100%; }
|
||
.screen-title { font: var(--text-h1); color: var(--color-ink-900); margin: 0 0 var(--space-8); }
|
||
|
||
.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);
|
||
text-decoration: none;
|
||
display: inline-flex;
|
||
}
|
||
.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; display: flex; align-items: center; }
|
||
.input-wrap .field-icon { position: absolute; left: 14px; color: var(--color-ink-400); pointer-events: none; }
|
||
.input-wrap input, .input-wrap select {
|
||
width: 100%;
|
||
font: var(--text-body-lg);
|
||
font-family: var(--font-body);
|
||
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, .input-wrap select:hover { border-color: var(--color-border-strong); }
|
||
.input-wrap input:focus, .input-wrap select:focus { border-color: var(--color-focus-ring); box-shadow: 0 0 0 3px rgba(59, 77, 149, 0.12); }
|
||
/* Нативный select в WebKit/Safari игнорирует border/border-radius/background
|
||
без явного отключения UA-рендеринга: без appearance:none контрол рисуется
|
||
системным виджетом («аквариумная» рамка ОС) поверх авторских стилей — этим
|
||
объясняется «браузерный дефолт» без скругления и с меньшей высотой. */
|
||
.input-wrap select {
|
||
appearance: none;
|
||
-webkit-appearance: none;
|
||
-moz-appearance: none;
|
||
padding-right: 38px;
|
||
cursor: pointer;
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236976AC' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
|
||
background-repeat: no-repeat;
|
||
background-position: right 14px center;
|
||
background-size: 16px;
|
||
}
|
||
.input-wrap .toggle-eye {
|
||
position: absolute;
|
||
right: 14px;
|
||
left: auto;
|
||
background: none;
|
||
border: none;
|
||
padding: 0;
|
||
cursor: pointer;
|
||
color: var(--color-ink-400);
|
||
display: flex;
|
||
}
|
||
|
||
.field.has-error input { border-color: var(--color-danger); box-shadow: 0 0 0 3px rgba(199, 54, 79, 0.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); }
|
||
|
||
.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; background: none; border: none; cursor: pointer; font: var(--text-body); }
|
||
.link:hover { text-decoration: underline; }
|
||
|
||
.btn-block { width: 100%; }
|
||
.btn-primary.btn-lg { font: var(--text-body-lg); font-weight: 700; padding: 13px 24px; }
|
||
.btn-secondary.btn-lg { font: var(--text-body-lg); font-weight: 600; padding: 12px 24px; }
|
||
|
||
/* ---------- Подтверждение 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-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);
|
||
}
|
||
.confirm-card.pending .confirm-icon { background: var(--color-warning-bg); color: var(--color-warning); }
|
||
.confirm-card.error .confirm-icon { background: var(--color-danger-bg); color: var(--color-danger); }
|
||
|
||
/* ---------- Переключатель темы: плавающая плашка (см. AuthLayout.tsx) ---------- */
|
||
.theme-toggle--floating {
|
||
position: fixed;
|
||
top: 24px;
|
||
right: 32px;
|
||
z-index: 50;
|
||
box-shadow: var(--shadow-md);
|
||
}
|
||
|
||
/* =====================================================================
|
||
* Тёмная тема: точечные патчи (design/mockups/dark/README.md, категория
|
||
* «декоративные градиенты/тени») — литеральные rgba построены на индиго/
|
||
* старом danger-hex светлой темы, поэтому не перекрашиваются через var().
|
||
* ===================================================================== */
|
||
@media (prefers-color-scheme: dark) {
|
||
:root:not([data-theme]) .brand-panel {
|
||
background: linear-gradient(160deg, #242424 0%, #1E1E1E 55%, #1A1A1A 100%);
|
||
}
|
||
:root:not([data-theme]) .brand-panel::after {
|
||
background: radial-gradient(circle at 30% 30%, rgba(127, 221, 168, 0.16), rgba(127, 221, 168, 0) 70%);
|
||
}
|
||
:root:not([data-theme]) .stat-glass { border-color: rgba(255, 255, 255, 0.08); }
|
||
}
|
||
:root[data-theme='dark'] .brand-panel {
|
||
background: linear-gradient(160deg, #242424 0%, #1E1E1E 55%, #1A1A1A 100%);
|
||
}
|
||
:root[data-theme='dark'] .brand-panel::after {
|
||
background: radial-gradient(circle at 30% 30%, rgba(127, 221, 168, 0.16), rgba(127, 221, 168, 0) 70%);
|
||
}
|
||
:root[data-theme='dark'] .stat-glass { border-color: rgba(255, 255, 255, 0.08); }
|
||
|
||
/* ---------- Узкие экраны ---------- */
|
||
/* ВАЖНО: этот блок должен идти строго ПОСЛЕДНИМ в файле — при равной
|
||
специфичности с безусловными правилами выше (`.brand-panel`, `.form-panel`
|
||
и т.п. — те же 0,1,0) побеждает порядок в исходнике, а не сам факт
|
||
совпадения media query (тот же баг уже ловили в lobby.css/.action, гейт 3
|
||
— см. комментарий там). Макет auth.html — desktop-only
|
||
(`html { min-width: 1280px }`), адаптива в нём нет.
|
||
Причина исходного бага: `.layout` — flex-row из двух панелей с width
|
||
в процентах и без flex-shrink:0, а `.brand-panel` — overflow:hidden (нужен
|
||
для декоративного круга). По спецификации flex, overflow:hidden отключает
|
||
автоматический min-width:auto (= min-content) и делает его 0 — поэтому
|
||
при узком viewport панель схлопывалась намного уже своего текста, а не
|
||
переносила его: overflow:hidden просто обрезал то, что не поместилось,
|
||
вместо переноса строк. Решение — не подбирать min-width, а на узких
|
||
экранах складывать колонки в одну: тогда ширина каждой панели равна 100%
|
||
и конкуренции за пространство между ними нет вовсе. */
|
||
@media (max-width: 900px) {
|
||
.layout {
|
||
flex-direction: column;
|
||
min-height: auto;
|
||
}
|
||
.brand-panel {
|
||
width: 100%;
|
||
min-width: 0;
|
||
padding: var(--space-8) var(--space-6) var(--space-6);
|
||
border-right: none;
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
.brand-panel::after {
|
||
width: 220px;
|
||
height: 220px;
|
||
right: -90px;
|
||
bottom: -90px;
|
||
}
|
||
/* clamp() — на узких экранах слово «инфраструктура» иначе вылезает за
|
||
край брендовой панели (см. .brand-panel padding ниже и её overflow:hidden,
|
||
обрезающий текст без переноса вместо уменьшения кегля). */
|
||
.brand-headline { max-width: none; font-size: clamp(22px, 6.2vw, 34px); }
|
||
.brand-sub { max-width: none; }
|
||
.brand-stats { flex-wrap: wrap; }
|
||
.stat-glass { flex: 1 1 140px; min-width: 0; }
|
||
|
||
.form-panel {
|
||
width: 100%;
|
||
min-width: 0;
|
||
padding: var(--space-8) var(--space-6);
|
||
justify-content: flex-start;
|
||
}
|
||
.screen-block { max-width: 100%; }
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
/* Совсем узкий телефон (375px) — экономим отступы и убираем декоративный
|
||
круг: на компактном hero он ближе к тексту и уже не читается как акцент. */
|
||
.brand-panel { padding: var(--space-6) var(--space-4); }
|
||
.brand-panel::after { display: none; }
|
||
.brand-stats { gap: var(--space-3); }
|
||
.stat-glass { flex-basis: 100%; }
|
||
|
||
.form-panel { padding: var(--space-6) var(--space-4) var(--space-10); }
|
||
}
|