/*
    Оформление новой версии — страниц подбора, карточки и переписки.

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

/* ===== Фон =====
   Плоский белый лист выглядит незаконченным. Два размытых пятна в цветах
   сервиса дают глубину и не мешают читать: они прибиты к экрану (fixed) и не
   ползут за содержимым. */
.app-body {
    background:
        radial-gradient(60vw 60vw at 12% -8%, rgba(124, 58, 237, .16), transparent 62%),
        radial-gradient(52vw 52vw at 96% 10%, rgba(219, 39, 119, .13), transparent 60%),
        radial-gradient(70vw 70vw at 50% 108%, rgba(8, 145, 178, .10), transparent 62%),
        var(--bg);
    background-attachment: fixed;
    min-height: 100vh;
}

/* Общее правило лендинга даёт каждому section по 84 пикселя сверху и снизу.
   Здесь секции идут подряд, и между ними зияли дыры в полэкрана.
   Панели исключены нарочно: они тоже section, и правило по тегу оказывалось
   сильнее их собственного класса — панели оставались вовсе без полей, а текст
   внутри упирался в рамку. Ровно это и было видно на первом экране. */
.app-page section:not(.app-panel):not(.p-panel) { padding: 0; }

/* ===== Карточка-панель ===== */
.app-panel {
    background: rgba(255, 255, 255, .72);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(124, 58, 237, .14);
    border-radius: 18px;
    padding: 1rem 1.1rem;
    margin-bottom: .9rem;
    box-shadow: 0 6px 24px rgba(76, 29, 149, .06);
}

/* Строка ошибки держит под себя место всегда: восемнадцать пикселей высоты плюс
   четырнадцать отступа сверху. Под панелью участия, где ошибки не бывает почти
   никогда, это тридцать два пикселя пустоты на самом верху страницы — и человек
   видит их каждый раз, а саму ошибку не увидит, скорее всего, ни разу. Пустой
   строке место не нужно: она появится вместе с текстом. */
.app-body .demo-error:empty { min-height: 0; margin-top: 0; }

.app-label { font-weight: 700; margin-bottom: .5rem; }
.app-hint { opacity: .7; font-size: .85rem; margin: .4rem 0 0; }
.app-row { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.app-row + .app-row { margin-top: .9rem; }

/* ===== Чипы вместо галочек =====
   Нативный квадратик рядом с текстом выглядит как форма из двухтысячных.
   Прячем его совсем (но оставляем доступным с клавиатуры) и рисуем состояние
   самим чипом: выбранный залит и обведён, у него своя галочка. */
.app-chip {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    padding: .5rem .9rem;
    border-radius: 999px;
    border: 1.5px solid rgba(124, 58, 237, .28);
    background: #fff;
    font-weight: 600;
    font-size: .92rem;
    cursor: pointer;
    user-select: none;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.app-chip input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
}

.app-chip::before {
    content: "";
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 1.5px solid rgba(124, 58, 237, .45);
    background: #fff;
    flex: 0 0 auto;
    transition: background .15s ease, border-color .15s ease;
}

.app-chip.on {
    background: linear-gradient(120deg, rgba(124, 58, 237, .14), rgba(219, 39, 119, .12));
    border-color: var(--violet, #7C3AED);
}

.app-chip.on::before {
    background: var(--violet, #7C3AED) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/12px no-repeat;
    border-color: var(--violet, #7C3AED);
}

.app-chip:focus-within { outline: 2px solid rgba(124, 58, 237, .45); outline-offset: 2px; }

/* ===== Списки выбора =====
   Своя стрелка вместо системной: нативный вид разный в каждом браузере, и в
   одном из них он всегда выбивается из остальной страницы. */
.app-select,
.app-body select {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    padding: .7rem 2.2rem .7rem .9rem;
    border: 1.5px solid rgba(124, 58, 237, .28);
    border-radius: 14px;
    background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5 8l5 5 5-5' fill='none' stroke='%237C3AED' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") right .7rem center/18px no-repeat;
    font-family: var(--font);
    font-size: 15px;
    font-weight: 600;
    color: inherit;
    cursor: pointer;
}

.app-body input[type="number"] {
    width: 5.2rem;
    padding: .55rem .7rem;
    border: 1.5px solid rgba(124, 58, 237, .28);
    border-radius: 12px;
    font-family: var(--font);
    font-size: 15px;
    background: #fff;
}

/* Ползунок: в браузере он серый по умолчанию — accent-color красит его в цвет
   сервиса одной строкой и в дорожке, и в бегунке. */
.app-body input[type="range"] {
    width: 100%;
    accent-color: var(--violet, #7C3AED);
}

/* ===== Аватар =====
   Пока фотографий нет — буква имени на градиенте по полу. Список людей без
   лиц читается как таблица, а не как люди. */
.app-avatar {
    /* Цвет по умолчанию нужен там, где пол собеседника неизвестен, — в списке
       разговоров его неоткуда взять, а бесцветный кружок читается как
       незагрузившаяся картинка. */
    background: linear-gradient(135deg, #7C3AED, #DB2777);
    width: 46px;
    height: 46px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 800;
    font-size: 1.1rem;
    flex: 0 0 auto;
    overflow: hidden;
}

/* Кружок центрирует букву имени, и та же расстановка сжимала снимок по
   содержимому — по краю оставалась полоска подложки, читавшаяся как
   незагрузившаяся картинка. Снимку велено занять кружок целиком. */
.app-avatar img { width: 100%; height: 100%; object-fit: cover; align-self: stretch; }
.app-avatar-female { background: linear-gradient(135deg, #EC4899, #F472B6); }
.app-avatar-male { background: linear-gradient(135deg, #6366F1, #7C3AED); }
.app-avatar-lg { width: 86px; height: 86px; font-size: 2rem; }

/* ===== Карточки людей =====
   Квадратный кадр сверху, подписи под ним. Кружок в сорок шесть пикселей
   читался таблицей, а снимок узкой полосой сбоку резал лицо по краям: на
   квадрате человек виден целиком, и на телефоне их помещается двое в ряд. */
.app-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: .75rem; }

/* Карточка-призрак (.sk-*, loading.css) стоит в тех же правилах, что настоящая,
   а не в своих похожих. Разъехавшись хоть на пиксель, они дёрнут страницу в
   момент подмены — и человек ткнёт пальцем не в ту анкету. Отличия призрака
   собраны отдельно, в loading.css: их три строки. */
.app-card,
.sk-card {
    display: flex;
    flex-direction: column;
    background: rgba(255, 255, 255, .78);
    border: 1px solid rgba(124, 58, 237, .14);
    border-radius: 18px;
    overflow: hidden;
    box-shadow: 0 6px 20px rgba(76, 29, 149, .05);
    /* Нажимается вся карточка — курсор обязан об этом сказать. */
    cursor: pointer;
}

.app-card:hover { border-color: rgba(124, 58, 237, .34); }
.app-card:focus-visible { outline: 2px solid var(--violet, #7C3AED); outline-offset: 2px; }

/* Квадрат: у кадра другой формы лицо либо обрезано по бокам, либо занимает
   пол-экрана высоты. */
.app-face,
.sk-face {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #7C3AED, #DB2777);
}

/* Снимок вынут из потока: в потоке он тянул кадр по своей высоте — вертикальная
   фотография вытягивала квадрат в полосу, и квадратным он оставался только в
   стилях. */
.app-face img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.app-face-letter { color: #fff; font-weight: 800; font-size: 2.6rem; }
.app-face-female { background: linear-gradient(135deg, #EC4899, #F472B6); }
.app-face-male { background: linear-gradient(135deg, #6366F1, #7C3AED); }

.app-card-body,
.sk-body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
    padding: .6rem .7rem .7rem;
}

.app-name,
.sk-name { font-weight: 700; font-size: 1rem; overflow-wrap: anywhere; }
.app-meta,
.sk-meta { opacity: .7; font-size: .85rem; }

.app-demo {
    display: inline-block;
    margin-left: .35rem;
    padding: .1rem .45rem;
    border-radius: 999px;
    font-size: .68rem;
    background: rgba(0, 0, 0, .07);
    vertical-align: middle;
}

/* Процент — главное число карточки. Он стоит на самом снимке: в подписях под
   ним он отнимал у карточки целую строку, а вместе с пояснением — две. */
.app-total {
    position: absolute;
    right: .4rem;
    bottom: .4rem;
    padding: .2rem .5rem;
    border-radius: 999px;
    font-size: .95rem;
    font-weight: 800;
    line-height: 1.25;
    font-variant-numeric: tabular-nums;
    color: #fff;
    background: rgba(23, 16, 43, .62);
    backdrop-filter: blur(3px);
}

/* Крестик «не показывать» — в углу снимка. Мелкий и полупрозрачный: это не
   главное действие карточки, но и прятать его в меню незачем — решение «не моё»
   принимают за секунду, глядя на лицо. */
.app-hide {
    position: absolute;
    top: .4rem;
    right: .4rem;
    width: 28px;
    height: 28px;
    border: none;
    border-radius: 50%;
    background: rgba(23, 16, 43, .45);
    color: #fff;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    opacity: .8;
    -webkit-tap-highlight-color: transparent;
}

.app-hide:hover { background: rgba(23, 16, 43, .75); opacity: 1; }
.app-hide:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* Сердечко «сохранить» — в противоположном углу того же снимка. Два действия
   одной карточки, и они противоположны по смыслу: слева отложить, справа
   убрать. Рядом их ставить нельзя — промах пальцем стоил бы человеку анкеты. */
.app-fav {
    position: absolute;
    top: .4rem;
    left: .4rem;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: rgba(23, 16, 43, .45);
    color: #fff;
    padding: 0;
    cursor: pointer;
    opacity: .85;
    -webkit-tap-highlight-color: transparent;
}

.app-fav svg { width: 16px; height: 16px; display: block; }

/* Контур — не сохранено, заливка — сохранено. Пустое и полное сердце человек
   различает мгновенно и без подписи; менять на «сохранено» цвет фона значило бы
   объяснять состояние оттенком поверх чужой фотографии. */
.app-fav svg path { fill: none; stroke: #fff; stroke-width: 2; }
.app-fav.is-on { background: rgba(219, 39, 119, .92); opacity: 1; }
.app-fav.is-on svg path { fill: #fff; stroke: #fff; }
.app-fav:hover { background: rgba(23, 16, 43, .75); opacity: 1; }
.app-fav.is-on:hover { background: rgba(219, 39, 119, 1); }
.app-fav:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* Пустой раздел — объяснение, а не пустая страница. Человек, впервые открывший
   «Избранное», должен узнать, чем его наполнить, а не решить, что раздел не
   работает. */
.app-blank { text-align: center; padding: 2rem 1rem; }
.app-blank-mark { font-size: 2.4rem; line-height: 1; }
.app-blank p { margin: .8rem auto 1.2rem; max-width: 34ch; opacity: .75; line-height: 1.5; }

/* Оси в один ряд равными долями: разной ширины столбики читались как ошибка. */
.app-axes,
.sk-axes { display: grid; grid-template-columns: repeat(3, 1fr); gap: .3rem; margin-top: .5rem; }
.app-axis,
.sk-axis { background: rgba(124, 58, 237, .07); border-radius: 10px; padding: .3rem .2rem; text-align: center; }
.app-axis b,
.sk-axis b { display: block; font-variant-numeric: tabular-nums; font-size: .85rem; }
.app-axis span,
.sk-axis span { display: block; font-size: .65rem; opacity: .75; overflow: hidden; text-overflow: ellipsis; }

/* Кнопка прижата к низу карточки: у соседей разной высоты она должна стоять на
   одной линии, иначе ряд выглядит сломанным. Кнопка одна — «Открыть» больше
   нет, анкета открывается нажатием на саму карточку. */
.app-open,
.sk-open { margin-top: auto; padding-top: .6rem; }
.app-open a,
.sk-open .btn { display: block; text-align: center; padding: .45rem .3rem; font-size: .85rem; }

/* ===== Списки людей =====
   Найденное по запросу, остальные из того же поиска и подобранное нами — три
   разных ответа на три разных вопроса. Сплошным списком они читались как один,
   и человек не понимал, где кончается ответ на его запрос. */
.app-group + .app-group,
#app-recommended-block { margin-top: 1.6rem; padding-top: 1.2rem; border-top: 1px solid rgba(124, 58, 237, .16); }

.app-group-title { margin: 0 0 .6rem; font-weight: 800; font-size: 1.05rem; }
.app-group-hint { margin: -.35rem 0 .7rem; font-size: .85rem; opacity: .7; }
.app-count { opacity: .7; font-size: .85rem; margin-top: .6rem; }

/* Пустой результат — объяснение, а не заголовок. Заголовок называет список
   одним словом; здесь же на месте заголовка стоит трёхстрочное предложение, и
   восьмисотым весом оно кричит там, где надо спокойно сказать, почему список
   пуст. Тот же элемент, но с этим классом, читается как речь, а не как вывеска. */
.app-empty {
    margin: 0 0 .6rem;
    font-weight: 400;
    font-size: .9rem;
    line-height: 1.45;
    opacity: .75;
}

/* На ноутбуке карточек в ряд больше, и они не должны мельчать до значков. */
@media (min-width: 761px) {
    .app-cards { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
}


/* ===== Место под фотографии =====
   Загрузка появится позже, но место под неё видно уже сейчас: знакомство
   начинается с лица, и пустая карточка без него выглядит недоделанной. */
.app-photos { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem; }

.app-photo {
    aspect-ratio: 3 / 4;
    border-radius: 14px;
    border: 1.5px dashed rgba(124, 58, 237, .3);
    background: rgba(124, 58, 237, .05);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    opacity: .55;
}

/* Ссылки-кнопки справа в шапке дублируют разделы, которые теперь стоят в её
   середине. На телефоне верхнего меню нет, и там они по-прежнему нужны —
   поэтому убираем только на широком экране. */
@media (min-width: 761px) {
    .app-body .nav-actions .btn-nav { display: none; }
}
