Files
vidconf/frontend/src/styles/auth.css
Max Ronzhin 35a1455645
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
refactor(auth): убрать строку «self-hosted» из брендовой панели
Копирайт целиком переехал в общий футер (решение оператора), в панели
строка больше не нужна. У `.brand-panel` осталось два потомка вместо трёх,
поэтому `.brand-copy` получил `margin-block: auto` — иначе
`justify-content: space-between` прижал бы текст к низу панели.
2026-07-27 01:53:27 +03:00

278 lines
12 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* VidConf — стили экранов 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); }
}