/*
 * Общие элементы дизайн-системы: кнопки, поля, сообщения.
 *
 * Файл подключают и оболочка приложения, и лендинг — поэтому кнопка описана
 * здесь один раз, а не по копии в каждом. Экранные стили сюда не складываем.
 */

/* кнопки */
.btn {
    display: inline-block;
    padding: 16px 32px;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--grad-accent);
    color: var(--c-white);
    font: inherit;
    font-weight: 700;
    font-size: 17px;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}

/*
 * Белый текст на фуксии не набирает 4.5:1 (замеры на этапе 1), поэтому на
 * кнопках он только крупный и жирный — для такого кегля порог 3:1, и он
 * берётся. Мелких подписей поверх фуксии в вёрстке быть не должно.
 */
.btn:active { transform: scale(0.99); }

.btn:disabled,
.btn[aria-disabled="true"] {
    background: var(--c-inactive);
    cursor: not-allowed;
}

.btn--block {
    display: block;
    width: 100%;
}

.btn--dark {
    background: var(--c-dark);
    color: var(--c-paper);
}

.btn--outline {
    background: transparent;
    border: 1.5px solid var(--accent);
    color: var(--accent);
}

/*
 * Текстовая кнопка. Хвойный в покое, фуксия под пальцем — те же два
 * фирменных цвета, что у остальных кнопок, только без плашки.
 *
 * Фуксия именно на :hover и :active, а не в покое: на белом фоне она
 * не набирает контраст 4.5:1 (вопрос плана про текст на фуксии), и
 * держать на ней постоянную подпись нельзя. Как отклик на нажатие она
 * читается мгновенно и висит доли секунды.
 */
.btn--link {
    /*
     * Полный сброс, а не только цвет: класс должен работать сам по себе.
     * Раньше он полагался на соседний `.btn`, и стоило написать
     * `class="btn--link"` без него — получалась кнопка браузера с рамкой
     * и системным шрифтом. На <a> это не видно, на <button> видно сразу.
     *
     * `font: inherit` идёт первым: он сбрасывает и размер с насыщенностью,
     * поэтому свои значения ставятся после него.
     */
    display: inline-block;
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent);
    font: inherit;
    font-weight: 600;
    text-align: inherit;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--dur-fast) var(--ease);
}

.btn--link:active { color: var(--accent-2); }

/* наведение — только там, где есть чем наводить: на телефоне его нет */
@media (hover: hover) {
    .btn--link:hover { color: var(--accent-2); }
}

/* поля ввода */
.field {
    display: block;
    margin-bottom: var(--gap-s);
    text-align: left;
}

.field__label {
    display: block;
    margin-bottom: 6px;
    color: var(--text-muted);
    font-size: 14px;
}

.input,
.select {
    display: block;
    width: 100%;
    padding: 15px 18px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius-s);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    /*
     * 16px и не меньше: при меньшем размере Safari на iPhone зумит страницу
     * на фокусе, и вёрстка «прыгает» на каждом поле.
     */
    font-size: 16px;
}

.input:focus,
.select:focus {
    border-color: var(--accent);
    outline: none;
}

.input::placeholder { color: var(--c-inactive); }

/* поле с кнопкой показа пароля */
.field--password { position: relative; }

.field--password .input { padding-right: 52px; }

.field__toggle {
    position: absolute;
    right: 8px;
    bottom: 4px;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--text-muted);
    cursor: pointer;
}

.field__hint {
    margin: 6px 0 0;
    color: var(--text-muted);
    font-size: 13px;
}

/* переключатель-таблетки: пол, период цели */
.pills {
    display: flex;
    gap: var(--gap-xs);
}

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

.pills label {
    flex: 1 1 0;
    padding: 13px 12px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius-s);
    text-align: center;
    cursor: pointer;
    transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.pills input:checked + label {
    border-color: var(--accent);
    color: var(--accent);
    font-weight: 600;
}

/* фокус видим и у скрытого радио — иначе клавиатурой не понять, где ты */
.pills input:focus-visible + label {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* сообщения */
.alert {
    margin-bottom: var(--gap-s);
    padding: 14px 16px;
    border-radius: var(--radius-s);
    background: var(--surface-sunken);
    color: var(--text);
    font-size: 15px;
    text-align: left;
}

.alert--error {
    background: rgba(var(--c-fuchsia-deep-rgb), 0.12);
    color: var(--c-ink);
}

.alert--done {
    background: rgba(var(--c-conifer-rgb), 0.1);
    color: var(--c-conifer);
}


/* ===================================== звёздное поле (этап 1) */

/*
 * Небо за лендингом, приложением и админкой — одно и то же. Разметку
 * раскладывает `views/include/stars.php`, здесь только вид.
 *
 * Слои `position: fixed` и выше экрана в несколько раз: при прокрутке
 * поле уезжает вверх, и без запаса снизу открылась бы пустая полоса.
 */
.stars {
    position: fixed;
    /*
     * Поле выше экрана в несколько раз: при прокрутке слой уезжает вверх, и
     * без запаса снизу открылась бы пустая полоса. Сдвиг ограничен в скрипте,
     * поэтому запаса в 150vh хватает с избытком.
     */
    inset: -150vh 0 -150vh;
    pointer-events: none;
    z-index: 0;
}

/*
 * Подсказка браузеру нужна только слою, который действительно двигают
 * при прокрутке. На неподвижном поле она заставляет держать отдельный
 * композиторный слой впустую — и это заметно там, где рядом происходит
 * что-то тяжёлое.
 */
.stars[data-parallax] { will-change: transform; }

.star {
    position: absolute;
    border-radius: 50%;
    background: var(--c-white);
}

.star--live {
    animation: twinkle var(--t, 4s) ease-in-out infinite;
    animation-delay: var(--d, 0s);
}

.star--bright {
    background: var(--c-fuchsia);
    box-shadow: 0 0 10px 2px rgba(var(--c-fuchsia-rgb), 0.55);
}

@keyframes twinkle {
    0%, 100% { opacity: var(--o, 0.7); }
    50% { opacity: calc(var(--o, 0.7) * 0.25); }
}

/*
 * Уведомление о cookie.
 *
 * Живёт в ui.css, а не в app.css: тот же блок нужен и лендингу, а лендинг
 * встраивает в страницу только tokens.css, ui.css и landing.css. Второй копии
 * этих правил быть не должно.
 *
 * Тёмная плашка на светлых экранах и на тёмном небе читается одинаково — тот
 * же приём, что у `.install` и `.update-bar` в приложении.
 */
.cookie-note {
    display: flex;
    position: fixed;
    left: 50%;
    bottom: calc(var(--gap) + env(safe-area-inset-bottom, 0px));
    z-index: 60;
    align-items: center;
    gap: var(--gap-s);
    width: min(var(--col), calc(100vw - var(--gap) * 2));
    padding: var(--gap-s) var(--gap);
    border-radius: var(--radius);
    background: var(--c-dark);
    color: var(--c-paper);
    box-shadow: var(--shadow-card);
    transform: translateX(-50%);
}

/*
 * Без скриптов уведомление видно сразу: скрыть его тогда нечем, но и
 * промолчать нельзя. Со скриптами показ решает `cookie-note--on` — иначе
 * прочитавший видел бы вспышку плашки на каждой странице.
 */
.js .cookie-note { display: none; }
.js .cookie-note--on { display: flex; }

@media (max-width: 400px) {
    .cookie-note {
        flex-direction: column;
        align-items: stretch;
        text-align: center;
    }
}

.cookie-note__text {
    margin: 0;
    font-size: 14px;
    line-height: 1.4;
}

.cookie-note__more {
    color: var(--c-paper);
    text-decoration: underline;
    white-space: nowrap;
}

.cookie-note__ok {
    flex: none;
    padding: 10px 22px;
    font-size: 15px;
}

/*
 * В приложении внизу висит панель вкладок — плашка встаёт над ней, как это
 * делают подсказка об установке и полоса обновления.
 */
.app .cookie-note {
    bottom: calc(var(--tabbar-h) + var(--tabbar-gap) * 2 + env(safe-area-inset-bottom, 0px));
}

/*
 * Нижний край один, а желающих на него двое. Пока не убрано уведомление,
 * предложение установки ждёт: перекрывать одну плашку другой хуже, чем
 * показать их по очереди — в следующий заход.
 */
body:has(.cookie-note--on) .install,
body:has(.cookie-note--on) .update-bar {
    display: none;
}
