/*
 * Экраны входа, регистрации и восстановления пароля.
 *
 * Общий файл на все шесть экранов: у них одна раскладка (тёмная колонка с
 * лозунгом слева, форма справа), одна карточка, одни поля и одни кнопки.
 * Держать их врозь значит развести оформление при первой же правке.
 *
 * Правило то же, что и на лендинге: ни одного значения напрямую — только
 * `var(--tb-*)` из `tokens.css`.
 */

/* ========================================================================
   Основа
   ======================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0;
  background: var(--tb-color-surface);
  color: var(--tb-color-ink);
  font-family: var(--tb-font-sans);
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--tb-color-ink);
  text-decoration: none;
}

a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: var(--tb-border-hairline) solid currentColor;
  outline-offset: var(--tb-space-4);
}

/* ========================================================================
   Раскладка экрана
   ======================================================================== */

.auth {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1.1fr 1fr;
}

/* Левая колонка — место под фотографию студии. */
.auth__visual {
  position: relative;
  background: var(--tb-stripe-hero);
  min-height: 100vh;
}

.auth__overlay {
  position: absolute;
  inset: 0;
  background: var(--tb-overlay-auth);
}

.auth__note {
  position: absolute;
  top: var(--tb-space-24);
  left: var(--tb-space-24);
  font-family: var(--tb-font-mono);
  font-size: var(--tb-text-11);
  color: var(--tb-color-muted);
}

.auth__visual-body {
  position: relative;
  padding: var(--tb-space-64);
  max-width: var(--tb-auth-visual-width);
}

.auth__slogan {
  color: var(--tb-color-surface);
  font-size: var(--tb-text-38);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
  line-height: var(--tb-leading-headline);
}

/* Правая колонка — карточка с формой. */
.auth__panel {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--tb-space-48);
}

.auth__card {
  width: 100%;
  max-width: var(--tb-auth-form-width);
}

.auth__card--center {
  text-align: center;
}

.auth__logo {
  display: block;
  font-size: var(--tb-text-18);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
  margin-bottom: var(--tb-space-40);
}

/* На экране регистрации полей больше — логотип прижат ближе к заголовку. */
.auth__logo--tight {
  margin-bottom: var(--tb-space-32);
}

.auth__title {
  font-size: var(--tb-text-32);
  font-weight: var(--tb-weight-black);
  letter-spacing: var(--tb-tracking-tight);
  margin: 0 0 var(--tb-space-28);
}

.auth__title--with-lead { margin-bottom: var(--tb-space-12); }
.auth__title--28        { font-size: var(--tb-text-28); margin-bottom: var(--tb-space-24); }
.auth__title--30        { font-size: var(--tb-text-30); margin-bottom: var(--tb-space-12); }
.auth__title--register  { margin-bottom: var(--tb-space-24); }

.auth__lead {
  font-size: var(--tb-text-14);
  color: var(--tb-color-muted);
  line-height: var(--tb-leading-snug);
  margin: 0 0 var(--tb-space-28);
}

.auth__lead--roomy {
  line-height: var(--tb-leading-normal);
}

.auth__lead strong {
  color: var(--tb-color-ink);
}

/* ========================================================================
   Форма и поля
   ======================================================================== */

/* Обёртка формы — обычный блок: у сообщения об отказе, ссылки «Забыли
   пароль?» и кнопки свои отступы, и общий `gap` их бы перебил. */
.fields {
  display: flex;
  flex-direction: column;
  gap: var(--tb-space-16);
  margin-bottom: var(--tb-space-8);
}

/* На регистрации полей пять — шаг между ними меньше. */
.fields--dense {
  gap: var(--tb-space-14);
}

.field__label {
  display: block;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  margin-bottom: var(--tb-space-6);
}

.field__control {
  position: relative;
}

.field__input {
  width: 100%;
  padding: var(--tb-space-12) var(--tb-space-16);
  border: var(--tb-border-hairline) solid var(--tb-color-light);
  border-radius: var(--tb-radius-4);
  font-size: var(--tb-text-14);
  font-family: inherit;
  color: var(--tb-color-ink);
  background: var(--tb-color-surface);
}

.field__input::placeholder {
  color: var(--tb-color-dim);
}

/* Место под кнопку «Показать». */
.field__input--with-toggle {
  padding-right: var(--tb-space-44);
}

/*
 * Неверное поле. Класс ставится и своей проверкой, и по `details` из ответа
 * сервера — вид у обоих случаев один, потому что для человека это одно и то
 * же: вот поле, вот что с ним не так.
 */
.field--invalid .field__input {
  border-color: var(--tb-color-danger);
  background: var(--tb-color-danger-surface);
}

.field__error {
  font-size: var(--tb-text-12);
  color: var(--tb-color-danger);
  margin-top: var(--tb-space-6);
}

.field__error:empty {
  display: none;
}

.field__toggle {
  position: absolute;
  right: var(--tb-space-14);
  top: 50%;
  transform: translateY(-50%);
  font-family: inherit;
  font-size: var(--tb-text-12);
  color: var(--tb-color-muted);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
}

/* ========================================================================
   Надёжность пароля
   ======================================================================== */

.strength {
  display: flex;
  gap: var(--tb-space-4);
  margin-top: var(--tb-space-8);
}

.strength__bar {
  flex: 1;
  height: var(--tb-strength-bar-height);
  border-radius: var(--tb-radius-2);
  background: var(--tb-color-line);
}

.strength__bar--weak   { background: var(--tb-color-danger); }
.strength__bar--medium { background: var(--tb-color-warning); }
.strength__bar--strong { background: var(--tb-color-success); }

.strength__hint {
  font-size: var(--tb-text-11);
  color: var(--tb-color-muted);
  margin-top: var(--tb-space-6);
}

/* ========================================================================
   Согласие с политикой
   ======================================================================== */

.checkbox {
  display: flex;
  align-items: flex-start;
  gap: var(--tb-space-10);
  font-size: var(--tb-text-12);
  color: var(--tb-color-outline-dark);
  cursor: pointer;
  margin-top: var(--tb-space-12);
}

.checkbox__mark {
  width: var(--tb-checkbox-size);
  height: var(--tb-checkbox-size);
  flex-shrink: 0;
  accent-color: var(--tb-color-ink);
  margin: 0;
}

.checkbox a {
  font-weight: var(--tb-weight-semibold);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
}

/* Согласие — тоже поле: сервер отвечает по нему `409`, и отказ нужно показать. */
.field--invalid .checkbox {
  color: var(--tb-color-danger);
}

/* ========================================================================
   Сообщение об отказе
   ======================================================================== */

/*
 * Текст ошибки сервера целиком, над кнопкой. Показывается всегда, даже
 * когда сервер назвал и конкретные поля: `message` объясняет причину, а
 * подсветка поля — только указывает место.
 */
.alert {
  display: flex;
  gap: var(--tb-space-10);
  align-items: flex-start;
  background: var(--tb-color-danger-surface);
  border: var(--tb-border-hairline) solid var(--tb-color-danger-border);
  border-radius: var(--tb-radius-8);
  padding: var(--tb-space-12) var(--tb-space-14);
  margin-top: var(--tb-space-8);
}

.alert[hidden] {
  display: none;
}

.alert__icon {
  width: var(--tb-alert-icon-size);
  height: var(--tb-alert-icon-size);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-danger);
  color: var(--tb-color-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-11);
  font-weight: var(--tb-weight-bold);
  flex-shrink: 0;
}

.alert__text {
  font-size: var(--tb-text-13);
  color: var(--tb-color-danger-strong);
  line-height: var(--tb-leading-compact);
}

/* ========================================================================
   Кнопки и ссылки
   ======================================================================== */

.btn-primary {
  display: block;
  width: 100%;
  margin-top: var(--tb-space-20);
  padding: var(--tb-space-14);
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
  border: 0;
  border-radius: var(--tb-radius-pill);
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-semibold);
  font-family: inherit;
  text-align: center;
  cursor: pointer;
}

/* Пока запрос в пути, кнопка заперта — иначе повтор создаст вторую попытку. */
.btn-primary[disabled] {
  background: var(--tb-color-outline-dark);
  cursor: default;
}

/*
 * Вход через внешний сервис — вторая кнопка на экранах Auth 01 и Auth 02.
 *
 * В прототипе её нет: функция появилась после него. Поэтому оформление не
 * придумано заново, а снято с того, что на этих экранах уже есть: ширина,
 * скругление, размер и вес шрифта — как у «Войти», значения — те же токены.
 * Отличие ровно одно и оно смысловое: главное действие экрана залито
 * чёрным, второе — обведено. Фирменных цветов Яндекса здесь нет намеренно:
 * их нет в `tokens.css`, а заводить ради одной кнопки второй визуальный
 * язык — значит перестать узнавать экран.
 */
.btn-outline {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--tb-space-10);
  width: 100%;
  margin-top: var(--tb-space-12);
  padding: var(--tb-space-14);
  background: var(--tb-color-surface);
  color: var(--tb-color-ink);
  border: var(--tb-border-hairline) solid var(--tb-color-ink);
  border-radius: var(--tb-radius-pill);
  font-size: var(--tb-text-15);
  font-weight: var(--tb-weight-semibold);
  font-family: inherit;
  text-align: center;
  cursor: pointer;
}

.btn-outline[disabled] {
  color: var(--tb-color-muted);
  border-color: var(--tb-color-line);
  cursor: default;
}

/* Значок сервиса. Буква, а не картинка: логотип — чужой знак, и класть
   его в репозиторий без разрешения правообладателя незачем. */
.btn-outline__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--tb-alert-icon-size);
  height: var(--tb-alert-icon-size);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-ink);
  color: var(--tb-color-surface);
  font-size: var(--tb-text-12);
  font-weight: var(--tb-weight-bold);
}

.btn-outline[disabled] .btn-outline__mark {
  background: var(--tb-color-muted);
}

/* Разделитель «или» между формой и второй кнопкой. */
.auth__or {
  display: flex;
  align-items: center;
  gap: var(--tb-space-12);
  margin-top: var(--tb-space-20);
  font-size: var(--tb-text-12);
  color: var(--tb-color-dim);
}

.auth__or::before,
.auth__or::after {
  content: '';
  flex: 1;
  height: var(--tb-border-hairline);
  background: var(--tb-color-line);
}

/*
 * Первое нажатие кнопки заводит учётную запись, а согласие с политикой на
 * этом пути никто не отмечает флажком — значит, условие должно стоять
 * рядом с кнопкой: `users.privacy_version_id` фиксирует принятую редакцию
 * и в этом случае тоже.
 */
.auth__consent {
  margin-top: var(--tb-space-10);
  text-align: center;
  font-size: var(--tb-text-12);
  line-height: var(--tb-leading-compact);
  color: var(--tb-color-muted);
}

.auth__consent a {
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-outline-dark);
}

/*
 * Сообщение, а не отказ: экран восстановления пароля отвечает им на адрес,
 * у которого пароля нет вовсе. Красная рамка здесь была бы неправдой —
 * человек ничего не сделал неверно, ему просто нужна соседняя кнопка.
 */
.alert--info {
  background: var(--tb-color-surface-alt);
  border-color: var(--tb-color-line);
}

.alert--info .alert__icon {
  background: var(--tb-color-ink);
}

.alert--info .alert__text {
  color: var(--tb-color-ink);
}

.auth__forgot {
  text-align: right;
  margin-top: var(--tb-space-14);
}

.link-muted {
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-outline-dark);
}

.auth__aside {
  text-align: center;
  margin-top: var(--tb-space-20);
}

.auth__aside-text {
  font-size: var(--tb-text-13);
  color: var(--tb-color-muted);
}

.auth__aside a {
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
}

.auth__back {
  display: block;
  text-align: center;
  margin-top: var(--tb-space-32);
  padding-top: var(--tb-space-20);
  border-top: var(--tb-border-hairline) solid var(--tb-color-line);
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-outline-dark);
}

.auth__back--tight {
  margin-top: var(--tb-space-24);
  padding-top: var(--tb-space-16);
}

/* ========================================================================
   Значки состояний: «Проверьте почту» и «Пароль изменён»
   ======================================================================== */

.status-icon {
  width: var(--tb-status-icon);
  height: var(--tb-status-icon);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-surface-alt);
  margin: 0 auto var(--tb-space-24);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-22);
}

.status-icon--success {
  width: var(--tb-status-icon-lg);
  height: var(--tb-status-icon-lg);
  background: var(--tb-color-success-surface);
  color: var(--tb-color-success);
  font-size: var(--tb-text-28);
  font-weight: var(--tb-weight-black);
}

.resend {
  font-size: var(--tb-text-13);
  color: var(--tb-color-dim);
  margin-bottom: var(--tb-space-20);
}

/* Повторная отправка доступна — надпись становится кнопкой. */
.resend__button {
  font-family: inherit;
  font-size: var(--tb-text-13);
  font-weight: var(--tb-weight-semibold);
  color: var(--tb-color-ink);
  background: transparent;
  border: 0;
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
  padding: 0;
  cursor: pointer;
}

/* ========================================================================
   Ссылка устарела
   ======================================================================== */

.expired {
  background: var(--tb-color-danger-surface);
  border: var(--tb-border-hairline) solid var(--tb-color-danger-border);
  border-radius: var(--tb-radius-12);
  padding: var(--tb-space-28);
  text-align: center;
}

.expired__icon {
  width: var(--tb-status-icon-sm);
  height: var(--tb-status-icon-sm);
  border-radius: var(--tb-radius-circle);
  background: var(--tb-color-surface);
  margin: 0 auto var(--tb-space-16);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--tb-text-18);
  color: var(--tb-color-danger);
}

.expired__title {
  font-size: var(--tb-text-18);
  font-weight: var(--tb-weight-black);
  color: var(--tb-color-danger-strong);
  margin-bottom: var(--tb-space-8);
}

.expired__text {
  font-size: var(--tb-text-13);
  color: var(--tb-color-danger-text);
  line-height: var(--tb-leading-snug);
  margin: 0 0 var(--tb-space-20);
}

.expired__button {
  display: block;
  width: 100%;
  padding: var(--tb-space-12);
  background: var(--tb-color-danger);
  color: var(--tb-color-surface);
  border-radius: var(--tb-radius-pill);
  font-size: var(--tb-text-14);
  font-weight: var(--tb-weight-semibold);
  text-align: center;
}

/* ========================================================================
   Подсказка разработчику
   ======================================================================== */

/*
 * Писем сервис не отправляет — почта вынесена за рамки MVP. При
 * NODE_ENV=development ответ несёт `reset_token`, и без него пройти
 * восстановление до конца невозможно: ссылку взять неоткуда. В боевом
 * режиме поля в ответе нет, и блок не появляется вовсе.
 */
.dev-hint {
  margin-top: var(--tb-space-20);
  padding: var(--tb-space-12) var(--tb-space-14);
  border: var(--tb-border-hairline) solid var(--tb-color-line);
  border-radius: var(--tb-radius-8);
  font-size: var(--tb-text-12);
  color: var(--tb-color-muted);
  line-height: var(--tb-leading-snug);
  text-align: left;
}

.dev-hint[hidden] {
  display: none;
}

.dev-hint a {
  font-weight: var(--tb-weight-semibold);
  border-bottom: var(--tb-border-hairline) solid var(--tb-color-ink);
  word-break: break-all;
}

/* ========================================================================
   Узкий экран
   ======================================================================== */

/*
 * Две колонки — фотография и форма — на узком экране встают друг под друга.
 * Колонка с фотографией не убирается: это первое, что человек видит на
 * входе, и без неё экран входа перестаёт быть похожим сам на себя. Она
 * становится полосой над формой ровно такой высоты, чтобы слоган поместился.
 *
 * Точки перелома — в конце `tokens.css`.
 */

@media (max-width: 900px) {
  .auth {
    grid-template-columns: 1fr;
  }

  .auth__visual {
    min-height: 0;
  }

  .auth__visual-body {
    padding: var(--tb-space-56) var(--tb-space-32) var(--tb-space-40);
    max-width: none;
  }

  .auth__slogan {
    font-size: var(--tb-text-32);
  }

  .auth__panel {
    padding: var(--tb-space-40) var(--tb-space-32);
    align-items: flex-start;
  }
}

@media (max-width: 600px) {
  .auth__visual-body {
    padding: var(--tb-space-48) var(--tb-space-20) var(--tb-space-32);
  }

  .auth__slogan {
    font-size: var(--tb-text-28);
  }

  .auth__panel {
    padding: var(--tb-space-32) var(--tb-space-20);
  }

  .auth__title {
    font-size: var(--tb-text-28);
  }

  /* Кнопка формы — цель для пальца, а не тонкая полоска. */
  .btn-primary,
  .btn-outline {
    min-height: var(--tb-tap);
  }
}

