/**
 * Наши стили поверх вёрстки.
 *
 * Отдельным файлом, а не правкой screen.css: следующая выгрузка от
 * верстальщика перезапишет его файлы целиком, а этот — нет.
 *
 * Здесь только то, чего в макете нет вовсе. Показ ошибок формы — как раз такой
 * случай: у полей есть состояния :focus и :disabled, а «поле заполнено
 * неверно» не нарисовано.
 */

.cf_error {
    display: none;
    margin-top: 8px;
    font: 16px 'Gilroy', sans-serif;
    line-height: 1.25;
    color: #E02B2B;
}

.cf_error.is_visible {
    display: block;
}

.cf_error_common {
    margin-top: 20px;
    text-align: center;
}

/* Красная рамка перебивает и обычное состояние поля, и :focus: пока значение
   не исправлено, поле остаётся отмеченным. Работает это за счёт порядка
   подключения — site.css идёт после screen.css. */
.cf_input.has_error {
    border: 1px solid #E02B2B;
}

/* Кнопка на время запроса перестаёт нажиматься. Повторный клик иначе
   отправляет вторую регистрацию, и вторая приходит на занятый email. */
.button.is_sending {
    opacity: 0.6;
    pointer-events: none;
}

/* Крутящееся кольцо на время запроса.
   
   Погашенной кнопки мало: за ней стоит чужая сеть — сверка капчи, звонок
   оператору, argon2 на сервере, — и полсекунды тишины человек читает как
   «не нажалось». Кольцо говорит, что нажалось и идёт.

   Псевдоэлементом, а не разметкой: состояние занятости у всех четырёх
   действий выражено одним классом, и заводить ради кольца четыре одинаковых
   span значило бы разложить одно правило по четырём островам. Цвет —
   currentColor: кнопка белым по синему, пункт меню — наоборот, и кольцо
   подхватывает то, что задано вокруг.

   Надпись при этом остаётся: «Получить код звонком» без текста — это кнопка,
   про которую непонятно, что она делала. */
@keyframes is_sending_spin {
    to {
        transform: rotate(360deg);
    }
}

.button.is_sending::after,
.code_link a[aria-busy='true']::after,
li a[role='button'].is_sending::after,
.verification_item label[aria-busy='true']::after {
    content: '';
    display: inline-block;
    vertical-align: middle;
    flex: none;
    width: 16px;
    height: 16px;
    margin-left: 10px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: is_sending_spin 0.7s linear infinite;
}

/* Тем, кто просил меньше движения, кольцо остаётся, но крутится медленно:
   застывшее читается как украшение, а не как «идёт запрос». */
@media (prefers-reduced-motion: reduce) {
    .button.is_sending::after,
    .code_link a[aria-busy='true']::after,
    li a[role='button'].is_sending::after,
    .verification_item label[aria-busy='true']::after {
        animation-duration: 3s;
    }
}

/* Блок капчи. Внутри рисует чужой скрипт — своей вёрстки у него в макете нет
   (там на этом месте была картинка без всякой проверки), поэтому здесь только
   отступы и выравнивание по остальной форме. */
.contacts_form_captcha {
    margin-top: 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* Невидимая капча (повторная отправка кода) галочки не рисует, но место в
   потоке всё равно занимает: скрипт ставит в контейнер свой элемент с
   зарезервированным размером. Поэтому у блока снимается отступ, а сам
   контейнер выносится из потока — нулевым размером и position: fixed.

   Не `display: none` и не `visibility: hidden`: сервис вправе показать
   подозрительной сессии окно с заданием, а погашенный виджет его не покажет —
   человек упрётся в проверку, которую нельзя пройти. Точка привязки — центр
   экрана: если окно задания позиционируется относительно контейнера, оно
   окажется посреди страницы, а не в её углу. */
.contacts_form_captcha.is_invisible {
    margin-top: 0;
}

.captcha_mount_hidden {
    position: fixed;
    left: 50%;
    top: 50%;
    width: 0;
    height: 0;
}

/* В макете кнопка формы — <a>, и стили написаны под ссылку. У нас это
   <button type="submit">: он отправляет форму, доступен с клавиатуры и умеет
   disabled. Браузерные умолчания button макет не учитывает, поэтому снимаем
   их здесь — сама вёрстка при этом остаётся нетронутой. */
button.button {
    appearance: none;
    border: none;
    font-family: 'Gilroy', sans-serif;
    cursor: pointer;
}

button.button:disabled {
    cursor: default;
}

/* «Выход из ЛК» — остров: в макете все пункты меню были <a> без адреса, то
   есть некликабельными. Этот кликается, поэтому ему нужен курсор и видимая
   рамка фокуса — с клавиатуры пункт нажимается наравне с мышью. */
.left_menu_list li a[role='button'],
.lk_menu_list li a[role='button'] {
    cursor: pointer;
}

/* Отказ выхода. Сессия в этот момент жива, и промолчать нельзя: человек ушёл
   бы от экрана с чувством, что вышел. */
.lk_exit_error {
    display: block;
    margin-top: 8px;
    font: 14px 'Gilroy', sans-serif;
    line-height: 1.25;
    color: #E02B2B;
}

/* Ссылка «Отправить код в смс». В макете это <a> без адреса — то есть
   некликабельная надпись; у нас она нажимается и мышью, и с клавиатуры,
   поэтому ей нужен курсор. */
.code_link a[role='button'] {
    cursor: pointer;
}

/* Ссылка повторной отправки стоит под виджетом капчи: решить проверку нужно
   раньше, чем нажимать. Своего верхнего отступа у .code_link в макете нет —
   там она шла за подсказкой, у которой отступ свой. */
.contacts_form_captcha + .code_link {
    margin-top: 20px;
}

/* Пока запрос в пути, ссылка заперта: второй клик стоил бы второго звонка или
   второго сообщения. На время интервала повторной отправки её не запирают, а
   убирают со страницы — нажимать в этот момент нечего вовсе, и на её месте
   стоит отсчёт. */
.code_link a[aria-disabled='true'] {
    color: #8A97A5;
    cursor: default;
    pointer-events: none;
}

/* Номер на втором шаге входа по телефону: он уже принят, поэтому показывается
   строкой, а не полем. Своей вёрстки у этой строки в макете нет — там оба поля
   стояли на форме сразу, — но и своей типографики у неё быть не должно: размер,
   цвет и выравнивание она берёт у подсказок формы (.code_text), а ссылка
   «Изменить» — у ссылок без адреса (.code_link a). Здесь остаётся только то,
   чего в тех классах нет: воздух до поля кода и отбивка ссылки от номера. */
.code_phone {
    margin-bottom: 25px;
}

/* Полужирный .code_text span — это про сам номер: ссылка рядом с ним такая же,
   как «Отправить код в смс» ниже, и выделять её нечем. */
.code_phone .code_link {
    margin-left: 10px;
    font-weight: 400;
}

/* Реквизиты, стоящие в договоре: название, ИНН, регистрационный номер и
   юридический адрес. Правит их служба поддержки, а не форма.

   readonly, а не disabled: disabled-поле браузер не отправляет вовсе, а форма
   профиля присылает все поля целиком и заменяет ими карточку — пропавшее
   значение стёрло бы реквизит.

   Что поле заперто, видно без единого слова: серая заливка неактивного поля из
   макета (.cf_input:disabled), приглушённая подпись и замок справа. Подписи
   под группой нет намеренно — объяснение, повторённое у каждой группы, читает
   один человек из ста, а место занимает у всех.

   Замок нарисован здесь же, data-URI: в наборе вёрстки такого значка нет, а
   класть свой в её каталог незачем — следующая выгрузка перезапишет его вместе
   с остальными. Цвет вшит в разметку значка (#8A97A5, тот же, которым
   приглушены неактивные ссылки): currentColor в background-image не работает.

   Рамка фокуса остаётся синей. Поле фокусируется, чтобы значение можно было
   выделить и скопировать, и рамка показывает, где стоит курсор; заливка с
   замком под ней никуда не деваются, так что запертым поле выглядеть не
   перестаёт. Приглушить её значило бы отнять единственный признак фокуса у
   того, кто ходит по форме с клавиатуры. */
.cf_input[readonly] {
    cursor: default;
    border: 1px solid rgba(37, 30, 74, 0.2);
    background-color: rgba(0, 0, 0, 0.03);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%238A97A5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2.75' y='7' width='10.5' height='6.5' rx='1.5'/%3E%3Cpath d='M5.5 7V4.75a2.5 2.5 0 0 1 5 0V7'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 20px center;
    /* 20 (отступ поля) + 16 (замок) + 10 (воздух): длинное значение не должно
       заезжать под значок. */
    padding-right: 46px;
}

.cf_input[readonly]::placeholder {
    color: #8A97A5;
}

/* Подпись поля пропускает щелчок к полю под собой. Вёрстка фокусирует поле по
   щелчку на подписи из main.js, но навешивает обработчик один раз при загрузке
   страницы, а поля островов появляются позже — и щелчок по «Дате выдачи»
   уходил в никуда. Прозрачная для щелчка подпись работает без скрипта и для
   любых полей, когда бы они ни появились. */
.input_moving_text > span {
    pointer-events: none;
}

/* Плавающая подпись запертого поля приглушена — тем же серым, что и замок. */
.input_moving_text .cf_input[readonly] + span {
    color: #8A97A5;
}

/* Пока подпись не всплыла, она лежит внутри поля, и белая заливка «таблетки»
   оказалась бы светлым пятном на сером. Всплыв, она перебивает рамку и белая
   ей снова нужна — поэтому правило и висит на неактивном состоянии. */
.input_moving_text:not(.active) .cf_input[readonly] + span {
    background: transparent;
}

/* Группа «Учётная запись»: поля и кнопки берутся у макета целиком —
   `lk_mi_item` + `input_moving_text` у полей, `button save_btn` у кнопок.
   Здесь остаётся только то, чего в макете нет вовсе.

   Каждый реквизит — маленькая форма: строка полей, под ней строка с кнопкой.
   Рядом с полем кнопка не ставится: `save_btn` несёт `margin-top: 20px`,
   рассчитанный на положение под формой, и в одной строке с полем всегда
   оказывается на двадцать пикселей ниже него. Отсюда и эта строка: отступ
   слева повторяет отступ ячеек (`lk_mi_item`), чтобы кнопка встала под левым
   краем поля, а не под краем строки.

   Действий в строке бывает два — кнопка и «Отмена», — и вертикально они
   выравниваются по кнопке. */
/* Кнопка вёрстки несёт `margin-top: 20px` — она нарисована стоять под формой, —
   и в ячейке сетки оказалась бы на двадцать пикселей ниже своего ряда. Отступ
   между строками даёт сама строка (`lk_mi_line`), поэтому здесь он снимается.

   Ширина у неё 285px под одну кнопку на всю форму; у нас их несколько и стоят
   они рядом с полями, поэтому ширину считает содержимое. */
.lk_account_btn {
    width: auto;
    margin-top: 0;
    padding: 0 28px;
}

/* Отказ от действия. В макете такого органа управления нет — там под формой
   стояла одна кнопка и отменять было нечего, — поэтому он выглядит ссылкой:
   синим и без рамки. Кнопкой, а не `<a>`: он не ведёт по адресу, и с
   клавиатуры обязан нажиматься сам, без роли и обработчика клавиш.

   Отступ сверху и высота — те же, что у кнопки рядом: иначе «Отмена» встала бы
   по верхнему краю строки, а кнопка на двадцать пикселей ниже. */
.lk_account_cancel {
    appearance: none;
    border: none;
    background: none;
    padding: 0;
    height: 50px;
    font: 18px 'Gilroy', sans-serif;
    color: #3261EC;
    cursor: pointer;
}

.lk_account_cancel:disabled {
    color: #8A97A5;
    cursor: default;
}

@media (max-width: 767px) {
    .lk_account_cancel {
        height: 40px;
        font-size: 14px;
    }
}

/* Поле пароля в профиле. Показывать в нём нечего — в базе лежит хеш, — и
   правится пароль кнопкой рядом, а не вводом сюда: смена требует текущего
   пароля и повтора.

   readonly здесь означает «не сюда», а не «меняется через службу поддержки»,
   поэтому замок с поля снимается: рядом стоит кнопка, которая как раз и
   меняет, и замок противоречил бы ей. */
.cf_input[readonly].lk_account_secret {
    background-image: none;
    padding-right: 20px;
}

/* Подсказки в профиле берут размер и цвет у подсказок формы входа
   (`.code_text`), но не их выравнивание: там форма узкая и стоит по центру
   страницы, а здесь текст относится к полям слева от него. Центрированный, он
   читался бы как подпись ко всей группе, а не к своим полям. */
.lk_mi_item .code_text,
.lk_mi_item .code_link {
    text-align: left;
}

/* Пустая ячейка-заполнитель: держит кнопку под своим полем на широком экране.
   На узком вёрстка растягивает ячейки на всю ширину и складывает их столбиком —
   заполнитель превратился бы в пустую строку с отступом. */
@media (max-width: 767px) {
    .lk_account_gap {
        display: none;
    }

    /* Подсказки в узкой колонке места не экономят: на телефоне они занимают
       всю ширину наравне с полями. */
    .lk_mi_item.lk_mi_item_w3 {
        width: 100%;
    }
}

/* Модальное окно профиля.

   Вёрстка рисует коробку (`modal_w2`) и прячет её (`.modal { display: none }`),
   а показывает fancybox. Здесь fancybox не участвует — он двигает узлы окна по
   документу, а внутри живёт React, — поэтому подложка и показ коробки наши. */
/* Слой окна — выше шапки вёрстки.

   Шапка приклеена (`position: sticky`) и стоит на z-index 8900, а окно стояло
   на 100: пока окна были короткие, они целиком помещались ниже шапки, и никто
   этого не замечал. Форма нового задания выше экрана — и её заголовок оказался
   за шапкой, то есть окно выглядело обрезанным сверху. Девять тысяч, а не
   «побольше»: это первое число над всем, что расставила вёрстка. */
.lk_modal_overlay {
    position: fixed;
    inset: 0;
    z-index: 9000;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 40px 20px;
    overflow-y: auto;
    background: rgba(26, 26, 26, 0.6);
}

/* Окно согласия — над всем, включая окна fancybox. Его спрашивают и изнутри
   них (заявка на вывод), а контейнер fancybox стоит на z-index 999929999999:
   браузер урезает такое число до наибольшего допустимого, 2147483647. Здесь
   стоит оно же, и при равенстве выше встаёт тот, кто позже в документе, — а
   окно согласия вставляется в body в момент вопроса, то есть после. */
.lk_modal_overlay.lk_modal_overlay_confirm {
    z-index: 2147483647;
}

.modal.lk_modal {
    display: block;
    position: relative;
    max-width: 100%;
    margin: auto;
}

/* Крестик. В макете его рисует fancybox своей кнопкой, поэтому здесь он свой —
   двумя линиями через псевдоэлементы, чтобы не заводить ещё один файл значка. */
.lk_modal_close {
    appearance: none;
    border: none;
    background: none;
    position: absolute;
    top: 16px;
    right: 16px;
    width: 32px;
    height: 32px;
    padding: 0;
    cursor: pointer;
}

.lk_modal_close::before,
.lk_modal_close::after {
    content: '';
    position: absolute;
    left: 6px;
    top: 15px;
    width: 20px;
    height: 2px;
    background: #8A97A5;
}

.lk_modal_close::before {
    transform: rotate(45deg);
}

.lk_modal_close::after {
    transform: rotate(-45deg);
}

/* Поля внутри окна идут в столбик: коробка узкая, и сетка формы профиля в ней
   не нужна. */
.lk_modal .lk_mi_line {
    margin-left: 0;
    margin-right: 0;
}

.lk_modal .lk_mi_item {
    width: 100%;
    padding: 0;
}

.lk_modal .lk_mi_item + .lk_mi_item {
    margin-top: 20px;
}

.lk_modal .code_text {
    text-align: center;
}

@media (max-width: 767px) {
    .lk_modal_overlay {
        padding: 20px 10px;
    }

    .modal.lk_modal {
        padding: 40px 20px 24px;
    }
}

/* Кнопка и отказ внизу модального окна. */
.lk_modal_actions {
    margin-top: 30px;
    gap: 24px;
}

@media (max-width: 767px) {
    .lk_modal_actions {
        gap: 16px;
    }
}

/* Плавающая подпись у запертого поля.

   «Таблетка» под подписью белая — она затем и есть, чтобы разрывать рамку
   поля, — но заливка запертого поля серая, и белое пятно читается как дырка в
   ней. Цвет подписи поэтому равен заливке поля, сплющенной по белому фону
   страницы: rgba(0,0,0,0.03) поверх белого даёт #F7F7F7. Над полем такая
   таблетка стоит на белом и почти не видна, а рамку разрывает по-прежнему. */
.input_moving_text .cf_input[readonly] + span {
    background: #F7F7F7;
}

/* Строки группы «Учётная запись» стоят просторнее, чем строки формы вёрстки.

   У вёрстки между строками 20px, и этого хватает там, где строки одинаковы. У
   нас под полями стоят то ссылка «Изменить», то кнопка, а плавающая подпись
   следующей строки выступает вверх на десять пикселей — и упирается в поле над
   собой. Двадцать пикселей здесь превращаются в десять. */
.lk_account .lk_mi_line + .lk_mi_line {
    margin-top: 30px;
}

/* Имя, рассказ о себе и фотография — верхний блок группы.

   Слева столбиком поля и кнопка, справа фотография. В макете рассказ с
   фотографией лежали отдельным блоком внизу формы: фотография во всю четверть
   строки, поле рассказа в три четверти и высотой с фотографию — под двести
   пикселей. За реквизитами организации этот блок читался как её описание, а
   поле такой высоты приглашало писать сочинение на странице, куда приходят
   смотреть.

   Левая колонка — половина строки, ровно та же, что занимают почта и телефон
   ниже: так поля стоят в одной вертикали, а не ступеньками. */
.lk_account_main .lk_about,
.lk_account_main .lk_account_actions {
    margin-top: 20px;
}

/* Поля столбца — фамилия, имя, отчество — друг под другом с тем же шагом. Через
   «~», а не «+»: под полем с отказом стоит строка ошибки, и следующее поле
   соседом ему уже не приходится. */
.lk_account_main .input_moving_text ~ .input_moving_text {
    margin-top: 20px;
}

/* Два действия в ряд: «Сохранить» и «Сменить пароль». Ширина кнопки вёрстки
   (285px) рассчитана на одну кнопку под формой — вдвоём они не помещаются в
   колонку, поэтому ширину им считает содержимое. */
.lk_account_actions {
    gap: 20px;
}

/* Рассказ о себе — такое же поле, как остальные на форме.

   Вёрстка рисует его иначе (`.lk_pole`): растянутым по высоте соседней
   фотографии и без подписи, потому что в макете он стоял отдельным блоком с
   заголовком над ним. Здесь он в одном столбце с именем, и отличаться ему не
   от чего — отсюда та же рамка, тот же шрифт и плавающая подпись.

   Плавающую подпись вёрстка умеет только для `input` (`.input_moving_text
   input:focus + span`), поэтому подсветка на фокусе добирается здесь. Всплывшей
   подпись стоит всегда: поле высокое, и лежащая внутри она накрывала бы первую
   строку текста. */
.lk_about_text {
    width: 100%;
    height: 110px;
    /* Поля кабинета вёрстка скругляет сильнее прочих (`.lk_block .cf_input`), а
       поле рассказа осталось при общем радиусе `.lk_pole` — рядом с именем это
       и было единственным, чем они отличались. */
    border-radius: 10px;
    font: 20px 'Gilroy', sans-serif;
    padding: 14px 20px;
}

.lk_about_text:focus {
    border: 1px solid #3261EC;
}

/* Подпись поля рассказа отбита от текста: у однострочного поля она стоит на
   рамке, а здесь под ней сразу начинается текст. */
.lk_about .lk_pole {
    padding-top: 18px;
}

/* Фотография занимает свою ячейку, но не растёт бесконечно: в четверти широкой
   строки она была бы почти в три сотни пикселей. */
/* Ячейка фотографии сжимается по содержимому: в четверти широкой строки
   фотография занимала бы меньше половины ячейки, а остаток превращался в
   пустую полосу между ней и полями. */
.lk_account_photo {
    flex: 0 0 auto;
    width: auto;
}

.lk_about_photo {
    position: relative;
    width: 180px;
    aspect-ratio: 1;
}

.lk_about_photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 5px;
}

/* Выбор файла: настоящий input внутри label, а не кнопка, зовущая click().
   Label открывает окно выбора и щелчком, и с клавиатуры, и делает это
   средствами браузера. Сам input поэтому не прячется display: none — так он
   выпал бы из порядка обхода вместе с возможностью до него дойти, — а
   уводится за пределы видимого. */
.lk_about_photo_pick {
    display: block;
    position: relative;
    width: 100%;
    height: 100%;
    cursor: pointer;
}

.lk_about_photo_input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    /* Прямо под ячейкой, а не за краем экрана: окно выбора файла браузер
       привязывает к положению элемента, и уведённый в -9999px input открывал
       бы его в углу. */
    inset: 0;
}

/* Подпись поверх фотографии. По наведению и по фокусу: второе обязательно —
   идущий по форме с клавиатуры иначе не увидит, что здесь что-то нажимается. */
.lk_about_photo_hint {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 8px 10px;
    border-radius: 0 0 5px 5px;
    background: rgba(26, 26, 26, 0.6);
    color: #fff;
    font: 14px 'Gilroy', sans-serif;
    line-height: 1.2;
    text-align: center;
    opacity: 0;
    transition: opacity 0.15s;
}

.lk_about_photo:hover .lk_about_photo_hint,
.lk_about_photo_input:focus-visible ~ .lk_about_photo_hint {
    opacity: 1;
}

/* Рамка фокуса рисуется на всей ячейке: сам input размером в пиксель, и его
   собственное кольцо было бы точкой в углу фотографии. */
.lk_about_photo_input:focus-visible ~ img,
.lk_about_photo_input:focus-visible ~ .lk_about_photo_empty {
    outline: 2px solid #2F80ED;
    outline-offset: 2px;
}

/* Пустая ячейка. В вёрстке её нет вовсе — в макете на этом месте всегда стоит
   фотография, — а показывать чужое лицо вместо своего нельзя. Поэтому вид у
   неё свой: пунктирная рамка с приглашением выбрать файл. */
.lk_about_photo_empty {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    padding: 10px;
    border: 1px dashed #C9D1D9;
    border-radius: 5px;
    background: rgba(0, 0, 0, 0.03);
    color: #8A97A5;
    font: 14px 'Gilroy', sans-serif;
    line-height: 1.25;
    text-align: center;
}

/* Пока файл уезжает, ячейка гаснет: у неё нет ни кнопки, ни надписи, на
   которой можно было бы показать кольцо занятости, а несколько секунд тишины
   после выбора файла читаются как «не сработало». */
.lk_about_photo[aria-busy='true'] {
    opacity: 0.6;
    pointer-events: none;
}

/* Отказ показывается под ячейкой, а не поверх фотографии: текст у него в
   несколько слов («файл больше 5 МиБ»), и внутри квадрата 180×180 он занял бы
   собой всю картинку. */
.lk_about_photo_error {
    position: absolute;
    top: 100%;
    left: 0;
    width: 180px;
    margin-top: 6px;
    font-size: 14px;
}

/* Крестик «убрать фотографию» из вёрстки появляется по наведению на ячейку;
   ячейка теперь общая с полем рассказа, поэтому наведение считается по самой
   фотографии.

   Кнопка, а не ссылка, как в макете: она совершает действие, а не ведёт
   куда-то, и с клавиатуры до неё надо доходить. Умолчания кнопки поэтому
   снимаются здесь же. */
.lk_about_photo .lk_mi_item_del_img {
    appearance: none;
    border: none;
    cursor: pointer;
    top: 8px;
    right: 8px;
    width: 28px;
    height: 28px;
    background-size: 28px 28px;
}

.lk_about_photo:hover .lk_mi_item_del_img,
.lk_about_photo .lk_mi_item_del_img:focus-visible {
    opacity: 1;
}

@media (max-width: 767px) {
    .lk_about_text {
        height: 90px;
        font-size: 16px;
        padding: 12px 15px;
    }

    .lk_about_photo {
        width: 120px;
    }

    /* Ширина сообщения об отказе идёт за ячейкой: она задана числом, потому
       что ячейка позиционирует его absolute и от родителя ширину он не
       возьмёт. */
    .lk_about_photo_error {
        width: 120px;
    }

    .lk_about_photo_empty,
    .lk_about_photo_hint {
        font-size: 12px;
    }
}

/* Строки группы «Учётная запись» стоят просторнее, чем строки формы вёрстки.

   У вёрстки между строками 20px, и этого хватает там, где строки одинаковы. У
   нас под полями стоят то ссылка «Изменить», то кнопка, а плавающая подпись
   следующей строки выступает вверх на десять пикселей — и упирается в поле над
   собой. Двадцать пикселей здесь превращаются в десять. */
.lk_account .lk_mi_line + .lk_mi_line {
    margin-top: 30px;
}



/* Всплывающие уведомления.

   В вёрстке их нет вовсе — ни блока, ни цвета, ни отступа, — поэтому здесь они
   свои целиком. Раньше на их месте стояла строка «Сохранено» под кнопкой: она
   принадлежала форме, гасла, когда поле снова трогали, и не появлялась там, где
   формы после успеха не остаётся — окно смены почты закрывается.

   Правый нижний угол, а не верхний: сверху у страницы шапка, которая при
   прокрутке остаётся на месте, а кнопки, после которых уведомление и
   появляется, стоят внизу своих групп — глазу ближе. */
.toasts {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 200;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 10px;
    /* Стопка перекрывает страницу целиком по ширине, но кликам не мешает:
       нажимать в уведомлении нечего, а невидимая полоса поверх формы отнимала
       бы у кнопок нижний угол. Само уведомление события принимает обратно —
       иначе текст в нём нельзя было бы выделить. */
    pointer-events: none;
}

/* Зелёным, а не общим цветом текста: тем же размером и в том же углу когда-то
   встанут отказы, и различать их только по формулировке значило бы просить
   человека читать там, где достаточно взглянуть. Тот же зелёный, каким была
   отметка «Сохранено» под кнопкой. */
.toast {
    max-width: 320px;
    padding: 14px 20px;
    border-radius: 10px;
    background: #2E9E4F;
    color: #fff;
    font: 16px 'Gilroy', sans-serif;
    line-height: 1.25;
    box-shadow: 0 4px 16px rgba(26, 26, 26, 0.16);
    pointer-events: auto;
    animation: toast_in 0.2s ease-out;
}

/* Появление снизу: уведомление приезжает оттуда, где стоит стопка, а не
   возникает на пустом месте — так видно, что это одно и то же место, даже
   когда уведомлений подряд несколько. */
@keyframes toast_in {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Движение выключается тем, кто о том просил. Само уведомление остаётся: оно
   несёт сообщение, а не украшает. */
@media (prefers-reduced-motion: reduce) {
    .toast {
        animation: none;
    }
}

/* Пояснение, а не подтверждение успеха: «Фото к заданию пока не
   прикрепляются». Цвет — тот же синий, что у кнопок макета. */
.toast_notice {
    background: #3261EC;
}

@media (max-width: 767px) {
    /* На узком экране уведомление занимает строку целиком: 320px в углу
       телефона — это почти вся ширина, и отступ справа выглядел бы промахом
       вёрстки, а не полем. */
    .toasts {
        right: 10px;
        left: 10px;
        bottom: 10px;
        align-items: stretch;
    }

    .toast {
        max-width: none;
        padding: 12px 16px;
        font-size: 14px;
    }
}

/* Окно выбора видимой части фотографии.

   Рамку двигает react-easy-crop, и своих стилей она почти не несёт: контейнер
   обязан быть position: relative с заданной высотой — внутрь она кладёт
   абсолютно позиционированные слои. Высоту поэтому задаём мы. */
.lk_crop {
    position: relative;
    width: 100%;
    height: 320px;
    margin-bottom: 20px;
    border-radius: 10px;
    /* Тёмная подложка, а не белая: за пределами рамки видна остальная
       фотография приглушённой, и на белом фоне светлый снимок сливался бы с
       окном — границы кадра было бы не разобрать. */
    background: #1A1A1A;
    overflow: hidden;
}

/* На время отправки рамка замирает и гаснет: двигать её незачем — вырезано
   уже то, что было, — а живая под пальцем она обещала бы, что уедет новое
   положение. */
.lk_crop[aria-busy='true'] {
    opacity: 0.6;
    pointer-events: none;
}

/* Сама рамка. Библиотека рисует её полупрозрачной белой линией, и на светлой
   фотографии границу кадра оказывается не разобрать — а это единственное, что
   в этом окне надо видеть. Отсюда сплошной белый контур и своя, более плотная
   заливка вокруг: она рисуется огромной тенью, растекающейся за пределы
   рамки, — приём библиотеки, который мы только перекрашиваем. */
.lk_crop .reactEasyCrop_CropArea {
    border: 2px solid #fff;
    box-shadow: 0 0 0 9999em rgba(26, 26, 26, 0.65);
}

/* Подсказка под рамкой. Выравнивание своё: code_text в вёрстке центрирован,
   а здесь он объясняет, что делать, и читается как обычный текст. */
.lk_crop_hint {
    text-align: left;
}

.lk_crop_zoom {
    display: flex;
    align-items: center;
    gap: 15px;
    margin-top: 20px;
}

.lk_crop_zoom span {
    font: 16px 'Gilroy', sans-serif;
    color: #8A97A5;
    white-space: nowrap;
}

/* Ползунок приближения. Вёрстка своего не содержит (ion.rangeSlider из набора
   работает через jQuery и переписывает разметку — то есть тот же спор о
   хозяине узла, что с fancybox), поэтому вид у него свой и на умолчаниях
   браузера: дорожка и бегунок красятся accent-color, всё остальное браузер
   рисует сам — вместе с поведением стрелок, Home и End. */
.lk_crop_zoom input[type='range'] {
    flex: 1 1 auto;
    accent-color: #2F80ED;
    cursor: pointer;
}

.lk_crop_zoom input[type='range']:disabled {
    cursor: default;
}

@media (max-width: 767px) {
    .lk_crop {
        height: 240px;
    }

    .lk_crop_zoom span {
        font-size: 14px;
    }
}

/* Полоса отказа проверки контрагента (остров profile-verification): реестр НПД
   у исполнителя, ЕГРЮЛ и ЕГРИП у работодателя.

   В вёрстке `lk_top_att` — это абзац текста и ничего больше: полос с формой
   внутри в макете нет. Своего здесь поэтому три вещи, и все три про то, что
   внутри полосы стоит форма: размер заголовка (двадцать пикселей на две строки
   отказа — это крик), обычный цвет текста у подсказки (красным набранное
   объяснение читается как второй отказ) и отступ формы от текста.

   Поля и кнопка внутри — те же, что во всей остальной форме профиля: второе
   оформление поля на одном экране читалось бы как чужой элемент. */
.lk_se_title {
    font-size: 18px;
    margin-bottom: 10px;
}

.lk_se_hint {
    font-size: 16px;
    color: #3F4A56;
}

.lk_se_form {
    margin-top: 20px;
}

/* Выбор типа внутри полосы отделён от текста тем же отступом, что и форма. */
.lk_se_kind {
    margin-top: 20px;
}

/* Выбор типа работодателя (islands/kindChoice.tsx) — кружки вёрстки
   (reg_check_block), как у роли над формой, но столбиком: каждой подписи своя
   строка на любом экране. Сегментом в одну строку он был, и на телефоне три
   подписи стояли вплотную.

   Подсказка — по левому краю, как текст полей, и тише их: поясняет выбор, а
   не спорит с ним. Цвет — тёмно-серый пояснений кабинета (.lk_se_hint). */
.kind_choice_hint {
    margin-bottom: 12px;
    font: 16px 'Gilroy', sans-serif;
    line-height: 1.25;
    color: #3F4A56;
    text-align: left;
}

.kind_choice {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
}

/* У вёрстки кружок стоит с отступами по бокам — для строки ролей по центру; в
   столбике по левому краю они сдвинули бы его с линии полей. */
.kind_choice .reg_check_block {
    margin: 0;
}

.kind_choice .reg_check_block label {
    font-size: 20px;
}

/* Скрыто глазом, но не от клавиатуры: вёрстка прячет radio display:none, и
   с клавиатуры тип было бы не выбрать. Тот же приём, что у вида каталога. */
.kind_choice .reg_check_block input[type='radio'] {
    display: block;
    position: absolute;
    left: 0;
    top: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.kind_choice .reg_check_block input[type='radio']:focus-visible + label:before {
    outline: 2px solid #3261EC;
    outline-offset: 2px;
}

/* Отказ — рамка кружков того же красного, что у поля с ошибкой. */
.kind_choice.has_error .reg_check_block input[type='radio'] + label:before {
    border-color: #E02B2B;
}

@media (max-width: 767px) {
    .kind_choice_hint {
        margin-bottom: 10px;
        font-size: 12px;
    }

    /* Кружок вёрстки здесь 10px, а подпись роли — 12px; столбец повторяет
       строку ролей над формой. Блок кружка вёрстка держит высотой в 10px, и
       подпись выступает за него — поэтому шаг между пунктами и отступ до поля
       ИНН задаются здесь, а не высотой блока: иначе последний пункт лёг бы на
       поле. */
    .kind_choice {
        gap: 16px;
        padding: 2px 0 8px;
    }

    .kind_choice .reg_check_block label {
        font-size: 12px;
    }
}

/*
    Имя вошедшего в кнопке шапки.

    Обрезать имя приходится: домен принимает до двухсот рун
    (domain.ParseUserName), а кнопка в вёрстке шириной ровно 200px
    (.lk_btn) — «Константинопольский Константин Константинович» в неё не
    влезет никогда. Полное имя человек и так знает, а в профиле оно стоит
    целиком.

    Границу задаёт сама кнопка, а не max-width у имени. Первая попытка
    поставить имени 12em и была ошибкой: при шрифте кнопки в 20px это 240px,
    то есть шире самой кнопки, — имя не помещалось, а ужаться не могло, потому
    что у элемента флекса min-width равен auto. Флекс из вёрстки (.flex) при
    этом переносит строки, и значок человека уезжал на вторую строку: кнопка
    разъезжалась надвое.

    Отсюда три правила вместо одного. Имени разрешено ужиматься (min-width: 0)
    — без этого ellipsis не сработает ни при какой ширине. Значку запрещено
    (flex-shrink: 0) — сжимать надо текст, а не иконку. Кнопке запрещён
    перенос: она заведомо в одну строку, и переносить в ней нечего.
*/
.lk_btn {
    flex-wrap: nowrap;
}

.lk_btn svg {
    flex-shrink: 0;
}

/*
    Поле по краям кнопки — только там, где имя вообще показывается.

    На узком экране вёрстка сжимает кнопку до 15×15 и прячет текст
    (screen-media.css, 767px): остаётся один значок, и отступ в 15px при
    box-sizing: border-box съел бы всю ширину, сдвинув значок вправо от центра.
    Порог поэтому тот же, что у вёрстки, — иначе два описания одной границы
    разъедутся на первой же её правке.
*/
@media only screen and (min-width: 768px) {
    .lk_btn {
        padding: 0 15px;
    }
}

/*
    display здесь не задаётся намеренно. Элемент флекса и так блокируется —
    ellipsis работает без указаний, — а написанное явно `display: block`
    оказывается специфичнее вёрстки (0,2,0 против 0,1,1) и перебивает её
    правило `.lk_btn span { display: none }` на узком экране: имя вылезало
    обратно в кнопку, сжатую до 15×15.
*/
.lk_btn .lk_btn_name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
    Отступ значка от текста в вёрстке — 20px слева (.lk_btn svg), и рассчитан
    он на короткое «Войти» в кнопке без отступов по краям. С полем в 15px и
    длинным именем эти 20px забирают у текста последние символы, поэтому здесь
    они уменьшены. На узком экране вёрстка их и так обнуляет: имя там не
    показывается вовсе, остаётся один значок.
*/
.lk_btn .lk_btn_name + svg {
    margin-left: 10px;
}

/* Объекты (остров profile-facilities).

   Своего здесь почти всё: в вёрстке этот блок — `activation_block` из макета
   23b, где адреса стояли полями ввода, а у нас это список строк. Общим остался
   крестик удаления `ab_del` — он единственный, что рисуется картинкой. */

/* Отступ от заголовка группы.

   `lk_title_small` полей не отбивает: у соседних групп первую строку опускает
   собственный отступ строки формы (`lk_mi_line`), а здесь первым идёт то текст,
   то список, и оба липли к заголовку вплотную. Двадцать пикселей — столько же,
   сколько `activation_title` отбивал в макете. */
.lk_facilities {
    margin-top: 20px;
}

/* Пустой список — одна фраза: под ней стоит кнопка «Добавить ещё», и что
   делать, человеку видно без объяснений. */
.lk_facilities_empty {
    font-size: 20px;
    color: #3F4A56;
    margin: 0 0 20px;
}

.lk_facilities_list {
    list-style: none;
    margin: 0 0 20px;
    padding: 0;
}

/* Строка списка — плашка по ширине содержимого, а не полоса во всю форму.

   Первая попытка растягивала строку на всю ширину и уводила крестик к правому
   краю: адрес занимал треть, две трети оставались пустыми, и разделительная
   черта через всю форму делала из списка таблицу без содержимого. Плашка
   занимает ровно столько, сколько занимает адрес, и крестик стоит сразу за
   ним — там, где человек его и ищет.

   Заливка и скругление те же, что у запертых полей формы: список читается
   значением, а не вводом, и это ровно то, что запертое поле означает. Замка при
   этом нет — вместо него крестик, который строку убирает.

   Длинный адрес переносится внутри плашки и упирается в ширину формы, а не
   растягивает страницу вбок. */
.lk_facilities_item {
    width: fit-content;
    max-width: 100%;
    padding: 12px 16px;
    background: #F1F4F9;
    border-radius: 10px;
}

/* Сама строка: адрес, кнопка карты и крестик в ряд.

   Отдельным узлом внутри плашки она стала вместе с картой: карта раскрывается
   под своей же строкой, то есть внутри той же плашки, и flex на плашке поставил
   бы её сбоку от адреса. Заодно видно, что плашка растёт под раскрытую карту —
   раскрытая строка занимает больше места, и это правда о её состоянии. */
.lk_facilities_row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}

/* Кнопка «На карте».

   Текстовая, а не значок: значок карты человеку приходится узнавать, а слово
   читается сразу. Рядом стоит крестик — единственный значок в строке, и он
   привычен; второй значок рядом с ним читался бы как пара «сделать / отменить».

   Подпись меняется вместе с состоянием («На карте» / «Скрыть»), поэтому у
   кнопки фиксированная ширина не задана: «Скрыть» короче, и строка чуть
   подбирается — это видимый ответ на нажатие. */
.lk_facilities_map {
    flex-shrink: 0;
    margin-top: 3px;
    padding: 0;
    border: 0;
    background: none;
    font: 400 15px/1.35 'Gilroy', sans-serif;
    color: #3261EC;
    cursor: pointer;
}

.lk_facilities_map:hover {
    text-decoration: underline;
}

.lk_facilities_map.is_open {
    color: #8E96A0;
}

/* ── Карта адреса ───────────────────────────────────────────────────────────

   Две карты одним видом: та, на которой ставят метку в форме заведения, и та,
   на которой смотрят заведённый объект. Различаются они высотой и тем, что на
   первой есть метка по центру и считка адреса.

   В вёрстке карта есть (`.catalog_map`, 257px, с кнопкой «Посмотреть на карте»
   поверх), но стоит она на страницах каталога и устроена иначе: там карта —
   зрелище во всю ширину, здесь — инструмент внутри формы. Взята оттуда
   единственная верная вещь — пропорция: карта высотой примерно в четверть
   экрана читается как карта, а не как полоска. */
.address_map {
    position: relative;
    width: 100%;
    margin-top: 12px;
    border: 1px solid #E3E8F0;
    border-radius: 10px;
    overflow: hidden;
}

/* Карта выбора выше карты просмотра: на ней работают, а не смотрят — метку
   двигают пальцем, и низкая карта означала бы, что дом уезжает за край на
   каждом движении. */
.address_map_pick {
    height: 260px;
    min-width: 280px;
}

.address_map_view {
    height: 200px;
}

/* Раскрытая строка шире сжатой, и ширину задаёт она, а не карта внутри.

   Плашка сжимается по адресу (width: fit-content), и карта внутри неё получалась
   бы то в пол-экрана, то в ладонь — смотря какой адрес человек завёл. Задать
   ширину самой карте нельзя: её процент считается от плашки, а плашка считается
   от содержимого, и круг замкнулся бы на той же ширине адреса. Поэтому ширину
   получает строка, а карта занимает её целиком.

   520 пикселей — ширина, на которой вокруг дома виден перекрёсток, а не один
   двор; на узком экране она уступает место самому экрану. */
.lk_facilities_item.is_open {
    width: min(520px, 100%);
}

/* Холст чужого скрипта. Абсолютным, как и в вёрстке: карта обязана занять
   рамку целиком, а свою высоту она не знает. */
.address_map_canvas {
    position: absolute;
    inset: 0;
}

.address_map_loading,
.address_map_failed {
    margin: 12px 0 0;
    font: 400 15px/1.35 'Gilroy', sans-serif;
    color: #8E96A0;
}

/* Отказ загрузки карты — не поломка формы: адрес по-прежнему выбирают из
   подсказок. Поэтому серым и без рамки, а не красной строкой отказа. */
.address_map_loading {
    position: absolute;
    left: 16px;
    top: 16px;
    margin: 0;
    z-index: 2;
}

/* Метка.

   Прибита к центру карты: её остриё — ровно та точка, о которой биржа
   спрашивает справочник. Отсюда и translate(-50%, -100%): узел висит над
   центром, а касается его нижним краем.

   z-index держит её над холстом, но ниже считки: считка — это то, что метка
   означает, и заслонять её меткой нельзя. */
.address_map_pin {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 2;
    transform: translate(-50%, -100%);
    transition: transform .16s ease-out;
    pointer-events: none;
}

/* Тень под остриём — единственное украшение на этой карте, и работает она не
   как украшение: без тени метка читается как значок, наклеенный на экран, а с
   тенью — как воткнутая в карту. */
.address_map_pin::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: -3px;
    width: 14px;
    height: 5px;
    border-radius: 50%;
    background: rgba(37, 47, 105, .35);
    transform: translateX(-50%);
    transition: transform .16s ease-out, opacity .16s ease-out;
}

/* Пока карту тянут, метка приподнята: она «отрывается» от карты, которая едет
   под ней, и садится, когда движение кончилось. Это единственное движение здесь
   и единственное, чего человек не запускал кнопкой, — но запустил он его
   пальцем, и оно отвечает ровно на его же действие. */
.address_map_pin.is_moving {
    transform: translate(-50%, calc(-100% - 7px));
}

.address_map_pin.is_moving::after {
    opacity: .5;
    transform: translateX(-50%) scale(.6);
}

/* Отказ под картой — тем же видом, что у всех полей формы (cf_error): своя
   строка завела бы второе оформление для того же самого. Отступ у неё свой,
   потому что стоит она не под полем, а под картой. */
.address_map_block .cf_error {
    margin-top: 10px;
}

/* Кнопки приближения.

   Свои, а не контрол поставщика: тот приезжает отдельным модулем ради двух
   кнопок и приносит свой вид. Здесь вид кабинета — белое на скруглении, тот же
   радиус и та же тень, что у остальных всплывающих поверхностей.

   Справа сверху: снизу у карты копирайт и ссылка на условия использования, а
   слева в режиме просмотра может оказаться метка — она стоит там, где стоит
   объект, и заслонять её кнопками нельзя.

   Парой в одной коробке, а не двумя отдельными кнопками: это одно действие с
   двумя направлениями, и разнесённые кнопки читались бы как два разных. */
.address_map_zoom {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 3;
    display: flex;
    flex-direction: column;
    border-radius: 10px;
    background: #FFFFFF;
    box-shadow: 0 4px 16px rgba(37, 47, 105, .18);
    overflow: hidden;
}

.address_map_zoom button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 0;
    background: none;
    color: #1A1A1A;
    cursor: pointer;
}

/* Волосяная черта между кнопками: она делит одну коробку надвое, а не рисует
   рамку вокруг каждой. */
.address_map_zoom button + button {
    border-top: 1px solid #E3E8F0;
}

.address_map_zoom button:hover {
    background: #F1F4F9;
}

/* На границе приближения кнопка гаснет и перестаёт отвечать на наведение:
   нажатие, которое ничего не делает, обещает то, чего нет. */
.address_map_zoom button:disabled {
    color: #C4CAD4;
    cursor: default;
}

.address_map_zoom button:disabled:hover {
    background: none;
}

/* Рамка фокуса своя, внутренняя: кнопка прижата к краю коробки, и обычная
   внешняя обводка ушла бы под её скругление. */
.address_map_zoom button:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px #3261EC;
}

/* Метка заведённого объекта. Тот же вид, что у метки выбора, но без тени и без
   подъёма: она стоит на месте, и подниматься ей не от чего. */
.address_map_marker {
    transform: translate(-50%, -100%);
    pointer-events: none;
}

/* Отступ до кнопки отправки вёрстка ставит правилом `.map_link + .login_btn`,
   а ссылки этой больше нет — карта стоит в окне всегда, и перед кнопкой теперь
   она. */
.address_map_block + .login_btn {
    margin-top: 25px;
}

/* На узком экране карта ниже: она делит высоту с полем, ссылкой и кнопкой, и
   окно, не помещающееся целиком, заставляет прокручивать форму ради кнопки. */
@media (max-width: 767px) {
    .address_map_pick {
        height: 220px;
    }

    .address_map_view {
        height: 170px;
    }
}

/* Подъём метки — движение ради понимания, а не ради красоты, поэтому оно не
   убирается совсем, а становится мгновенным: метка по-прежнему отличается на
   вид, пока карту тянут. */
@media (prefers-reduced-motion: reduce) {
    .address_map_pin,
    .address_map_pin::after {
        transition: none;
    }
}

.lk_facilities_item + .lk_facilities_item {
    margin-top: 10px;
}

/* Маркер и отступ, которые вёрстка вешает на любой li внутри .content_wp
   (`content: '–'` и padding-left: 20px у `.content_wp li`). Список здесь не
   перечисление в тексте статьи, а строки формы, и тире перед адресом читалось
   бы как часть адреса.

   Селектор длиннее, чем нужно для чтения, и это не украшение: у правил вёрстки
   специфичность выше нашей (`.content_wp ul li:before` — класс и два элемента),
   и коротким `.lk_facilities_item::before` их не перебить. Порядок подключения
   тут не помогает: он решает только при равной специфичности. */
.lk_facilities_list .lk_facilities_item::before {
    content: none;
}

.lk_facilities_list .lk_facilities_item {
    padding-left: 16px;
}

.lk_facilities_address {
    font: 400 20px/1.35 'Gilroy', sans-serif;
    color: #1A1A1A;
    /* Длинный адрес переносится, а не растягивает плашку: пробелов в нём
       хватает, но встречаются и слитные куски вроде индекса с городом. */
    overflow-wrap: anywhere;
}

/* Крестик удаления виден всегда, а не по наведению.

   В вёрстке `.ab_del` имеет opacity: 0 и проявляется на `.msb_item:hover` —
   то есть у того, у кого есть мышь. На телефоне такой крестик не существует
   вовсе, а профиль открывают с телефона; с клавиатуры его тоже не найти —
   фокус попадает на невидимую кнопку. Убрать объект иначе нечем: правки у него
   нет, только заведение и удаление.

   Наведение и фокус при этом остаются заметны — крестик темнеет, — и
   focus-visible рисует рамку: кнопка здесь без текста, и без рамки не видно,
   на чём стоит курсор.

   Из абсолютного позиционирования вёрстки он вынут: там крестик висел в углу
   поля во всю ширину, а здесь стоит следующим за адресом в одной строке.
   Смещение по вертикали — на разницу между строкой текста и его собственной
   высотой: адрес переносится на две строки, и крестик обязан остаться у
   первой. */
.lk_facilities .ab_del {
    position: static;
    flex-shrink: 0;
    margin-top: 6px;
    opacity: .55;
    border: 0;
    padding: 0;
    cursor: pointer;
}

.lk_facilities_item:hover .ab_del,
.lk_facilities .ab_del:hover,
.lk_facilities .ab_del:focus-visible {
    opacity: 1;
}

.lk_facilities .ab_del:focus-visible {
    outline: 2px solid #3261EC;
    outline-offset: 4px;
    border-radius: 2px;
}

.lk_facilities .ab_del:disabled {
    opacity: .25;
    cursor: default;
}

/* ── Подсказки адреса ──────────────────────────────────────────────────────
   Выпадающий список под полем адреса в окне заведения объекта.

   Своего вида в вёрстке у него нет: список `msb_select`, которым вёрстка
   рисует селекторы формы задания, живёт под jQuery — он переписывает разметку
   под собой, а здесь рядом стоит React, считающий эти узлы своими. Поэтому вид
   свой целиком, а заливка и скругление взяты у полей кабинета: список
   продолжает поле, а не спорит с ним. */
.address_suggest {
    /* Список висит над формой, а не раздвигает её: появившись между полем и
       кнопкой, он уводил бы кнопку из-под пальца ровно в тот момент, когда
       человек до неё дотянулся. */
    position: relative;
}

.address_suggest_list {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    /* Выше подложки модального окна и её содержимого: список рисуется внутри
       окна и обязан лежать поверх соседних полей. */
    z-index: 5;
    margin: 0;
    padding: 6px 0;
    list-style: none;
    background: #FFFFFF;
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(26, 26, 26, .16);
    /* Десять подсказок целиком не помещаются, и это правильно: список во весь
       экран закрыл бы собой окно. Остальные прокручиваются. */
    max-height: 264px;
    overflow-y: auto;
}

/* Тире и отступ, которые вёрстка вешает на любой li внутри .content_wp. Тот же
   случай и тот же селектор, что у списка объектов: коротким `::before` правило
   вёрстки не перебить — у него специфичность выше. */
.address_suggest_list .address_suggest_item::before,
.address_suggest_list .address_suggest_note::before {
    content: none;
}

.address_suggest_item,
.address_suggest_note {
    padding: 8px 16px;
}

.address_suggest_item {
    cursor: pointer;
}

/* Наведение мышью и выбор клавишами показываются одинаково: строка, на которой
   стоит человек, одна — независимо от того, чем он её выбрал. */
.address_suggest_item:hover,
.address_suggest_item.is_active {
    background: #F1F4F9;
}

.address_suggest_title {
    display: block;
    font: 400 16px/1.35 'Gilroy', sans-serif;
    color: #1A1A1A;
}

/* Подпись строки, которая домом не является: нажатие на неё выбор не закончит,
   а продолжит — дом в адресе обязателен, и сервер такой адрес не примет. Стоит
   рядом с названием, а не под ним: это свойство самой строки, а не вторая её
   половина. Приглушена и мельче — читать её надо тому, кто уже потянулся
   нажать. */
.address_suggest_narrow {
    margin-left: 8px;
    font: 400 12px/1.35 'Gilroy', sans-serif;
    color: #8E96A0;
    white-space: nowrap;
}

/* Вторая строка подсказки — город и страна: справочник отдаёт её отдельно, и
   слитая с первой она дала бы список, где все строки начинаются одинаково. */
.address_suggest_subtitle {
    display: block;
    font: 400 13px/1.35 'Gilroy', sans-serif;
    color: #8E96A0;
}

/* «Ничего не нашлось» и отказ связи стоят на месте списка: они отвечают на тот
   же вопрос, что и он, и человек смотрит туда же. */
.address_suggest_note {
    font: 400 15px/1.35 'Gilroy', sans-serif;
    color: #8E96A0;
}

/* ── Адрес с подсказками в форме профиля ────────────────────────────────────
   Фактический адрес и адрес регистрации. Те же подсказки, что в окне объекта,
   но вид — как у поля БИК: список продолжает поле синей рамкой фокуса, а не
   всплывает карточкой с тенью. Строки — те же, что у окна объекта
   (address_suggest_title и соседи). */

.address_field {
    position: relative;
}

.address_field.is_open .cf_input {
    border-color: #3261EC;
    border-radius: 5px 5px 0 0;
}

.address_field_list {
    position: absolute;
    top: 49px;
    left: 10px;
    right: 10px;
    z-index: 5;
    margin: 0;
    padding: 4px 0;
    list-style: none;
    background: #FFFFFF;
    border: 1px solid #3261EC;
    border-top-color: #BAC8D6;
    border-radius: 0 0 5px 5px;
    max-height: 300px;
    overflow-y: auto;
}

/* Тире и отступ, которые вёрстка вешает на любой li внутри .content_wp. */
.address_field_list .address_field_item::before,
.address_field_list .address_field_note::before {
    content: none;
}

.address_field_item {
    padding: 10px 20px;
    cursor: pointer;
}

.address_field_item:hover,
.address_field_item.is_active {
    background: #F3F7FA;
}

.address_field_note {
    padding: 12px 20px;
    font: 400 15px/1.35 'Gilroy', sans-serif;
    color: #8E96A0;
}

/* Кнопка загрузки документа, пока идёт другая загрузка, приглушена: поле под
   ней выключено, а синяя кнопка звала бы нажать. Идущая — с кольцом
   (aria-busy, правило кольца выше). */
.verification_item input[type='file']:disabled + label {
    opacity: 0.6;
    cursor: default;
}

.verification_item input[type='file']:disabled + label[aria-busy='true'] {
    opacity: 1;
}

/* ── Отметка «Частный дом» под полем квартиры ───────────────────────────────
   Отвечает на вопрос поля над ней, поэтому стоит в его ячейке и мельче
   галочек согласия (`contacts_form_check`, 30px — для отдельной строки окна):
   под полем высотой 50px такой квадрат перевесил бы само поле. Цвета,
   скругление и значки — те же, что у галочек вёрстки. */
.unit_flag {
    position: relative;
    margin-top: 10px;
}

/* Настоящий checkbox невидим, но остаётся в потоке фокуса — как у галочки
   согласия (.bf_check): вёрстка прячет его display: none, и с клавиатуры до
   него было бы не дойти. */
.unit_flag_input {
    position: absolute;
    left: 0;
    top: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.unit_flag_label {
    position: relative;
    display: inline-block;
    padding-left: 30px;
    /* Как плавающие подписи полей формы: один голос у всех подписей. */
    font: 400 15px/20px 'Gilroy', sans-serif;
    color: #1A1A1A;
    cursor: pointer;
}

.unit_flag_label::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    width: 20px;
    height: 20px;
    box-sizing: border-box;
    border: 1px solid #BAC8D6;
    border-radius: 6px;
    background: #FFFFFF;
}

.unit_flag_input:checked + .unit_flag_label::before {
    background: #FFFFFF url("../images/ico-check-black.svg") no-repeat center / 12px auto;
}

.unit_flag_input:focus-visible + .unit_flag_label::before {
    outline: 2px solid #3261EC;
    outline-offset: 2px;
}

/* ── Банковские реквизиты: поле БИК и расчётный счёт ───────────────────────

   Список подсказок продолжает поле, как выпадающий список вёрстки
   (msb_select): у открытого поля снимается нижнее скругление, список идёт под
   ним той же синей рамкой фокуса. Не всплывающая карточка с тенью — так
   подсказка читается частью поля, а не чужим элементом поверх формы. */

.bank_field.is_open .cf_input {
    border-color: #3261EC;
    border-radius: 5px 5px 0 0;
}

/* Выбранный банк — внутри поля, справа от цифр БИК. Галочка — знак того, что
   цифры подтверждены справочником, а не набраны наугад. Подложки у узла нет:
   текст стоит на фоне самого поля, а поле отодвигает свои цифры (has_bank) —
   так он не перекрывает ни рамку, ни набранное. Нажатий узел не ловит. */
.bank_field.has_bank .cf_input {
    padding-right: 52%;
}

.bank_field .input_moving_text .bank_field_name {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 20px;
    left: auto;
    max-width: calc(52% - 30px);
    padding: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    font: 500 16px/1.2 'Gilroy', sans-serif;
    color: #1A1A1A;
    background: none;
    pointer-events: none;
    white-space: nowrap;
    overflow: hidden;
    transition: none;
}

.bank_field_name_text {
    overflow: hidden;
    text-overflow: ellipsis;
}

.bank_field .input_moving_text .bank_field_name::before {
    content: '';
    flex: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #3261EC url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Cpath d='M5 9.2l2.6 2.6L13 6.4' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / 18px 18px;
}

.bank_suggest_list {
    position: absolute;
    top: 49px;
    left: 10px;
    right: 10px;
    z-index: 5;
    margin: 0;
    padding: 4px 0;
    list-style: none;
    background: #FFFFFF;
    border: 1px solid #3261EC;
    border-top-color: #BAC8D6;
    border-radius: 0 0 5px 5px;
    /* Десять строк целиком не помещаются: остальные прокручиваются. */
    max-height: 300px;
    overflow-y: auto;
}

/* Тире и отступ, которые вёрстка вешает на любой li внутри .content_wp. */
.bank_suggest_list .bank_suggest_item::before,
.bank_suggest_list .bank_suggest_note::before {
    content: none;
}

.bank_suggest_item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 10px 20px;
    cursor: pointer;
}

/* Наведение мышью и выбор клавишами показываются одинаково. */
.bank_suggest_item:hover,
.bank_suggest_item.is_active {
    background: #F3F7FA;
}

.bank_suggest_name {
    min-width: 0;
    font: 400 18px/1.3 'Gilroy', sans-serif;
    color: #1A1A1A;
}

.bank_suggest_bic {
    flex: none;
    font: 400 16px/1.3 'Gilroy', sans-serif;
    color: #8E96A0;
    font-variant-numeric: tabular-nums;
}

/* Совпадение с набранным — почему строка попала в список. */
.bank_suggest_item mark {
    background: none;
    color: #3261EC;
    font-weight: 600;
}

.bank_suggest_note {
    padding: 12px 20px;
    font: 400 15px/1.35 'Gilroy', sans-serif;
    color: #8E96A0;
}

/* Счётчик цифр расчётного счёта — внутри поля справа, пока номер не набран. */
.bank_account .cf_input {
    padding-right: 84px;
    font-variant-numeric: tabular-nums;
}

.bank_account_count {
    position: absolute;
    top: 0;
    right: 30px;
    line-height: 50px;
    font: 400 15px/50px 'Gilroy', sans-serif;
    color: #8E96A0;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

/* ── Форма нового задания ──────────────────────────────────────────────────

   Страница ленты и форма перенесены из макета 24a-client-timeline.html как
   есть: рисуют их screen.css, style.css и swiper-bundle.css, оживляет
   собственный скрипт вёрстки. Ни одно её правило здесь не переопределяется —
   тронь любое, и колонки разъедутся по высоте: слайду снизу зарезервированы
   пятьдесят пикселей под кнопку «Новое задание», которые на наведении уступают
   ей место.

   Своё здесь одно: в макете список категорий одноуровневый и короткий, а
   справочник биржи — сотня разделов в два уровня. Оба правила заужены до формы
   задания: тем же `msb_select` вёрстка рисует выбор города в шапке. */

/* Корень справочника — заголовок группы. В форме задания он не выбирается:
   задание в раздел домен не ставит (Category.AcceptsTask). В окне категорий
   уведомлений исполнителя тот же заголовок нажимается — отметка раздела там
   означает все его подкатегории (ТЗ 23b). */
.contacts_form .msb_select_group {
    font: 600 15px/1.2 'Gilroy', sans-serif;
    color: #808080;
    padding: 10px 20px 3px;
}

/* Сто разделов не помещаются на экран, и без прокрутки нижние были бы
   недосягаемы. */
.contacts_form .msb_select_toggle {
    max-height: 320px;
    overflow-y: auto;
}

/* Окно «Добавить категорию» в профиле исполнителя: список тот же, что у
   выпадающего `msb_select`, но стоит в окне раскрытым. Вёрстка прячет
   `msb_select_toggle` (`display: none`) и открывает его только внутри
   `.msb_select.active`, а обёртки-переключателя в окне нет: без этого правила
   окно открывалось пустым. Висеть поверх соседей ему тоже незачем — в окне,
   кроме него, ничего нет. */
.msb_select_toggle.lk_category_choice {
    display: block;
    position: static;
    min-width: 0;
    border: 1px solid #BAC8D6;
    border-radius: 10px;
}

/* Отмеченная категория — синим и галочкой: повторное нажатие на неё ничего не
   добавит, и это должно быть видно до нажатия. */
.lk_category_choice a.is_chosen {
    color: #3261EC;
    padding-right: 44px;
    background: url(../images/ico-check-blue.svg) no-repeat right 20px center;
    background-size: 14px auto;
}

/* Отказ отмечает коробку списка так же, как поле (`.cf_input.has_error`) —
   рамкой того же красного. Состояния «заполнено неверно» вёрстка не рисует ни
   у полей, ни тем более у списка. */
.msb_select.has_error .msb_select_top {
    border: 1px solid #E02B2B;
}

/* Часы работы не набирают — их считает окно, — и поле обязано это показывать.
   Заливка и рамка те же, какими вёрстка гасит недоступное поле
   (`.cf_input:disabled`): второй вид неактивного поля на одном экране читался
   бы как другое состояние. Само поле при этом `readonly`, а не `disabled`:
   значение из него читает отправка, а `disabled` браузер не отдаёт вовсе, — то
   же решение, что у запертых реквизитов в профиле. */
.contacts_form .cf_input[readonly] {
    cursor: default;
    border: 1px solid rgba(37, 30, 74, 0.2);
    background: rgba(0, 0, 0, 0.03);
}

/* Строка отказа в модальных окнах этапов задания и на карточке.
   Класс свой, а не `cf_error` соседних форм: та строка встаёт под конкретным
   полем и потому прижата к нему, а эта относится к форме целиком и стоит над
   кнопкой — отступ у неё поэтому с обеих сторон. Цвет и начертание те же:
   двух видов отказа на одном сайте быть не должно. */
.form_error {
    font: 500 14px/1.4 'Gilroy', sans-serif;
    color: #E02B2B;
    margin: 12px 0;
    text-align: center;
}

/* Объяснение вместо кнопки на карточке задания: почему «Взять в работу» нет.
   Серым и по центру — там же, где стояла бы кнопка: человек ищет ответ на
   вопрос «что мне здесь делать» именно в этом месте. */
.card_notice {
    font: 500 15px/1.4 'Gilroy', sans-serif;
    color: #808080;
    margin: 0 0 30px;
    text-align: center;
}

/* Оценка в форме завершения задания.

   Обычные радиокнопки, а не плагин rateit из вёрстки: тот работает через
   jQuery и переписывает разметку под собой, а рядом стоит форма, узлы которой
   считает своими наш модуль. Пять звёзд рисуются подписями, сами кнопки
   уводятся с экрана — но не `display: none`, иначе они выпали бы из порядка
   обхода и с клавиатуры оценку было бы не поставить.

   Порядок в разметке обратный (от пяти к одной) ровно ради `~`: подсветить
   соседей слева селектором нельзя, а справа — можно, и «четыре звезды»
   означает «зажглись четвёртая и все, что левее». */
.task_rating {
    direction: rtl;
    gap: 6px;
    margin: 0 0 20px;
}

.task_rating input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.task_rating label {
    cursor: pointer;
    font-size: 0;
    line-height: 0;
    color: rgba(37, 30, 74, 0.2);
    transition: color 0.15s;
}

.task_rating label::before {
    content: '★';
    font-size: 32px;
    line-height: 1;
}

.task_rating input:checked ~ label,
.task_rating label:hover,
.task_rating label:hover ~ label {
    color: #FFB800;
}

/* Рамка фокуса нужна тому, кто ставит оценку с клавиатуры: без неё не видно,
   на какой звезде он стоит. */
.task_rating input:focus-visible + label {
    outline: 2px solid #2F80ED;
    outline-offset: 2px;
}

/* Строка списка откликнувшихся без фотографии: ячейка остаётся на месте, чтобы
   имена в столбце не разъезжались. Пунктир — тот же, каким размечена пустая
   ячейка фотографии в профиле. */
.employee_img:empty {
    border: 1px dashed rgba(37, 30, 74, 0.3);
    border-radius: 50%;
}

/* Отметка исполнителя в окне выбора. Вёрстка рисует квадрат только галочке
   (`input[type='checkbox'] + label:before`), а выбирают здесь одного — стоит
   радиокнопка, и квадрата не было вовсе: на её месте висел голый кружок. Вид
   тот же, что у галочки макета.

   И столбец виден всегда, а не под курсором (`opacity: 0` у
   `.employee_right` до :hover): невидимая кнопка — это кнопка, о которой не
   знают, а на телефоне курсора нет. Строку отмечает и щелчок по ней самой
   (lk/taskStages.ts). */
.employee_right {
    opacity: 1;
}
.employee_right input[type='radio'] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.employee_right input[type='radio'] + label:before {
    content: '';
    width: 40px;
    height: 40px;
    border-radius: 8px;
    border: 2px solid #BAC8D6;
    position: absolute;
    top: 0;
    right: 0;
    box-sizing: border-box;
}
.employee_right input[type='radio']:checked + label:before {
    background: url("../images/ico-check-black.svg") no-repeat center center;
    background-size: 20px auto;
    border-color: #3261EC;
}
.employee_right input[type='radio']:focus-visible + label:before {
    outline: 2px solid #2F80ED;
    outline-offset: 2px;
}
.employee_right input[type='radio']:disabled + label {
    cursor: default;
    opacity: 0.5;
}
.employee_item {
    cursor: pointer;
}

/* Окно согласия — «Форма согласия» из макета.

   Вида в вёрстке у него нет: `modal_text_v2`, `agreement_btns` и
   `login_btn_bg_white` стоят в разметке макета, но ни одного правила под них в
   `screen.css` не написано. Поэтому вид свой целиком — как у уведомлений, — а
   классы оставлены макетные: вернётся выгрузка со стилями, и она сядет на
   готовую разметку. */
.modal_text_v2 {
    margin: 0 0 24px;
    text-align: center;
}

.modal_text_v2 p {
    font: 500 16px/1.5 'Gilroy', sans-serif;
    color: #251E4A;
    margin: 0;
}

/* Кнопки в строку и одинаковой ширины: вопрос закрытый, и оба ответа
   равноправны по месту. Различает их не размер, а заливка. */
.agreement_btns {
    gap: 12px;
}

.agreement_btns .login_btn {
    flex: 1 1 0;
    min-width: 0;
    margin-top: 0;
}

/* «Да» — белая, «Нет» — обычная синяя, ровно как в макете. Выделен, то есть,
   безопасный ответ: спрашивают согласия перед тем, чего не отменить, и промах
   должен попадать в «Нет». */
.login_btn_bg_white {
    background: #FFFFFF;
    color: #251E4A;
    border: 1px solid rgba(37, 30, 74, 0.2);
}

.login_btn_bg_white:hover {
    background: #F7F7F7;
}

/* Форма задания в режиме правки.

   Правится в ней окно работ и бюджет — то, что ТЗ разрешает менять при
   опоздании исполнителя (16g). Остальное заперто: объект, категория и
   формулировка — это то, на что человек уже согласился, и поменять их значило
   бы дать ему другую работу под тем же согласием.

   Переключателя вкладок в этом режиме нет вовсе: повторов у правки не бывает, а
   вкладка «Повторное» предлагала бы размножить задание, которое уже заведено. */
.task_form_editing [data-task-tabs] {
    display: none;
}

/* Запертое выглядит так же, как поле «Часов работы», и по той же причине: два
   вида неактивного поля на одном экране читались бы как разные состояния.
   Заливка и рамка — те, какими вёрстка гасит `.cf_input:disabled`. */
.task_form_editing .cf_pole[readonly],
.task_form_editing [data-task-field] .msb_select_top {
    cursor: default;
    border: 1px solid rgba(37, 30, 74, 0.2);
    background: rgba(0, 0, 0, 0.03);
}

/* Список запирается тем, что не открывается: `readonly` у собранной из div
   коробки не бывает. Стрелка при этом гаснет — она обещала бы, что список
   раскроется. */
.task_form_editing [data-task-field] .msb_select_toggle,
.task_form_editing [data-task-field] .msb_select_top span {
    display: none;
}

.task_form_editing [data-task-field] .msb_select_top {
    pointer-events: none;
}

/* Галочка медкнижки и галерея снимков заперты так же: их правка не меняет.
   Полупрозрачность, а не `display: none`, — человеку надо видеть, что у
   задания есть эти свойства, а не гадать, куда они делись. */
.task_form_editing .contacts_form_check,
.task_form_editing .review_gallery {
    pointer-events: none;
    opacity: 0.5;
}

/* --- Раздел «Финансы» и печатная форма счёта --------------------------------

   Своего в разделе почти нет: таблица движения, полоса баланса и панель
   действий взяты из макета (27a-client-finance.html, 36-executor-affiliate.html)
   целиком. Здесь только то, чего в вёрстке не было. */

/* Причина отказа стоит под описанием операции, а не отдельным столбцом: она
   бывает у одной строки из ста, и столбец под неё пустовал бы во всю высоту
   таблицы. Красным — это единственное место таблицы, где что-то пошло не так. */
.finance_reason {
    margin-top: 4px;
    color: #E4002B;
}

/* Пустая таблица говорит об этом одной фразой — как и пустой список объектов в
   профиле. Типографику берёт у подписей формы: заводить третий размер шрифта
   ради одной строки незачем. */
.lk_empty {
    padding: 20px 0;
    color: rgba(37, 30, 74, 0.5);
}

/* Полоса напоминания об оплате — та же, что у «выписка ещё едет» в профиле;
   зелёная — только у оплаченного счёта, где она сообщает не о том, что надо
   сделать, а о том, что уже сделано. */
.lk_top_att_ok {
    color: #1A7F37;
    background: rgba(26, 127, 55, 0.08);
}

/* Счёт на оплату — по образцу заказчика (docs/Счёт.pdf): документ на белом
   листе, рамка реквизитов с QR-кодом, таблица позиции и подписи. В вёрстке
   такого документа нет, поэтому стили свои целиком. */
.invoice_doc {
    max-width: 820px;
    margin-top: 20px;
    color: #000;
    font-size: 13px;
    line-height: 1.35;
}

.invoice_head {
    display: flex;
    justify-content: space-between;
    margin-bottom: 18px;
}

.invoice_head_sum {
    text-align: right;
}

.invoice_strong {
    font-size: 16px;
    font-weight: 700;
}

.invoice_strong_small {
    font-weight: 700;
}

.invoice_muted {
    font-size: 12px;
    color: #555;
}

.invoice_right {
    text-align: right;
}

.invoice_bank {
    display: flex;
    gap: 16px;
    align-items: flex-start;
}

.invoice_bank_table {
    flex: 1;
    border-collapse: collapse;
    border: 2px solid #000;
}

.invoice_bank_table td {
    padding: 6px 10px;
    border: 1px solid #999;
    vertical-align: top;
}

.invoice_bank_label {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

.invoice_qr {
    flex: none;
    width: 150px;
    height: 150px;
    image-rendering: pixelated;
}

.invoice_title {
    margin: 36px 0 22px;
    font-size: 26px;
    font-weight: 700;
}

.invoice_lines {
    margin-bottom: 22px;
}

.invoice_line {
    display: flex;
    gap: 12px;
    margin-bottom: 10px;
}

.invoice_line > span {
    flex: none;
    width: 105px;
}

.invoice_items {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 18px;
}

.invoice_items th {
    padding: 6px;
    font-weight: 400;
    font-size: 12px;
    text-align: left;
    border-bottom: 2px solid #000;
}

.invoice_items td {
    padding: 8px 6px;
    border-bottom: 1px solid #999;
    border-right: 1px solid #ddd;
    vertical-align: top;
}

.invoice_items td:last-child {
    border-right: none;
}

/* Короткие столбцы — в одну строку, переносится только название услуги; фон
   шапки вёрстка ставит всем таблицам, в счёте его нет. */
.invoice_items th,
.invoice_items td {
    white-space: nowrap;
    background: none;
}

.invoice_items th:nth-child(2),
.invoice_items td:nth-child(2) {
    width: 100%;
    white-space: normal;
}

.invoice_items .invoice_right {
    text-align: right;
}

.invoice_summary {
    display: flex;
    justify-content: space-between;
    gap: 20px;
    margin-bottom: 26px;
}

.invoice_summary_total {
    flex: none;
    min-width: 260px;
}

.invoice_summary_row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 12px;
}

.invoice_summary_row b {
    font-size: 20px;
}

.invoice_signs {
    display: flex;
    justify-content: space-between;
    gap: 30px;
    margin-top: 50px;
}

.invoice_sign_row {
    display: flex;
    gap: 10px;
    margin-bottom: 14px;
}

.invoice_sign_row i {
    width: 140px;
    border-bottom: 1px solid #999;
}

/* На узком экране рамка реквизитов и QR друг под другом, строки — в столбик. */
@media (max-width: 640px) {
    .invoice_bank,
    .invoice_summary,
    .invoice_signs,
    .invoice_line {
        flex-direction: column;
    }
}

.invoice_actions {
    margin-top: 20px;
}

.invoice_actions .button {
    max-width: 200px;
}

/* На печати остаётся сам документ. Шапка с меню и подвал с сотней категорий
   дали бы две страницы мусора вокруг таблицы из шести строк, а кнопка «Печать»
   на бумаге — это предложение нажать её ещё раз. */
@media print {
    header,
    footer,
    .left_menu,
    .lk_mob_menu,
    .invoice_actions,
    #toasts,
    #confirm {
        display: none !important;
    }

    .invoice_block {
        box-shadow: none;
    }
}

/* Комментарий Админа к решению по жалобе (ТЗ 33e) стоит под статусом, а не
   отдельным столбцом: он бывает у решённых, то есть у части строк, и столбец
   под него пустовал бы во всю высоту таблицы. Приглушён, потому что главное в
   ячейке — сам статус. */
.complaint_resolution {
    margin-top: 4px;
    color: rgba(37, 30, 74, 0.5);
}

/* --- Раздел «Мессенджер» -----------------------------------------------------

   На узком экране вёрстка показывает либо список переписок, либо одну
   переписку, и переключает их main.js встроенными стилями по нажатию на
   карточку. Карточка у нас ссылка, страница после нажатия перезагружается, и
   состояние main.js пропадает вместе с ней, — поэтому открытость рисует
   сервер классом `is_chat_open` (переписка названа в адресе). Правила
   повторяют ровно то, что делает main.js; «назад» (`chat_back`) он же и
   обслуживает, и его встроенные стили сильнее этого класса. */
@media only screen and (max-width: 1023px) {
    .messenger_wp.is_chat_open .messenger_top,
    .messenger_wp.is_chat_open .messenger_block > .messenger_left {
        display: none;
    }

    .messenger_wp.is_chat_open .messenger_right_mob {
        display: block;
    }
}

/* --- Раздел «Статистика» -----------------------------------------------------

   Плитки и блок графика есть в вёрстке; своего здесь только сам график. В
   макете его рисует amCharts с чужого CDN — единственная сторонняя зависимость
   во всей вёрстке, — а у нас он приезжает готовым SVG от сервера. */

/* Линия растягивается по ширине блока: viewBox задаёт систему координат, а не
   размер. Высота фиксированная — иначе график менял бы высоту вместе с
   шириной окна. */
.schedule_chart {
    display: block;
    width: 100%;
    height: 240px;
}

.schedule_line {
    fill: none;
    stroke: #4B4AEF;
    stroke-width: 2;
    /* Линия рисуется в координатах viewBox и растягивается вместе с ним: без
       этого правила её толщина менялась бы вместе с шириной окна. */
    vector-effect: non-scaling-stroke;
    stroke-linejoin: round;
}

.schedule_area {
    fill: rgba(75, 74, 239, 0.08);
    stroke: none;
}

/* Подписи оси и максимум — тем же приглушённым цветом, что и подписи форм:
   главное на графике линия, а не цифры под ним. */
.schedule_axis,
.schedule_max {
    margin-top: 8px;
    font-size: 13px;
    color: rgba(37, 30, 74, 0.5);
}

/* Знак изменения показателя: рост зелёным, падение красным. В вёрстке у него
   цвета нет — там нарисован только плюс. */
.dashboard_up {
    color: #1A7F37;
}

.dashboard_down {
    color: #E4002B;
}

/* ── Публичная часть: каталог, компании, поддержка ─────────────────────────
   Своего здесь ровно столько, сколько добавлено сверх макета: ссылки там, где
   в вёрстке стояли неактивные подписи, и три подписи, которых в макете нет
   вовсе. Ни одно правило вёрстки не переопределяется — это общее правило
   проекта, и держится оно тем, что все селекторы ниже свои. */

/* Название компании на мини-карточке стало ссылкой на её страницу (ТЗ 44b). В
   макете это простой текст, и подчёркивание с синим цветом сделали бы из
   подписи вторую кнопку рядом с «Подробнее». */
.catalog_name a {
    color: inherit;
    text-decoration: none;
}

.catalog_name a:hover {
    text-decoration: underline;
}

/* Подкатегории раздела стоят полосой плашек над сеткой: ими человек сужает
   выдачу, не возвращаясь в каталог. Плашка та же, что у меток задания, — своего
   вида ей не заводится, — но она ссылка, и цвет текста в ней наследуется. */
a.catalog_tag {
    color: inherit;
    text-decoration: none;
}

a.catalog_tag:hover {
    background: #E8E8F5;
}

/* Заголовок раздела в колонках каталога — ссылка на страницу этого раздела. В
   макете это подпись без адреса. */
.sitemap_item > div > a {
    color: inherit;
    text-decoration: none;
}

.sitemap_item > div > a:hover {
    text-decoration: underline;
}

/* Строка «Или напишите на …» под кнопкой формы поддержки: адрес нужен тому,
   у кого форма не отправляется, и стоять он обязан там же, где кнопка. */
.cf_note {
    margin-top: 10px;
    font-size: 14px;
    text-align: center;
    color: rgba(37, 30, 74, 0.5);
}

/* Файл к обращению (форма поддержки и окно «Задать вопрос»). Вёрстка прячет
   input display: none — с клавиатуры до него тогда не дойти. Здесь он сведён
   к пикселю под подписью, а фокус рисуется на подписи-кнопке. */
.contacts_form_btn_item {
    position: relative;
}

.contacts_form_btn_item input[type='file'] {
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.contacts_form_btn_item input[type='file']:focus-visible + label {
    outline: 2px solid #3261EC;
    outline-offset: 2px;
}

/* Строка под подписью: имя выбранного файла с крестиком или отказ по нему.
   У вёрстки строка узкая (200px, «Файл загружен»), имя файла в неё не
   влезает — она растягивается на ширину колонки, длинное имя режется
   многоточием. */
.contacts_form_btn_item .file_check {
    width: auto;
    max-width: 100%;
    margin: 15px 0 0;
    font-size: 16px;
}

.contacts_form_btn_item .file_name {
    display: flex;
    align-items: center;
    gap: 8px;
}

.contacts_form_btn_item .file_name_text {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.contacts_form_btn_item .file_remove {
    flex: none;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 0;
    background: url("../images/ico-close-red.svg") no-repeat center;
    background-size: 12px auto;
    cursor: pointer;
}

.contacts_form_btn_item .file_remove:focus-visible {
    outline: 2px solid #3261EC;
    border-radius: 50%;
}

.contacts_form_btn_item .file_error {
    color: #e5484d;
}

/* Строка «в этом разделе пока нет заданий» и её соседи по пустым страницам.
   Вёрстка подзаголовок под заголовком описывает, а отдельно стоящий — нет:
   без отступа он прилипает к сетке сверху. */
.inner_title + .inner_title {
    margin-top: 24px;
}

/* Выбранный город в шапке. В макете подпись «Ваш город» неактивна, а выбранный
   город показывается только галочкой в списке — то есть человеку, закрывшему
   список, не видно, что выдача сужена. */
.tm_menu ul li a.active {
    font-weight: 600;
}

/* ── Публичные страницы: заявка на звонок, полоса о cookie, переносы строк,
      клавиатура ─────────────────────────────────────────────────────────── */

/* Контейнер острова, выключенный из раскладки: остров заявки на звонок рисует
   <form class="bottom_form">, и flex-ряд bottom_forma обязан видеть форму, а
   не обёртку вокруг неё, — ширина формы (510px) и её прижатие вправо написаны
   вёрсткой под .bottom_form. */
.island_contents {
    display: contents;
}

/* Отказ поля заявки — той же красной рамкой, что у полей остальных форм
   (.cf_input.has_error): поле вёрстки здесь своё, bf_input. */
.bf_input.has_error {
    border: 1px solid #E02B2B;
}

/* Строка «Телефон | E-mail»: в вёрстке поля выровнены по центру, и строка
   отказа под одним из них сдвигала бы соседнее поле вниз. По верху — то же
   самое, пока отказов нет: поля одной высоты. */
.bf_line {
    align-items: flex-start;
}

/* Галочка согласия. Вёрстка прячет настоящий checkbox (display: none) и
   рисует коробку псевдоэлементом подписи — такой checkbox не получает фокус:
   с клавиатуры до него не дойти, и после отказа «без согласия» фокус к нему
   не вернуть. Здесь он остаётся невидимым, но в потоке фокуса; рамку фокуса
   получает нарисованная коробка. */
.bf_check input[type='checkbox'] {
    display: block;
    position: absolute;
    left: 0;
    top: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.bf_check input[type='checkbox']:focus-visible + label:before {
    outline: 2px solid #3261EC;
    outline-offset: 2px;
}

/* Полоса «Данный сайт использует файлы cookie». Вёрстка её прячет
   (display: none) и не показывает никогда; показывает модуль
   site/cookieBanner.ts этим классом, пока человек не нажал «Согласен». */
.cookie_block.is_shown {
    display: block;
}

/* Переносы строк в тексте, который пишут люди: формулировка задания,
   описание компании, отзыв. Разметка макета — один <p> (или div) на текст, и
   без этого правила абзацы, которые человек разделил переносом, склеивались в
   одну строку. pre-line, а не pre-wrap: пробелы схлопываются как обычно,
   сохраняются только переносы. */
.card_item_main h2 + p,
.seo_circle_bg .agreement_item p,
.review_slide_text {
    white-space: pre-line;
}

/* Ссылки-кнопки вёрстки без адреса стали доступны с клавиатуры
   (site/keyboardButtons.ts), а вёрстка снимает рамку фокуса у всего
   (`* { outline: none }`). Рамка возвращается только на фокус с клавиатуры —
   мышью вид прежний. */
[data-keyboard-button]:focus-visible {
    outline: 2px solid #3261EC;
    outline-offset: 2px;
}

/* Раздел каталога таблицей (макет 03b-category-table.html, «?view=table»).

   Переключатель «Карточками / Таблицей» — вёрсточные радиокнопки reg_check:
   своего в макетах нет. Вёрстка прячет радиокнопку (display: none) и рисует
   кружок псевдоэлементом подписи — такая радиокнопка не получает фокус, и с
   клавиатуры вид было бы не выбрать. Тот же приём, что у галочки согласия:
   невидимая, но в потоке фокуса, а рамку получает нарисованный кружок. */
.catalog_view .reg_check_block input[type='radio'] {
    display: block;
    position: absolute;
    left: 0;
    top: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.catalog_view .reg_check_block input[type='radio']:focus-visible + label:before {
    outline: 2px solid #3261EC;
    outline-offset: 2px;
}

/* Подпись — ссылка на тот же адрес (дорога без скрипта), и выглядеть она
   обязана подписью радиокнопки, а не ссылкой. */
.catalog_view label a {
    color: inherit;
}

/* Заголовок, по которому сортируют. В вёрстке у table_sorting_block нет ни
   стрелки, ни состояния — макет сортировку не нарисовал. Стрелка — та же
   синяя «вниз», что у раскрывающихся коробок; у выбранного столбца она
   видна всегда и смотрит в сторону порядка, у остальных проявляется при
   наведении — заголовок нажимается, и это должно быть видно до нажатия. */
.catalog_sort {
    display: inline-flex;
    align-items: center;
    color: inherit;
}

.catalog_sort:hover {
    color: #3261EC;
}

.catalog_sort::after {
    content: '';
    flex: none;
    width: 12px;
    height: 7px;
    margin-left: 8px;
    background: url("../images/ico-arrow-down-blue.svg") no-repeat center center;
    background-size: 100% auto;
    opacity: 0;
}

.catalog_sort:hover::after {
    opacity: 0.4;
}

.catalog_sort.is_asc::after,
.catalog_sort.is_desc::after {
    opacity: 1;
}

.catalog_sort.is_asc::after {
    transform: rotate(180deg);
}

/* «Только с медкнижкой» под описанием — тот же красный, что у плашки
   мини-карточки (.catalog_tag_red). */
.catalog_table_red {
    color: #C62828;
    font-size: 16px;
}

/* Стрелка навигации на краю списка: адреса у неё нет, но с места она не
   уходит, чтобы полоса номеров не прыгала. Приглушена — иначе выглядела бы
   нажимаемой. */
.pagination_full .pagination_prev:not([href]),
.pagination_full .pagination_next:not([href]) {
    opacity: 0.3;
    cursor: default;
}

/* Таблица заданий (24z): период в календаре вёрстки. У datepicker jQuery UI
   вида для диапазона нет — дни помечает модуль lk/taskTable.ts классами через
   beforeShowDay. Середина — заливкой светлой кнопки «Очистить», края — синим
   выбранного дня вёрстки (.ui-state-active). !important — потому что им
   вёрстка гасит фон всех дней (.ui-state-default). */
.lk_tasks_calendar .ui-datepicker td.task_table_range a.ui-state-default {
    background: #EBEDF7 !important;
}

.lk_tasks_calendar .ui-datepicker td.task_table_range_edge a.ui-state-default {
    background: #3261EC !important;
    color: #fff !important;
}

/* «Назад» и «Дальше» на краю списка стоят без адреса, как в макете, и
   приглушены — иначе выглядели бы нажимаемыми. */
.pagination_lk .p_lk_btn:not([href]) {
    opacity: 0.3;
    cursor: default;
}

/* Сотрудники, роли и доступы (остров profile-staff, макет 23b).

   Строки — разметка макета: `lk_mi_line`, `msb_item`, `cf_input`, `access_btn`.
   Своего здесь три вещи. Отступ группы от заголовка — тот же, что у объектов.
   Черта между сотрудниками: у каждого по две строки полей, и без неё строки
   соседей сливались бы в одну таблицу. И запертые поля без замка
   (`lk_staff_value`): замок означает «меняет служба поддержки», а у сотрудника
   рядом стоит «Изменить доступ» — тот же довод, что у поля пароля в учётной
   записи. */
.lk_staff {
    margin-top: 20px;
}

.lk_staff_member + .lk_staff_member {
    margin-top: 20px;
    padding-top: 10px;
    border-top: 1px solid rgba(37, 30, 74, 0.1);
}

.cf_input[readonly].lk_staff_value {
    background-image: none;
    padding-right: 46px;
}

/* Кнопки строки — `<button>`, а не `<a>` макета: они не ведут по адресу и с
   клавиатуры обязаны нажиматься сами. Браузерные рамка и шрифт кнопки
   снимаются, вид остаётся тем, что задала вёрстка. */
.lk_staff .access_btn {
    border: 0;
    font-family: inherit;
    color: inherit;
    cursor: pointer;
}

.lk_staff .access_btn:hover,
.lk_staff .access_btn:focus-visible {
    color: #fff;
}

/* Крестик снятия в вёрстке проявляется на наведении (`.msb_item:hover`), и на
   телефоне его не видно вовсе. Здесь он приглушён, но виден всегда — тот же
   размен, что у крестика объектов. */
.lk_staff .ab_del {
    border: 0;
    padding: 0;
    opacity: .55;
    cursor: pointer;
}

.lk_staff .msb_item:hover .ab_del,
.lk_staff .ab_del:hover,
.lk_staff .ab_del:focus-visible {
    opacity: 1;
}

.lk_staff .ab_del:disabled {
    opacity: .25;
    cursor: default;
}

/* Подсказка вместо списка объектов в окне: объектов нет, и привязать
   сотрудника некуда. Размер и цвет — у пустого списка объектов. */
.lk_staff_note {
    font-size: 16px;
    color: #3F4A56;
    margin: 0;
}

/* Список объектов в окне открывает React (`active`), а не скрипт вёрстки, —
   тот вешает обработчики на узлы, которые были при загрузке. Пункты — те же
   `<a>` вёрстки, и курсор им нужен явно: адреса у них нет. */
.contacts_form .msb_select_toggle a[role="option"] {
    cursor: pointer;
}

/* Лента отзывов (главная, страница компании): слайды одной высоты.

   В макете тексты отзывов одной длины, и ровный ряд там получался сам. Живые
   отзывы разные — бывает и пустой (оценка обязательна, текст нет), — и слайды
   Swiper росли каждый по своему содержимому. Слайд тянется на высоту ряда,
   а строка автора прижимается к низу: текст забирает свободное место.
   Заголовок и текст обрезаются многоточием, как в макете («способствует ...»),
   иначе один длинный отзыв вытянул бы под себя весь ряд. */
#swiper-rev .swiper-slide {
    display: flex;
    height: auto;
}

.review_slide {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
}

.rs_title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
}

.review_slide_text {
    flex-grow: 1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    overflow: hidden;
}

/* Фотография автора — круг. В макете снимки квадратные, а загруженный
   человеком файл бывает любым: без обрезки круг стал бы овалом. */
.review_slide_img img,
.review_slide_noimg {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    border-radius: 50%;
    object-fit: cover;
}

/* Заглушка вместо фотографии у того, кто её не поставил: в макете на этом
   месте всегда снимок, а пустое место сдвигало имя и выглядело недогрузкой. */
.review_slide_noimg {
    background: #E9EEF3 url('/static/images/ico-person-grey.svg') center / 50% auto no-repeat;
}

/* Строка метрик главной: плитки одной высоты. В макете у всех подписей по две
   строки, а живая «средний чек задания» — в одну, и плитка выходила ниже
   соседних. */
.advantage_item_wp {
    display: flex;
}

.advantage_item {
    flex: 1;
}

/* ── Публикации ──────────────────────────────────────────────────────────
   Рубрика и название на карточке каталога — ссылки (в макете это div без
   адреса): цвет и подчёркивание берутся у подписи, а не у ссылки. */
.pi_category a,
.publication_text a {
    color: inherit;
    text-decoration: none;
}

.publication_text a:hover {
    color: #3261EC;
}

/* Обложка карточки заполняет её целиком в пропорции макета. В выгрузке у
   картинки нет ни ширины, ни пропорции: макет держится на снимках, нарезанных
   ровно 380×225 (каталог, главная) и 150×150 («Анонсы публикаций»), а обложку
   из консоли присылают какую угодно — маленькая вставала в натуральную величину,
   вытянутая ломала ряд. */
.publication_img img {
    display: block;
    width: 100%;
    aspect-ratio: 380 / 225;
    object-fit: cover;
}

.publications_block_v3 .publication_img img {
    aspect-ratio: 1;
}

/* Обложка статьи — фон блока с названием. В макете картинка подобрана под
   блок, а загруженная консолью бывает любой: без cover она легла бы плиткой. */
.article_top_block {
    background-size: cover;
    background-position: center;
}

/* Счётчики под заголовком статьи: просмотры и рейтинг — не ссылки, но
   выглядят так же, как ссылка на комментарии. */
span.pl_link {
    cursor: default;
}

/* Текст статьи из редактора консоли: картинка не шире колонки, у ссылки —
   цвет сайта. */
.agreement_item img {
    max-width: 100%;
    height: auto;
}

.agreement_item a {
    color: #3261EC;
}

/* Комментарий: переносы строк, которые набрал человек, сохраняются. */
.comment_text {
    white-space: pre-line;
    overflow-wrap: anywhere;
}

/* Скрытый модератором комментарий — отметка вместо текста. */
.comment_hidden {
    color: #9AA6B2;
    font-style: italic;
}

/* Оценка статьи звёздами рядом с автором. В макете это картинка с пятью
   полными звёздами; у живого комментария звёзд бывает меньше пяти. */
.comment_stars {
    width: auto;
    color: #F5B301;
    font-size: 18px;
    letter-spacing: 2px;
    white-space: nowrap;
}

/* Голос читателя: нажатая стрелка заметна. Неактивная (свой комментарий,
   аноним) — бледнее и без указателя. */
.cbt_reaction a.active {
    border-color: #3261EC;
    background-color: #EAF0FD;
}

.cbt_reaction a[aria-disabled="true"] {
    opacity: .4;
    cursor: default;
}

/* Фото автора комментария — то же правило, что у ленты отзывов. */
.cbt_img img {
    display: block;
    width: 60px;
    aspect-ratio: 1;
    object-fit: cover;
}

.cbt_img .review_slide_noimg {
    width: 60px;
    border-radius: 5px;
}

/* Поле реплики мессенджера — textarea вместо однострочного input макета:
   длинная реплика переносится, а поле растёт вниз под текст (lk/messenger.ts)
   до предела и дальше прокручивается.

   Справа отступ обычный, а не 110px макета: там он оставлен под смайлик и
   скрепку, которых на бирже нет, и текст обрывался, не дойдя до края поля.
   Высоту задаёт вёрстка (50px, на телефоне 32px) — здесь только строка и
   отступы, рассчитанные так, чтобы одна строка стояла в ней по центру. */
textarea.chat_message_input {
    display: block;
    resize: none;
    overflow-y: auto;
    padding: 12px 20px;
    line-height: 24px;
}

@media only screen and (max-width: 767px) {
    textarea.chat_message_input {
        padding: 7px 15px;
        line-height: 16px;
    }
}

/* На широком экране кнопка вёрстки занимает 200px из колонки шириной около
   500px, и поле оставалось узким. Кнопке хватает 150px — слово «Отправить»
   помещается с запасом, — а освободившееся место отдаётся полю. На узких
   экранах вёрстка сама раскладывает строку иначе (media.css), их не трогаем. */
@media only screen and (min-width: 1270px) {
    #chat_form .chat_message_input_block {
        width: calc(100% - 165px);
    }

    #chat_form .chat_message_btn {
        width: 150px;
    }
}

/* Выросшее поле тянет строку вниз, а кнопка остаётся у его нижнего края —
   там, где курсор, а не посередине многострочного текста. */
#chat_form {
    align-items: flex-end;
}

/* Переносы, набранные в реплике, доезжают до собеседника: без этого правила
   абзацы склеивались бы в строку, а длинное слово или ссылка вылезали за
   пузырь. */
.chat_line_text p {
    white-space: pre-line;
    overflow-wrap: anywhere;
}

/* Переписка с биржей в списке мессенджера: вместо фотографии — знак логотипа.
   Он не квадратный снимок, а рисунок, поэтому вписывается целиком на белом
   поле с рамкой, а не обрезается по краям, как лицо собеседника. */
.chat_block_img .chat_block_logo {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    object-fit: contain;
    padding: 18px;
    background: #FFFFFF;
    border: 1px solid #E1E8F0;
}

/* Карта заданий (ТЗ 42e, 44d; site/tasksMap.ts). Метка нажимается — в отличие
   от метки выбора адреса, — и рядом с ней встаёт копия мини-карточки из
   выдачи. Ширина карточки — как у её колонки в сетке. */
.tasks_map_marker {
    pointer-events: auto;
    cursor: pointer;
    position: relative;
}

.tasks_map_card {
    position: absolute;
    left: 50%;
    bottom: 44px;
    transform: translateX(-50%);
    width: 320px;
    max-width: calc(100vw - 32px);
    cursor: default;
    z-index: 2;
}

.tasks_map_card .catalog_item {
    background: #fff;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
}

/* Карта на весь экран (кнопка «Посмотреть на карте»): блок раскрывается, а
   полоса карты занимает его целиком. */
.catalog_map:fullscreen {
    height: 100vh;
    margin-top: 0;
    background: #fff;
}

/* Станция метро на мини-карточке — ссылка на страницу станции (42h): цвет
   строки остаётся вёрсточным. */
a.subway_item {
    color: inherit;
    text-decoration: none;
}

/* ── Фото паспорта работодателя ─────────────────────────────────────────────
   Плитки под полями паспорта: плитка и есть кнопка (нажал — выбрал —
   загрузилось, стоит превью). */
.passport_tiles_hint {
    margin-top: 10px;
}

.passport_tiles {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
    max-width: 820px;
    margin: 15px 0 10px;
}

.passport_tile_cell {
    position: relative;
    min-width: 0;
}

/* Поле файла — невидимое, но доступное с клавиатуры: фокус рисуется на
   плитке рядом. */
.passport_tile_input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.passport_tile {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border: 1.5px dashed #BAC8D6;
    border-radius: 10px;
    background: #F7F9FC;
    cursor: pointer;
    transition: border-color .15s, background-color .15s;
}

label.passport_tile:hover {
    border-color: #3261EC;
    background: #F2F5FE;
}

.passport_tile_input:focus-visible + .passport_tile {
    outline: 2px solid #3261EC;
    outline-offset: 3px;
}

.passport_tile.is_filled {
    border-style: solid;
    border-color: #E1E7EF;
    background: #F7F9FC;
}

/* Запертая — паспорт принят: только превью, нажимать нечего. */
.passport_tile.is_locked {
    cursor: default;
}

/* Фото вписано целиком, без обрезки: на скане паспорта важны края — серия,
   номер, подпись. */
.passport_tile img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.passport_tile.is_invalid {
    border-color: #E02B2B;
}

/* Пустая — «+ Добавить фото» в центре; заполненная — «Заменить» полосой
   снизу, только при наведении и фокусе: превью не закрыто подписью. */
.passport_tile_hint {
    font: 500 16px/1.3 'Gilroy', sans-serif;
    color: #3261EC;
}

.passport_tile:not(.is_filled) .passport_tile_hint::before {
    content: '+';
    display: block;
    margin-bottom: 2px;
    font-size: 30px;
    font-weight: 400;
    line-height: 1;
    text-align: center;
}

.passport_tile.is_filled .passport_tile_hint {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 8px 12px;
    background: rgba(26, 26, 26, .72);
    color: #FFFFFF;
    text-align: center;
    opacity: 0;
    transition: opacity .15s;
}

label.passport_tile.is_filled:hover .passport_tile_hint,
.passport_tile_input:focus-visible + .passport_tile.is_filled .passport_tile_hint,
.passport_tile.is_busy .passport_tile_hint {
    opacity: 1;
}

.passport_tile.is_busy {
    cursor: progress;
}

.passport_tile_input[aria-disabled='true'] + .passport_tile:not(.is_busy) {
    opacity: .6;
    cursor: default;
}

.passport_tile_caption {
    margin-top: 8px;
    font: 400 16px/1.3 'Gilroy', sans-serif;
    color: #1A1A1A;
}

/* На сенсорном экране наведения нет: «Заменить» на заполненной плитке видно
   всегда, иначе превью не говорит, что на него можно нажать. */
@media (hover: none) {
    .passport_tile.is_filled .passport_tile_hint {
        opacity: 1;
    }
}

@media (max-width: 767px) {
    .passport_tiles {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 12px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .passport_tile,
    .passport_tile_hint {
        transition: none;
    }
}

/*
 * Пометка «Адрес не подтверждён» под почтой в «Учётной записи». Классы подписи
 * и ссылки — из формы входа (code_text, code_link), где они стоят по центру;
 * здесь строка относится к полю слева и встаёт под ним.
 */
.lk_email_unconfirmed {
    text-align: left;
    margin-top: -10px;
}

/*
 * Регистрация: окно «Подтвердите номер». Подсказки взяты из формы входа
 * (.code_text, .code_link); в окне они стоят по центру над полем кода, как там.
 */
.reg_code_form .code_text {
    text-align: center;
}

.reg_code_form .code_text:first-child {
    margin-top: 10px;
}

.reg_code_form .contacts_form_item {
    margin-top: 20px;
}

.reg_code_form .reg_btn {
    margin: 0 auto;
}

.reg_code_form .code_link {
    text-align: center;
    margin-top: 16px;
}

/*
 * Регистрация: номер и его подтверждение одной строкой. Поле забирает всё,
 * что осталось от кнопки; высота кнопки и отметки — высота поля (.cf_input),
 * чтобы строка не прыгала, когда кнопку сменяет отметка.
 */
.reg_phone {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.reg_phone .reg_phone_field {
    flex: 1;
    min-width: 0;
}

.reg_phone_confirm {
    flex-shrink: 0;
    height: 50px;
    padding: 0 24px;
    border-radius: 10px;
    font-size: 18px;
}

.reg_phone_ok {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    height: 50px;
    font-size: 18px;
    font-weight: 500;
    color: #1f8a4c;
    white-space: nowrap;
}

.reg_phone_ok::before {
    content: '✓';
    margin-right: 6px;
}

@media (max-width: 767px) {
    .reg_phone_confirm {
        padding: 0 14px;
        font-size: 16px;
    }

    .reg_phone_ok {
        font-size: 16px;
    }
}

/*
 * Договор с биржей в профиле работодателя и окно кода подписи
 * (docs/v2/document-signing.md). Полоса — та же lk_top_att, что у активации:
 * договор, ждущий подписи, — такое же «сделайте это», и выглядеть иначе ему
 * незачем. Подписанный — спокойнее, без тревожного цвета.
 */
.platform_contract p {
    margin: 0 0 12px;
}

.platform_contract_actions {
    flex-wrap: wrap;
    gap: 12px 24px;
}

.platform_contract_actions a {
    text-decoration: underline;
}

.platform_contract_actions .lk_account_btn {
    width: auto;
    padding: 0 24px;
}

.lk_top_att.platform_contract_done {
    background: #f3f6f9;
    color: inherit;
}

.sign_dialog p {
    margin: 0 0 12px;
}

.sign_dialog a {
    text-decoration: underline;
}

.sign_dialog_field {
    max-width: 280px;
    margin: 16px auto 0;
}

.sign_dialog_notice {
    color: #1f8a4c;
    text-align: center;
}
