/* ZM Project — моушен-слой страницы входа.
   Кладётся ПОСЛЕ auth-canon.css и только на login.php: канон общий для
   login/register/request-access, а этот слой пока обкатывается на входе.

   Личность движения — Premium: без overshoot, длинные мягкие дуги.
   Три константы, из которых собрано всё остальное:
     signature easing  cubic-bezier(.4,0,.2,1)
     палитра длительностей  quick 160ms / standard 380ms / slow 620ms
     паттерн входа  подъём снизу + расфокус, всё с одной стороны
*/

:root{
  --e-sig:cubic-bezier(.4,0,.2,1);      /* 80% движений */
  --e-out:cubic-bezier(.16,1,.3,1);     /* выразительный вход тяжёлых блоков */
  --e-firm:cubic-bezier(.45,0,.55,1);   /* симметричный — для тряски ошибки */
  --t-quick:160ms;
  --t-std:380ms;
  --t-slow:620ms;
}

/* ─────────────────────────────────────────────────────────────
   AMBIENT — фон живёт
   Три ауры дрейфуют вразнобой и на разной скорости, поэтому
   рисунок не повторяется на глаз. Периоды длинные и взаимно
   непериодичные (19/23/31s), движение — sine-подобное, чтобы
   петля не «щёлкала» на стыке.
   ───────────────────────────────────────────────────────────── */

.auth-bg{
  /* Ауры переезжают в псевдоэлементы, здесь остаётся только базовая заливка */
  background:linear-gradient(180deg,var(--bg-1) 0%,var(--bg-0) 60%);
  overflow:hidden;
}
.auth-bg::before,
.auth-bg::after{
  content:"";position:absolute;inset:-25%;
  will-change:transform;
}
.auth-bg::before{
  background:
    radial-gradient(680px 460px at 22% 14%,rgba(139,92,246,.26),transparent 60%),
    radial-gradient(720px 480px at 84% 8%,rgba(56,189,248,.17),transparent 60%);
  animation:aura-a 23s ease-in-out infinite;
}
.auth-bg::after{
  background:radial-gradient(820px 620px at 58% 88%,rgba(52,211,153,.12),transparent 60%);
  animation:aura-b 31s ease-in-out infinite;
}
@keyframes aura-a{
  0%,100%{transform:translate3d(0,0,0) scale(1)}
  33%    {transform:translate3d(3.5%,-2.5%,0) scale(1.06)}
  66%    {transform:translate3d(-2.5%,2%,0) scale(.97)}
}
@keyframes aura-b{
  0%,100%{transform:translate3d(0,0,0) scale(1.04)}
  50%    {transform:translate3d(-4%,-3%,0) scale(.96)}
}

/* Зерно поверх фона — глушит бандинг (ступеньки) на больших градиентах */
.auth-shell::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ─────────────────────────────────────────────────────────────
   СТЕКЛО — карточка
   Логин относится к «тяжёлому» ярусу фроста: blur 24-40px.
   По краю ходит свет: conic-gradient в маске рисует ободок в 1px,
   и вращается — стекло ловит блик, а не просто лежит.
   ───────────────────────────────────────────────────────────── */

.auth-card{
  position:relative;
  backdrop-filter:blur(26px) saturate(165%);
  -webkit-backdrop-filter:blur(26px) saturate(165%);
  box-shadow:
    0 40px 90px rgba(2,6,23,.6),
    inset 0 1px 0 rgba(255,255,255,.09),
    inset 0 -1px 0 rgba(0,0,0,.18);
  animation:card-in var(--t-slow) var(--e-out) both;
}

/* Ободок света. mask вырезает середину, остаётся рамка в 1px.
   Крутится именно УГОЛ градиента, а не сам псевдоэлемент: rotate() развернул бы
   прямоугольник целиком, и его углы уехали бы далеко за карточку.
   Углы анимируются только через @property; где его нет — ободок просто
   останется неподвижным, это допустимая деградация. */
@property --rim{syntax:'<angle>';initial-value:0deg;inherits:false}

.auth-card::before{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  padding:1px;
  background:conic-gradient(from var(--rim),
    rgba(255,255,255,.5),rgba(167,139,250,.35) 25%,
    rgba(255,255,255,.06) 50%,rgba(56,189,248,.3) 75%,rgba(255,255,255,.5));
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask-composite:exclude;
  animation:rim-light 14s linear infinite;
  opacity:.9;
}
@keyframes rim-light{to{--rim:360deg}}

/* Зерно на самом стекле — тот же приём против бандинга, что и на фоне */
.auth-card::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  opacity:.035;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* Карточка — «герой», входит первой: поднимается и наводит резкость.
   Тень догоняет её к концу, поэтому приземление читается как касание. */
@keyframes card-in{
  from{
    opacity:0;transform:translate3d(0,22px,0) scale(.985);
    backdrop-filter:blur(0) saturate(100%);
    -webkit-backdrop-filter:blur(0) saturate(100%);
    box-shadow:0 0 0 rgba(2,6,23,0),inset 0 1px 0 rgba(255,255,255,0);
  }
  to{opacity:1;transform:none}
}

/* ─────────────────────────────────────────────────────────────
   СТАГГЕР — содержимое въезжает следом за карточкой
   Шаг 55ms, разброс задержек 80→470ms: держимся в бюджете 500ms,
   иначе форма начинает «собираться» на глазах и раздражает.
   Все элементы идут снизу — одно направление читается как один жест.
   ───────────────────────────────────────────────────────────── */

.auth-logo,.auth-head,.a-sep,.a-foot,.a-back,
form > *,
.auth-card > .a-actions{
  animation:rise var(--t-std) var(--e-sig) both;
}
@keyframes rise{
  from{opacity:0;transform:translate3d(0,10px,0)}
  to  {opacity:1;transform:none}
}

/* Скрытые служебные поля в потоке не участвуют: анимировать csrf-input незачем.
   Позицию в nth-child он всё равно занимает — это сдвигает форму на один шаг,
   что незаметно, зато счёт остаётся честным. */
form > input[type="hidden"]{animation:none}

.auth-logo{animation-delay:80ms}
.auth-head{animation-delay:130ms}

/* Стаггер идёт по ПРЯМЫМ детям формы, а не по .a-field: тогда двухколоночный
   .a-row (пароль + повтор в register) едет одним блоком, как его и читают,
   а не двумя половинками вразнобой. Шаг 45ms покрывает и логин с четырьмя
   элементами, и request-access с восемью, не вылезая за бюджет. */
form > *:nth-child(1),.auth-card > .a-actions{animation-delay:195ms}
form > *:nth-child(2){animation-delay:240ms}
form > *:nth-child(3){animation-delay:285ms}
form > *:nth-child(4){animation-delay:330ms}
form > *:nth-child(5){animation-delay:375ms}
form > *:nth-child(6){animation-delay:420ms}
form > *:nth-child(7){animation-delay:465ms}
form > *:nth-child(n+8){animation-delay:510ms}

.a-sep {animation-delay:430ms}
.a-foot{animation-delay:465ms}
.a-back{animation-delay:495ms}

/* Широкая карточка = длинная форма (register, request-access). Подвал обязан
   приезжать ПОСЛЕ последнего поля, иначе низ карточки собирается раньше
   середины и порядок сверху вниз ломается. */
.auth-card.wide .a-sep {animation-delay:545ms}
.auth-card.wide .a-foot{animation-delay:575ms}
.auth-card.wide .a-back{animation-delay:600ms}

/* Логотип: подсветка под ним разгорается уже после того, как он приехал */
.auth-logo img{
  animation:logo-glow 2.4s var(--e-sig) 340ms both;
}
@keyframes logo-glow{
  from{filter:drop-shadow(0 6px 18px rgba(139,92,246,0))}
  60% {filter:drop-shadow(0 6px 26px rgba(139,92,246,.7))}
  to  {filter:drop-shadow(0 6px 18px rgba(139,92,246,.45))}
}

/* Бейдж BETA дышит — самый тихий ambient-слой, амплитуда почти на пороге
   заметности. Задача — «страница живая», а не «смотри сюда». */
.auth-beta{animation:beta-breath 4.5s ease-in-out 1.2s infinite}
@keyframes beta-breath{
  0%,100%{opacity:1}
  50%    {opacity:.72}
}

/* ─────────────────────────────────────────────────────────────
   ПОЛЯ — фокус
   Микрофидбек, поэтому quick: реакция должна казаться мгновенной.
   ───────────────────────────────────────────────────────────── */

.a-field{position:relative}

.a-input,.a-select{
  transition:border-color var(--t-quick) var(--e-sig),
             box-shadow var(--t-quick) var(--e-sig),
             background var(--t-quick) var(--e-sig);
}
.a-input:hover:not(:focus){border-color:rgba(255,255,255,.2)}
.a-input:focus,.a-select:focus{background:rgba(7,11,20,.78)}

/* Лейбл загорается вместе с полем — связь «подпись ↔ поле» становится явной */
.a-label{transition:color var(--t-quick) var(--e-sig)}
.a-field:focus-within .a-label{color:rgba(196,181,253,.95)}

/* Линия под активным полем растёт из центра к краям */
.a-field::after{
  content:"";position:absolute;left:50%;right:50%;bottom:0;height:1px;
  background:linear-gradient(90deg,transparent,var(--violet),transparent);
  transition:left var(--t-std) var(--e-sig),right var(--t-std) var(--e-sig),
             opacity var(--t-quick) var(--e-sig);
  opacity:0;
}
.a-field:focus-within::after{left:8%;right:8%;opacity:.85}

/* Поле кода 2FA — цифры «доезжают» на место при появлении формы */
.a-input.big{animation:code-settle 560ms var(--e-out) 200ms both}
@keyframes code-settle{
  from{opacity:0;transform:translate3d(0,8px,0);letter-spacing:.9em}
  to  {opacity:1;transform:none;letter-spacing:.4em}
}

/* ─────────────────────────────────────────────────────────────
   КНОПКА
   Нажатие — 120-180ms, отпускание чуть длиннее. Overshoot нулевой:
   личность Premium, кнопка не должна пружинить.
   ───────────────────────────────────────────────────────────── */

.a-btn{
  position:relative;overflow:hidden;
  transition:transform var(--t-quick) var(--e-sig),
             box-shadow var(--t-std) var(--e-sig),
             background var(--t-std) var(--e-sig),
             border-color var(--t-std) var(--e-sig);
}
.a-btn:active{transform:translateY(0) scale(.985);transition-duration:90ms}

/* Иконка уезжает вперёд на наведении — вторичное движение, оно и подсказывает
   направление действия. Кнопка возврата, наоборот, тянет влево. */
.a-btn i{transition:transform var(--t-std) var(--e-sig)}
.a-btn:hover i{transform:translateX(3px)}

/* Блик проходит по кнопке на наведении */
.a-btn-primary::after{
  content:"";position:absolute;top:0;bottom:0;left:-60%;width:45%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.42),transparent);
  transform:skewX(-18deg);pointer-events:none;opacity:0;
}
.a-btn-primary:hover::after{animation:sheen 720ms var(--e-sig) both}
@keyframes sheen{
  from{left:-60%;opacity:.9}
  to  {left:115%;opacity:0}
}

/* Отправка формы: кнопка гасит подпись и крутит спиннер.
   Класс вешает JS внизу login.php — без него кнопка просто не подаёт
   признаков жизни, пока браузер ждёт ответ POST. */
.a-btn.is-loading{pointer-events:none;color:transparent}
.a-btn.is-loading i{opacity:0}
.a-btn.is-loading::before{
  content:"";position:absolute;top:50%;left:50%;width:19px;height:19px;margin:-10px 0 0 -10px;
  border:2px solid rgba(17,7,31,.32);border-top-color:#11071f;border-radius:50%;
  animation:spin .62s linear infinite;
}
@keyframes spin{to{transform:rotate(1turn)}}

/* ─────────────────────────────────────────────────────────────
   ЧЕКБОКС И ССЫЛКИ
   ───────────────────────────────────────────────────────────── */

.a-check{transition:color var(--t-quick) var(--e-sig)}
.a-check:hover{color:var(--text)}

/* color-scheme переключает нативную отрисовку квадратика на тёмную: без него
   неотмеченный чекбокс остаётся белым пятном на стекле (accent-color красит
   только отмеченное состояние). */
.a-check input{color-scheme:dark;transition:transform var(--t-quick) var(--e-sig)}
.a-check:hover input{transform:scale(1.08)}
.a-check input:checked{animation:check-pop 260ms var(--e-sig)}
@keyframes check-pop{
  0%  {transform:scale(.82)}
  60% {transform:scale(1.12)}
  100%{transform:scale(1)}
}

.a-foot a,.a-back{transition:color var(--t-quick) var(--e-sig)}

/* Подчёркивание в подвале растёт слева направо, а не появляется целиком */
.a-foot a{position:relative;text-decoration:none}
.a-foot a::after{
  content:"";position:absolute;left:0;right:100%;bottom:-2px;height:1px;
  background:currentColor;transition:right var(--t-std) var(--e-sig);
}
.a-foot a:hover{text-decoration:none}
.a-foot a:hover::after{right:0}

.a-back:hover{transform:translateX(-3px)}
.a-back{transition:color var(--t-quick) var(--e-sig),transform var(--t-quick) var(--e-sig)}

/* ─────────────────────────────────────────────────────────────
   СОСТОЯНИЯ
   Ошибка: 3 колебания по ±9px, симметричное easing, нулевой overshoot —
   отказ должен читаться твёрдо, а не игриво. Вход и тряска слиты в одну
   анимацию: обе правят transform, двумя правилами они бы конфликтовали.
   ───────────────────────────────────────────────────────────── */

.a-alert{animation:alert-in 700ms var(--e-firm) 140ms both}
.a-alert.err{animation-name:alert-err}

@keyframes alert-in{
  from{opacity:0;transform:translate3d(0,-6px,0)}
  to  {opacity:1;transform:none}
}
@keyframes alert-err{
  0%  {opacity:0;transform:translate3d(0,-6px,0)}
  40% {opacity:1;transform:translate3d(0,0,0)}
  52% {transform:translate3d(-9px,0,0)}
  64% {transform:translate3d(8px,0,0)}
  76% {transform:translate3d(-5px,0,0)}
  88% {transform:translate3d(3px,0,0)}
  100%{transform:none}
}
.a-alert.err i{animation:err-icon 520ms var(--e-sig) 300ms both}
@keyframes err-icon{
  0%  {transform:scale(.7);opacity:0}
  55% {transform:scale(1.12);opacity:1}
  100%{transform:scale(1)}
}

/* ─────────────────────────────────────────────────────────────
   ДОСТУПНОСТЬ И ЗАПАСНЫЕ ПУТИ
   Всё выше — украшение. Ни один из этих режимов не должен ломать вход.
   ───────────────────────────────────────────────────────────── */

/* Отключённое движение: контент показываем сразу, вся петля стоит.
   Оставляем только смену цвета — она не вестибулярная. */
@media (prefers-reduced-motion:reduce){
  .auth-bg::before,.auth-bg::after,.auth-card,.auth-card::before,
  .auth-logo,.auth-head,.a-sep,.a-foot,.a-back,form > *,.auth-card > .a-actions,
  .auth-logo img,.auth-beta,.a-input.big,.a-alert,.a-alert.err i,
  .a-btn-primary:hover::after{
    animation:none !important;
    opacity:1;transform:none;
  }
  .a-field::after{transition:opacity var(--t-quick) linear}
  .a-btn:hover i,.a-back:hover{transform:none}
  .a-btn.is-loading::before{animation:spin 1.1s linear infinite} /* спиннер нужен: он статус, а не декор */
}

/* Пониженная прозрачность: стекло становится плотной панелью,
   зерно и бегающий ободок убираем — они читаются как шум. */
@media (prefers-reduced-transparency:reduce){
  .auth-card{
    background:#101a2e;
    backdrop-filter:none;-webkit-backdrop-filter:none;
  }
  .auth-card::before,.auth-card::after{display:none}
  .auth-shell::before{display:none}
}

/* Нет backdrop-filter — карточка должна остаться читаемой сама по себе */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .auth-card{background:rgba(13,22,38,.93)}
}

/* Тесный экран: те же движения меньшей амплитудой, ободок гасим —
   на узкой карточке вращающийся блик выглядит суетливо. */
@media (max-width:440px){
  @keyframes card-in{
    from{opacity:0;transform:translate3d(0,14px,0)}
    to  {opacity:1;transform:none}
  }
  .auth-card::before{animation-duration:22s;opacity:.6}
  .auth-bg::before,.auth-bg::after{animation:none}
}
