/* Админка антифрод */
:root {
    /* Светлая «стандартная» тема (нейтральные тона, хороший контраст) */
    --bg: #f4f4f5;
    --surface: #ffffff;
    --border: #e4e4e7;
    --text: #18181b;
    --muted: #52525b;
    --primary: #2563eb;
    --primary-hover: #1d4ed8;
    --danger: #dc2626;
    --success: #16a34a;
    /* Настройка бесполезна, но не сломана — отдельный тон между danger и muted */
    --warning: #b45309;
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    font-family: 'Segoe UI', system-ui, sans-serif;
    background: var(--bg);
    color: var(--text);
    line-height: 1.5;
    min-height: 100vh;
}

/* Страница входа */
.auth-page {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.auth-card {
    width: 100%;
    max-width: 360px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 2rem;
}

.auth-card h1 {
    margin: 0 0 0.25rem;
    font-size: 1.5rem;
}

.auth-brand {
    margin: 0 0 0.5rem;
    line-height: 0;
    text-align: center;
}

.auth-logo {
    display: block;
    max-width: 100%;
    width: auto;
    height: auto;
    max-height: 52px;
    margin: 0 auto;
}

.auth-subtitle {
    margin: 0 0 1.5rem;
    color: var(--muted);
    font-size: 0.9rem;
}

.auth-form label {
    display: block;
    margin-bottom: 1rem;
}

.auth-form label span {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 0.85rem;
    color: var(--muted);
}

.auth-form input {
    width: 100%;
    padding: 0.6rem 0.75rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text);
    font-size: 1rem;
}

.auth-form input:focus {
    outline: none;
    border-color: var(--primary);
}

.auth-form button {
    width: 100%;
    margin-top: 0.5rem;
    padding: 0.7rem;
    background: var(--primary);
    color: #fff;
    border: none;
    border-radius: 8px;
    font-size: 1rem;
    cursor: pointer;
}

.auth-form button:hover {
    background: var(--primary-hover);
}

.auth-form .auth-remember {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: nowrap;
    margin: 0.25rem 0 0.75rem;
    font-size: 0.88rem;
    color: var(--text);
    cursor: pointer;
}

.auth-form .auth-remember span {
    display: inline;
    margin-bottom: 0;
    font-size: 0.88rem;
    color: var(--text);
    white-space: nowrap;
    line-height: 1.3;
}

.auth-form .auth-remember input[type="checkbox"] {
    width: auto;
    flex-shrink: 0;
    margin: 0;
}

.auth-page .error {
    margin-bottom: 1rem;
    padding: 0.6rem;
    background: #fef2f2;
    border: 1px solid #fecaca;
    border-radius: 8px;
    color: #b91c1c;
    font-size: 0.9rem;
}

/* Шапка */
.header {
    border-bottom: 1px solid var(--border);
    background: var(--surface);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8) inset, 0 4px 14px rgba(15, 23, 42, 0.06);
}

.header-inner {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0.65rem 1rem;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.65rem 0.85rem;
}

.header h1 {
    margin: 0;
    font-size: 1.25rem;
}

.header-brand {
    margin: 0;
    line-height: 0;
    justify-self: start;
}

.header-logo {
    color: var(--text);
    text-decoration: none;
    display: inline-block;
    border-radius: 10px;
    transition: box-shadow 0.15s ease, opacity 0.15s ease;
}

.header-logo:hover {
    opacity: 0.95;
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
}

.header-logo:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.35);
}

.header-logo img {
    display: block;
    height: 36px;
    width: auto;
    vertical-align: middle;
}

.header-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    justify-self: center;
    /* По содержимому, а не во всю колонку: пунктов стало четыре, и растянутая
       таблетка читалась бы как пустая полоса с кучкой ссылок посередине */
    width: auto;
    max-width: 100%;
    min-width: 0;
    margin: 0;
    padding: 0.2rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.85);
    box-sizing: border-box;
}

.header-nav-link {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.4rem 0.75rem;
    border: none;
    border-radius: 999px;
    background: transparent;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--muted);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    /* appearance гасит рамку и фон нативной кнопки: у групп это button, а не
       ссылка, и без этого он выбивался бы из ряда пунктов */
    -webkit-appearance: none;
    appearance: none;
    transition: color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}

.header-nav-link:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.85);
}

.header-nav-link:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.45);
}

.header-nav-link.is-active {
    color: var(--primary);
    background: #fff;
    font-weight: 600;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.1);
}

/* Группа разделов: девять пунктов в один ряд не встают, поэтому близкие убраны
   под общую кнопку. Меню висит над содержимым страницы, а не раздвигает шапку. */
.header-nav-group {
    position: relative;
    display: inline-flex;
}

.header-nav-chevron {
    flex: none;
    opacity: 0.7;
    transition: transform 0.15s ease;
}

.header-nav-group.is-open .header-nav-chevron {
    transform: rotate(180deg);
}

.header-nav-group.is-open .header-nav-toggle {
    color: var(--text);
    background: #fff;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.1);
}

.header-nav-menu {
    position: absolute;
    top: calc(100% + 0.45rem);
    left: 0;
    z-index: 40;
    min-width: 15rem;
    padding: 0.3rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 14px 34px rgba(15, 23, 42, 0.16);
    /* Прячем видимостью, а не display: так меню появляется плавно и при этом
       не берёт на себя Tab и не читается экранным диктором, пока закрыто */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-0.3rem);
    transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s ease;
}

/* Правая группа раскрывается влево: иначе её меню уходит за край шапки */
.header-nav-menu--right {
    left: auto;
    right: 0;
}

.header-nav-group.is-open .header-nav-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.header-nav-item {
    display: block;
    padding: 0.45rem 0.6rem;
    border-radius: 8px;
    color: var(--text);
    text-decoration: none;
    transition: background 0.15s ease;
}

.header-nav-item:hover {
    background: var(--bg);
}

.header-nav-item:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.45);
}

.header-nav-item.is-active {
    background: rgba(37, 99, 235, 0.08);
}

.header-nav-item.is-active .header-nav-item-label {
    color: var(--primary);
}

.header-nav-item-label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
}

/* Пояснение под подписью: в ряду шапки на него не было места, а без него
   «Пресеты» и «Ключи доступа» приходится открывать, чтобы вспомнить, что там */
.header-nav-item-note {
    display: block;
    margin-top: 0.1rem;
    font-size: 0.75rem;
    line-height: 1.35;
    color: var(--muted);
    white-space: normal;
}

/* Черта перед справкой: отделяет чтение от разделов работы */
.header-nav-sep {
    width: 1px;
    height: 1.1rem;
    margin: 0 0.25rem;
    background: var(--border);
}

.header-nav-help {
    padding: 0.4rem;
    border-radius: 50%;
}

.header-user {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    justify-self: end;
    flex-shrink: 0;
}

.header-user-name {
    display: inline-block;
    max-width: 12rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 0.4rem 0.75rem;
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--muted);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 999px;
}

.header-user .btn-ghost {
    padding: 0.4rem 0.9rem;
    font-size: 0.82rem;
    font-weight: 500;
    border-radius: 999px;
    background: var(--surface);
}

.header-user .btn-ghost:hover {
    color: var(--primary);
    border-color: rgba(37, 99, 235, 0.4);
    background: rgba(37, 99, 235, 0.06);
}

@media (max-width: 900px) {
    .header-nav-link {
        padding: 0.35rem 0.55rem;
        font-size: 0.78rem;
    }

    /* У справки отступы одинаковые с четырёх сторон: правило выше сделало бы
       из круга овал, а знак вопроса в нём — приплюснутым */
    .header-nav-help {
        padding: 0.35rem;
    }

    /* Меню не уже кнопки и не шире экрана: на узком запас по бокам мал, и
       пояснения под подписями перенесутся в две строки вместо одной */
    .header-nav-menu {
        min-width: 13rem;
        max-width: min(20rem, calc(100vw - 2rem));
    }
}

@media (max-width: 560px) {
    .header-inner {
        grid-template-columns: 1fr;
        justify-items: stretch;
    }

    .header-brand {
        justify-self: center;
    }

    .header-nav {
        justify-self: stretch;
        justify-content: center;
    }

    .header-user {
        justify-self: stretch;
        justify-content: center;
        flex-wrap: wrap;
    }

    .header-user-name {
        max-width: none;
        text-align: center;
    }
}

/* Основной контент */
.main {
    max-width: 960px;
    margin: 0 auto;
    padding: 1.5rem 1rem;
}

.breadcrumb {
    margin-bottom: 1rem;
    font-size: 0.9rem;
    color: var(--muted);
}

.breadcrumb a {
    color: var(--primary);
    text-decoration: none;
}

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

.section h2 {
    margin: 0 0 0.5rem;
    font-size: 1.35rem;
}

/* Разбор, открытый из строки таблицы, а не из формы: своя обёртка с отступами,
   потому что строка их не даёт, и с шапкой — иначе неясно, к какому гео он относится */
.country-review-panel {
    padding: 0.6rem 0.65rem 0.9rem;
}

.country-review-head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.2rem;
}

.country-review-head strong { font-size: 0.9rem; }

.country-review-head .muted { font-size: 0.78rem; }

.country-review-close {
    margin-left: auto;
}

/* Разбор гео. Панель информационная, поэтому она не спорит за внимание
   с кнопкой сохранения: приглушённый фон, отступ сверху, ширина по контенту. */
.geo-review {
    margin-top: 0.9rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.85rem 1rem;
    font-size: 0.85rem;
    line-height: 1.55;
    max-width: 70ch;
}

/* Ответ приходит обычным текстом с переносами — сохраняем их как есть */
.geo-review-body { white-space: pre-wrap; }

.geo-review-note {
    color: var(--muted);
    font-size: 0.78rem;
    margin-bottom: 0.5rem;
}

.geo-review-error {
    color: var(--danger);
    font-weight: 500;
}

/* Непрочитанное предложение недельного разбора. Точка, а не другой цвет самой
   иконки: цветом в этой строке уже показано, открыт ли разбор, и два смысла на
   одном признаке читаться не будут. */
.btn-country-review-icon.has-advice {
    color: var(--primary);
}

.btn-country-review-icon.has-advice::after {
    content: '';
    position: absolute;
    top: 0.15rem;
    right: 0.15rem;
    width: 0.4rem;
    height: 0.4rem;
    border-radius: 50%;
    background: var(--primary);
}

.btn-country-review-icon {
    position: relative;
}

/* Режим наблюдения. Стоит сразу под уровнем проверки: и то, и другое задаёт
   строку целиком, а не отдельный сигнал, и мешать их с баллами нельзя. */
.rule-ai-mode {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0.9rem;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
}

.rule-ai-mode-label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--muted);
}

.rule-ai-mode select {
    font-size: 0.82rem;
    padding: 0.2rem 0.4rem;
}

.rule-ai-mode-note {
    font-size: 0.78rem;
    max-width: 60ch;
}

/* История правок. Каждое сохранение — своя карточка: правки делают пачками, и
   отменять их поодиночке бессмысленно, так что граница между пачками важнее,
   чем между отдельными полями внутри. */
.rule-history-item {
    padding: 0.7rem 0;
    border-bottom: 1px solid var(--border);
}

.rule-history-item:last-child { border-bottom: none; }

.rule-history-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Кнопка возврата уходит вправо: она опаснее всего в карточке, и её не должны
   нажимать, целясь в дату */
.rule-history-head .rule-history-undo { margin-left: auto; }

.rule-history-reason {
    margin-top: 0.25rem;
    color: var(--muted);
    font-size: 0.8rem;
    max-width: 70ch;
}

.rule-history-changes {
    margin-top: 0.45rem;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.rule-history-change {
    display: flex;
    gap: 0.6rem;
    font-size: 0.82rem;
}

.rule-history-field {
    min-width: 18rem;
    color: var(--muted);
}

/* Само изменение — единственное число в строке, ради которого её читают */
.rule-history-move {
    font-variant-numeric: tabular-nums;
    font-weight: 500;
}

/* Предложенные правки. Отделены рамкой сверху: это единственная часть разбора,
   по которой можно что-то нажать, и её нельзя путать с рассуждением. */
.geo-changes {
    margin-top: 0.9rem;
    padding-top: 0.8rem;
    border-top: 1px solid var(--border);
}

.geo-changes-head {
    font-weight: 600;
    margin-bottom: 0.5rem;
}

.geo-changes-list {
    margin: 0 0 0.7rem;
    padding: 0;
    list-style: none;
}

.geo-changes-list li {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.1rem 0.8rem;
    padding: 0.4rem 0;
    border-bottom: 1px dashed var(--border);
}

.geo-change-name { font-weight: 500; }

.geo-change-move {
    justify-self: end;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.geo-change-move s { color: var(--muted); }
.geo-change-move b { color: var(--primary); }

/* Обоснование во всю ширину под названием: рядом с числами оно ломало бы колонку */
.geo-change-why {
    grid-column: 1 / -1;
    color: var(--muted);
    font-size: 0.8rem;
}

.geo-changes-effect {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.6rem 0.75rem;
    margin-bottom: 0.7rem;
}

.geo-changes-effect-head {
    font-weight: 600;
    margin-bottom: 0.3rem;
}

.geo-changes-note {
    margin-top: 0.4rem;
    color: var(--muted);
    font-size: 0.8rem;
}

.geo-changes-warn {
    margin-bottom: 0.7rem;
    padding: 0.5rem 0.7rem;
    border-radius: 6px;
    background: rgba(220, 38, 38, 0.08);
    color: var(--danger);
    font-weight: 500;
}

.geo-changes-actions {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.geo-changes-hint {
    color: var(--muted);
    font-size: 0.78rem;
}

.geo-review-facts { margin-top: 0.8rem; }

.geo-review-facts summary {
    cursor: pointer;
    color: var(--muted);
    font-size: 0.78rem;
}

.geo-review-facts pre {
    margin: 0.5rem 0 0;
    padding: 0.7rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.72rem;
    line-height: 1.5;
    overflow-x: auto;
    white-space: pre;
}

/* Метка исхода лида в CRM. Цвет отвечает на один вопрос: правильно ли антифрод
   пропустил лид. Зелёный — деньги, синий — живой человек без денег, красный —
   мусор, который надо было отсечь. Остальное намеренно нейтрально: «не
   дозвонились» — это отсутствие исхода, а не приговор. */
.outcome-badge {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 20px;
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
}

.outcome-good    { background: #f0fdf4; color: var(--success); }
.outcome-live    { background: #eff6ff; color: #1d4ed8; }
.outcome-bad     { background: #fef2f2; color: var(--danger); }
.outcome-dupe    { background: #f5f3ff; color: #6d28d9; }
.outcome-neutral { background: var(--bg); color: var(--muted); }

/* Единый выбор периода в разделах аналитики.
   То, чем пользуются каждый день, — в один клик; произвольный диапазон
   задаётся полями дат в самой форме фильтров. */
.period-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-bottom: 0.8rem;
}

.period-chip {
    display: inline-block;
    padding: 0.32rem 0.8rem;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface);
    font-size: 0.82rem;
    color: var(--muted);
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}

.period-chip:hover { color: var(--text); border-color: var(--muted); }

.period-chip.is-active {
    color: #fff;
    background: var(--primary);
    border-color: var(--primary);
    font-weight: 600;
}

/* Общая раскладка фильтров разделов аналитики */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    align-items: flex-end;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 0.9rem 1rem;
    margin-bottom: 1.1rem;
}

.filter-group { display: flex; flex-direction: column; gap: 0.25rem; }
.filter-group label { font-size: 0.78rem; color: var(--muted); }

.filter-group select,
.filter-group input,
.filter-input {
    padding: 0.38rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.85rem;
    background: var(--bg);
    color: var(--text);
    font-family: inherit;
}

/* Заголовок группы разделов с переключением вкладками.
   Вкладки прижаты к правому краю, но на узком экране переносятся под
   заголовок, а не сжимаются в нечитаемую полоску. */
.section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-bottom: 0.9rem;
}

.section-head h2 {
    margin: 0;
}

.section-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.15rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 0.2rem;
}

.section-tab {
    display: inline-block;
    padding: 0.32rem 0.85rem;
    border-radius: 999px;
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--muted);
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}

.section-tab:hover {
    color: var(--text);
    background: rgba(255, 255, 255, 0.8);
}

.section-tab:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.45);
}

.section-tab.is-active {
    color: var(--primary);
    background: var(--surface);
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.1);
}

@media (max-width: 560px) {
    .section-head { justify-content: flex-start; }
    .section-tabs { width: 100%; justify-content: center; }
}

.muted {
    color: var(--muted);
    font-size: 0.9rem;
    margin: 0 0 1rem;
}

/* Справка «О проверках» */
.checks-ref-hero {
    margin-bottom: 1rem;
}

.checks-ref-hero h2 {
    margin: 0 0 0.35rem;
}

.checks-ref-hero-lead {
    margin-bottom: 0 !important;
}

.checks-ref-toc {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 1rem 1.5rem;
    margin: 0 0 1.75rem;
    padding: 1rem 1.1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
}

.checks-ref-toc-heading {
    margin: 0 0 0.4rem;
    font-size: 0.82rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
}

.checks-ref-toc-heading a {
    color: var(--primary);
    text-decoration: none;
}

.checks-ref-toc-heading a:hover {
    text-decoration: underline;
}

.checks-ref-toc-list {
    margin: 0;
    padding-left: 1.1rem;
    font-size: 0.88rem;
    line-height: 1.55;
    color: var(--text);
}

.checks-ref-toc-list a {
    color: var(--primary);
    text-decoration: none;
}

.checks-ref-toc-list a:hover {
    text-decoration: underline;
}

.checks-ref-part {
    margin-bottom: 2rem;
}

.checks-ref-part-title {
    margin: 0 0 0.35rem;
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--text);
    padding-bottom: 0.35rem;
    border-bottom: 2px solid var(--border);
}

.checks-ref-part-intro {
    margin: 0 0 1rem !important;
    max-width: 52rem;
}

.checks-ref-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 0.85rem;
    align-items: stretch;
}

.checks-ref-card {
    margin: 0;
    padding: 0.85rem 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.checks-ref-card-title {
    margin: 0 0 0.15rem;
    font-size: 0.98rem;
    font-weight: 600;
    color: var(--text);
}

.checks-ref-card p {
    margin: 0;
    font-size: 0.88rem;
    line-height: 1.45;
    color: var(--text);
}

.checks-ref-card-note {
    margin-top: 0.25rem !important;
    font-size: 0.82rem !important;
}

/* Статья IPQS — отдельный визуальный блок */
.checks-ref-article {
    margin: 0 0 1.5rem;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface);
    box-shadow: 0 2px 12px rgba(15, 23, 42, 0.06);
    overflow: hidden;
}

.checks-ref-article-ipqs {
    border-left: 4px solid var(--primary);
}

.checks-ref-article-header {
    padding: 1.1rem 1.25rem 1rem;
    background: linear-gradient(180deg, rgba(37, 99, 235, 0.06) 0%, transparent 100%);
    border-bottom: 1px solid var(--border);
}

.checks-ref-article-title {
    margin: 0 0 0.4rem;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text);
}

.checks-ref-article-lead {
    margin: 0 !important;
    max-width: 48rem;
    font-size: 0.9rem;
    line-height: 1.5;
}

.checks-ref-article-section {
    padding: 1rem 1.25rem 1.1rem;
    border-top: 1px solid var(--border);
}

.checks-ref-article-section:first-of-type {
    border-top: none;
}

.checks-ref-section-title {
    margin: 0 0 0.5rem;
    font-size: 1.02rem;
    font-weight: 600;
    color: var(--text);
}

.checks-ref-article-section > p {
    margin: 0 0 0.5rem;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--text);
}

.checks-ref-article-section > p:last-child {
    margin-bottom: 0;
}

.checks-ref-list-tight {
    margin: 0.25rem 0 0.65rem;
    padding-left: 1.15rem;
    font-size: 0.88rem;
    line-height: 1.5;
}

.checks-ref-dl {
    margin: 0.35rem 0 0;
    display: grid;
    gap: 0.35rem 0;
}

.checks-ref-dl dt {
    margin: 0.5rem 0 0;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text);
}

.checks-ref-dl dt:first-child {
    margin-top: 0;
}

.checks-ref-dl dd {
    margin: 0 0 0 0;
    padding-left: 0.5rem;
    border-left: 2px solid var(--border);
    font-size: 0.86rem;
    line-height: 1.45;
    color: var(--muted);
}

.checks-ref-footer {
    margin-top: 0.5rem;
    padding-top: 1rem;
    border-top: 1px dashed var(--border);
}

.checks-ref-footer p {
    margin: 0;
}

/* Список трекеров */
.tracker-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.tracker-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    margin-bottom: 0.75rem;
}

.tracker-info {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.tracker-info code {
    background: var(--bg);
    padding: 0.2rem 0.5rem;
    border-radius: 4px;
    font-size: 0.85rem;
    color: var(--muted);
}

.badge.inactive {
    font-size: 0.75rem;
    padding: 0.15rem 0.4rem;
    background: var(--border);
    border-radius: 4px;
    color: var(--muted);
}

/* Кнопки */
.btn {
    display: inline-block;
    padding: 0.5rem 1rem;
    border-radius: 8px;
    font-size: 0.9rem;
    text-decoration: none;
    cursor: pointer;
    border: none;
    font-family: inherit;
}

/* Заданный здесь display перебивал браузерное правило для hidden, и спрятанная
   кнопка оставалась на экране пустым прямоугольником. Такие кнопки есть и в
   настройках трекера («Забыть токен»), и в окне пресета («Обновить») */
.btn[hidden] {
    display: none;
}

.btn-primary {
    background: var(--primary);
    color: #fff;
}

.btn-primary:hover {
    background: var(--primary-hover);
}

.btn-ghost {
    background: transparent;
    color: var(--muted);
    border: 1px solid var(--border);
}

.btn-ghost:hover {
    color: var(--text);
    border-color: var(--text);
}

.btn-danger {
    background: #fef2f2;
    color: #b91c1c;
    border: 1px solid #fecaca;
}

.btn-danger:hover {
    background: var(--danger);
    color: #fff;
    border-color: var(--danger);
}

/* Форма конфига */
.config-section .error,
.config-section .success {
    padding: 0.75rem;
    border-radius: 8px;
    margin-bottom: 1rem;
}

.config-section .error {
    background: #fef2f2;
    border: 1px solid #fecaca;
    color: #b91c1c;
}

.config-section .success {
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    color: #166534;
}

.config-form {
    margin-top: 1rem;
}

.config-block {
    margin-bottom: 1.5rem;
    padding: 1.25rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
}

.config-block legend {
    padding: 0 0.5rem;
    color: var(--muted);
    font-size: 0.9rem;
}

.config-form label {
    display: block;
    margin-bottom: 0.75rem;
}

.config-form label span {
    display: block;
    margin-bottom: 0.3rem;
    font-size: 0.85rem;
    color: var(--muted);
}

.field-hint {
    display: block;
    margin-top: 0.35rem;
    font-size: 0.8rem;
    color: var(--muted);
}

.config-form input[type="text"],
.config-form input[type="url"],
.config-form input[type="password"],
.config-form textarea {
    width: 100%;
    max-width: 480px;
    padding: 0.5rem 0.75rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text);
    font-size: 0.95rem;
}

.config-form input.readonly {
    opacity: 0.8;
    cursor: not-allowed;
}

.config-form textarea {
    max-width: 100%;
    min-height: 200px;
    font-family: ui-monospace, monospace;
    font-size: 0.85rem;
}

.config-form label.full-width {
    max-width: none;
}

.form-actions {
    margin-top: 1.5rem;
    display: flex;
    gap: 0.75rem;
}

.form-actions .btn {
    margin: 0;
}

/* Страны и баллы */
.countries-add-form {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.75rem 1rem;
    margin-bottom: 1.5rem;
    padding: 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
}

.countries-add-form-collapsed {
    display: none !important;
}

.countries-add-form-sectioned {
    align-items: stretch;
}

.countries-add-main {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    align-items: flex-end;
    justify-content: space-between;
}

.countries-country-field {
    flex: 1 1 220px;
    min-width: 220px;
}

.countries-country-field input {
    width: 100%;
    max-width: 420px;
    padding: 0.55rem 0.85rem;
    background: #fff;
    border: 1px solid #d4d4d8;
    border-radius: 8px;
    color: var(--text);
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.07);
}

.countries-country-field input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.22);
}

.countries-add-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
    margin-left: auto;
}

.countries-add-submit {
    flex: 0 0 auto;
}

.countries-fieldset {
    width: 100%;
}

.countries-fieldset-hint {
    margin: 0 0 0.75rem 0;
}

/* Ярлык источника сигнала: без него неочевидно, что «email» и «email invalid» —
   это два разных сервиса, а не одна настройка в двух местах. В справке идёт
   строчным ярлыком, в панели — подписью над группой полей (.rule-src-caption). */
.rule-src {
    display: inline-block;
    margin-left: 0.35rem;
    padding: 0.05rem 0.3rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 0.7rem;
    font-weight: 500;
    line-height: 1.5;
    color: var(--muted);
    white-space: nowrap;
    vertical-align: middle;
}

/* Общий выключатель IPQS стоит отдельным блоком: он гасит сигналы сразу в трёх
   категориях, поэтому в строку одного сигнала его поместить нельзя */
.rule-toggle-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.75rem;
    min-width: 0;
}

/*
 * Подгруппа по источнику внутри блока категории. Строго одна колонка: попытка
 * разложить строки в две ради пустого места справа сделала порядок чтения рваным,
 * а колонки баллов — невыровненными между собой.
 */
.rule-src-group + .rule-src-group {
    margin-top: 0.5rem;
}

/* Источник — тихой подписью с линией, а не рамкой: рамка выглядела кнопкой
   и её принимали за кликабельную */
.rule-src-caption {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.15rem;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--muted);
    white-space: nowrap;
}

.rule-src-caption::after {
    content: '';
    flex: 1 1 auto;
    height: 1px;
    background: var(--border);
}

/*
 * Строка одного сигнала: галочка и подпись, подсказка, условие срабатывания, балл.
 * Сетка, а не flex: колонка баллов должна выстраиваться друг под другом во всех
 * строках, иначе их не сравнить взглядом. Ширина ограничена — при растяжении на всю
 * форму балл уезжал к правому краю и терял связь со своей подписью.
 */
.rule-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 8.5rem 3.6rem;
    align-items: center;
    gap: 0.1rem 0.5rem;
    /* Ширина ограничена: растянутая на всю форму строка уводила балл к правому
       краю, и он терял связь со своей подписью */
    max-width: 31rem;
    min-height: 1.7rem;
}

/* Подпись, галочка и подсказка держатся вместе: подсказка в отдельной колонке
   отрывалась от подписи и повисала посреди пустого места */
.rule-row-name {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    margin: 0;
    min-width: 0;
    font-size: 0.76rem;
    line-height: 1.2;
}

.rule-row-name .score-hint {
    flex: 0 0 auto;
    margin-left: 0.1rem;
}

/* Обрезаем только текст подписи. Иконку подсказки трогать нельзя: её всплывающее
   окно позиционируется абсолютно внутри неё и overflow: hidden его обрежет */
.rule-row-name > span:not(.score-hint):not(.rule-row-idle) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rule-row-name input[type="checkbox"] {
    flex: 0 0 auto;
    margin: 0;
}

/* Выключенный сигнал: подпись гаснет, поля показывают «—». Строку не прячем —
   человек должен видеть, что сигнал существует и его можно вернуть.

   Гасим части метки по отдельности, а не саму метку: прозрачность родителя
   перемножается с потомками, и подсказка ⓘ — это ::after той же метки, поэтому
   у выключенного сигнала она выцветала вместе с подписью. Ещё opacity заводит
   отдельный слой наложения, из которого всплывающей подсказке не выбраться
   поверх соседних секций, каким бы большим ни был её z-index. */
.rule-row--off .rule-row-name > input,
.rule-row--off .rule-row-name > span:not(.score-hint),
.rule-row--off .rule-row-cond {
    opacity: 0.5;
}

/* Саму иконку гасим цветом, чтобы строка выглядела как прежде: #a1a1aa — это
   то, во что превращался --muted под прозрачностью 0.5 на белом фоне. Текст
   внутри подсказки задан своим цветом и от этого не светлеет.
   Оговорка про :hover нужна из-за веса селектора: без неё это правило
   перебивало бы подсветку иконки под курсором. */
.rule-row--off .rule-row-name > .score-hint:not(:hover) {
    color: #a1a1aa;
}

.rule-row--off input[type="number"] {
    background: var(--bg);
    color: var(--muted);
    border-style: dashed;
}

/*
 * Метка правила, которое включено, но не начисляет баллов. Такое правило не
 * бесплатно: проверка выполняется, у WhatsApp и IPQS это ещё и платный запрос.
 * Молча пропускать такую настройку нельзя, запрещать тоже — на нуле удобно
 * держать проверку ради наблюдения, пока подбираются баллы.
 */
.rule-row-idle {
    display: none;
    flex: 0 0 auto;
    margin-left: 0.15rem;
    padding: 0 0.28rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--warning, #b45309) 14%, transparent);
    color: var(--warning, #b45309);
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1.5;
    cursor: help;
}

.rule-row--idle .rule-row-idle {
    display: inline-block;
}

.rule-row-cond {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    justify-content: flex-end;
    min-width: 0;
    font-size: 0.72rem;
    line-height: 1.2;
    color: var(--muted);
    white-space: nowrap;
}

.rule-row-score {
    display: flex;
    justify-content: flex-end;
    min-width: 0;
}

.rule-row input[type="number"] {
    width: 100%;
    max-width: 3.5rem;
    padding: 0.18rem 0.25rem;
    font-size: 0.8rem;
    line-height: 1.2;
    text-align: center;
}

/* Порог времени бывает четырёхзначным (tmsl до 9999) — узкое поле его обрезало */
.rule-row-cond input[type="number"] {
    max-width: 3.6rem;
}

/* Оговорка к проверке: стоит на месте условия срабатывания, которого у такого
   сигнала нет. Своей подсказки у неё нет намеренно — текст уходит в общую
   подсказку строки, чтобы в строке не выстраивались две иконки подряд */
.rule-row-extra {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin: 0;
    cursor: pointer;
}

.rule-row-extra input[type="checkbox"] {
    flex: 0 0 auto;
    margin: 0;
}

/* Итог по категории — рядом с её названием, чтобы баланс баллов и порога был
   виден без прокрутки к концу формы */
.rule-cat-total {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.02rem 0.4rem;
    background: var(--bg);
    border-radius: 999px;
    font-size: 0.68rem;
    font-weight: 600;
    line-height: 1.5;
    color: var(--muted);
    text-transform: none;
    letter-spacing: 0;
    white-space: nowrap;
    cursor: help;
}

/* «макс. 30» читалось как ограничение на ввод, хотя это подсчёт суммы */
.rule-cat-total::before {
    content: 'даёт до ';
    font-weight: 400;
}

.rule-cat-total::after {
    content: ' баллов';
    font-weight: 400;
}

/*
 * Пресеты. Ряд чипов над формой: клик заполняет все поля разом. «Свой» руками не
 * выбирается — он появляется сам, как только значения перестали совпадать с
 * эталоном, и подписывается тем пресетом, с которого начинали.
 */
.preset-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.7rem;
    margin: 0 0 0.8rem 0;
    padding: 0.5rem 0.7rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
}

.preset-bar-label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--muted);
}

.preset-chips {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.15rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
}

.preset-chip {
    padding: 0.28rem 0.7rem;
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    font: inherit;
    font-size: 0.82rem;
    color: var(--text);
    cursor: pointer;
    white-space: nowrap;
}

.preset-chip:hover {
    background: var(--surface);
}

.preset-chip.is-active {
    background: var(--surface);
    border-color: var(--border);
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
}

/* «Свой» — это состояние, а не кнопка: нажимать его не на что */
.preset-chip--custom {
    color: var(--muted);
    cursor: default;
}

.preset-chip--custom[hidden] {
    display: none;
}

/* Личный пресет: виден только автору, и отличать его от общих надо с одного
   взгляда — иначе непонятно, почему коллега не видит того же чипа */
.preset-chip--mine::before {
    content: '•';
    margin-right: 0.3rem;
    color: var(--primary);
}

/* Кнопка действия в полоске пресетов, а не ещё один вариант выбора.
   Отличается от чипов цветом: чипы серо-белые, действие — синее с лёгкой
   заливкой. Раньше тут были пунктирная рамка и серый текст, чтобы кнопку не
   приняли за недоступный чип, но в таком виде её просто переставали замечать:
   приглушены были сразу и рамка, и цвет, и насыщенность. */
.preset-bar-save {
    /* К правому краю: вплотную к чипам кнопка читалась как ещё один вариант
       выбора. Расстояние само отделяет действие от набора */
    margin-left: auto;
    padding: 0.3rem 0.7rem;
    border: 1px solid color-mix(in srgb, var(--primary) 40%, transparent);
    border-radius: 6px;
    background: color-mix(in srgb, var(--primary) 8%, transparent);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--primary);
    cursor: pointer;
    white-space: nowrap;
}

.preset-bar-save:hover {
    border-color: var(--primary);
    background: color-mix(in srgb, var(--primary) 15%, transparent);
}

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

   Два класса в селекторе не для красоты: общее .tset стоит в файле ниже и при
   равном весе побеждало бы, оставляя окну прокрутку и срезанную подсказку */
.tset.preset-save {
    overflow: visible;
}

/* Подсказка в заголовке раскрывается вниз: вверх ей некуда, там край окна.
   Шире обычной: в окне для неё есть место, а узкой колонкой тот же текст
   вытягивается в десяток строк */
.preset-save .score-hint::after {
    top: calc(100% + 6px);
    bottom: auto;
    width: max-content;
    max-width: min(30rem, calc(100vw - 2rem));
}

.psave-shared {
    margin-top: 0.75rem;
}

.psave-mine {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    /* Потолок на случай, когда пресетов накопилось много: окно не должно расти
       во весь экран, прокрутка остаётся внутри списка */
    max-height: 9rem;
    overflow: auto;
}

.psave-mine-item {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.3rem 0.2rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg);
    font-size: 0.82rem;
}

.psave-mine-del {
    width: 1.25rem;
    height: 1.25rem;
    padding: 0;
    border: none;
    border-radius: 4px;
    background: transparent;
    color: var(--muted);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

.psave-mine-del:hover {
    background: var(--surface);
    color: var(--danger);
}

.preset-bar-note {
    flex: 1 1 14rem;
    min-width: 0;
    font-size: 0.78rem;
    color: var(--muted);
}

.preset-revert {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: var(--primary);
    text-decoration: underline;
    cursor: pointer;
}

/*
 * Подсветка того, что изменил пресет. Живёт несколько секунд и гаснет при первом
 * касании формы: постоянная подсветка превращается в фон и перестаёт что-либо
 * значить.
 */
.rule-row.is-preset-changed,
.check-input.is-preset-changed,
.threshold-field.is-preset-changed {
    background: color-mix(in srgb, var(--primary) 10%, transparent);
    border-radius: 5px;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 10%, transparent);
    transition: background 0.5s, box-shadow 0.5s;
}

.rule-row-was {
    flex: 0 0 auto;
    margin-left: 0.3rem;
    font-size: 0.68rem;
    font-weight: 400;
    color: var(--primary);
    white-space: nowrap;
}

/*
 * Тост отката. Кнопка называется «Вернуть как было», а не «Отменить»: «Отмена» в
 * липкой панели закрывает форму, и одно слово на два разных действия путало бы.
 * Висит над липкой панелью, поэтому bottom считается от её высоты.
 */
.preset-toast {
    position: fixed;
    left: 50%;
    bottom: 4.2rem;
    z-index: 41;
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.5rem 0.6rem 0.5rem 0.9rem;
    transform: translateX(-50%);
    background: var(--text);
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(15, 23, 42, 0.25);
    color: #fff;
    font-size: 0.82rem;
}

.preset-toast[hidden] {
    display: none;
}

.preset-toast .btn {
    background: rgba(255, 255, 255, 0.14);
    border-color: rgba(255, 255, 255, 0.3);
    color: #fff;
}

.preset-toast .btn:hover {
    background: rgba(255, 255, 255, 0.24);
}

/*
 * Липкая панель с итогом и кнопками. Форма настройки длиннее экрана, а главное
 * число — сумма баллов против порога фейка — жило в самом её конце: настраивая
 * верхние блоки, человек не видел результата и не мог сохранить, не долистав.
 * Панель держится поверх страницы всё время, пока форма открыта.
 *
 * Она именно fixed, а не sticky: панель редактирования живёт внутри ячейки
 * таблицы, у которой своя горизонтальная прокрутка, и sticky прилипал бы к её
 * дну, а не к низу экрана.
 */
.rule-sticky-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    background: var(--surface);
    border-top: 3px solid var(--primary);
    box-shadow: 0 -4px 16px rgba(15, 23, 42, 0.13);
}

.rule-sticky-bar[hidden] {
    display: none;
}

.rule-sticky-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.9rem;
    max-width: 1600px;
    margin: 0 auto;
    padding: 0.5rem 1rem;
    font-size: 0.82rem;
}

.rule-sticky-title {
    font-weight: 600;
    white-space: nowrap;
}

.rule-sticky-total {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    white-space: nowrap;
}

.rule-sticky-label {
    color: var(--muted);
}

.rule-sticky-num {
    font-size: 1.45rem;
    font-weight: 700;
    line-height: 1;
    color: var(--primary);
}

/* Короткая вспышка на изменившемся числе: без неё правка в верхнем блоке и
   новая сумма внизу выглядят как два несвязанных события */
.rule-sticky-num.is-changed {
    animation: rule-sticky-pulse 0.45s ease-out;
}

@keyframes rule-sticky-pulse {
    from { transform: scale(1.25); }
    to { transform: scale(1); }
}

/* Дельта от суммы на момент открытия: видно, что изменила именно эта правка */
.rule-sticky-delta {
    font-size: 0.85rem;
    font-weight: 700;
}

.rule-sticky-delta.is-up {
    color: var(--danger, #dc2626);
}

.rule-sticky-delta.is-down {
    color: var(--success, #16a34a);
}

.rule-sticky-limit {
    color: var(--muted);
    white-space: nowrap;
}

.rule-sticky-note {
    color: var(--warning, #b45309);
}

.rule-sticky-note:empty {
    display: none;
}

.rule-sticky-actions {
    display: flex;
    gap: 0.45rem;
    margin-left: auto;
}

/* Недостижимый порог — не ошибка ввода, а бесполезное правило: предупреждаем */
.rule-sticky-bar--short {
    /* Простой цвет первым: color-mix понимают не все версии браузеров */
    background: #fdf6ed;
    background: color-mix(in srgb, var(--warning, #b45309) 7%, var(--surface));
    border-top-color: var(--warning, #b45309);
}

.rule-sticky-bar--short .rule-sticky-num {
    color: var(--warning, #b45309);
}

/* Чтобы панель не накрыла конец формы */
body.has-rule-sticky-bar .main {
    padding-bottom: 4.5rem;
}

/* Кнопки формы переезжают в панель. Прячем их только когда скрипт работает:
   без него они остаются на месте и форма сохраняется как раньше */
body.has-rule-sticky-bar .countries-add-actions,
body.has-rule-sticky-bar .country-edit-actions {
    display: none;
}

/* Короткая вспышка на поле, значение которого вернули в допустимые границы:
   без неё исправление выглядит так, будто ввод просто не сработал */
.rule-row input.is-clamped,
.threshold-field input.is-clamped {
    outline: 2px solid var(--warning, #b45309);
    outline-offset: 1px;
    transition: outline-color 0.4s;
}

/* Панель раскрывается внутри строки таблицы, места по высоте меньше — чуть плотнее */
.country-edit-panel .rule-row {
    min-height: 1.55rem;
}

.country-edit-panel .rule-row-name,
.country-edit-panel .rule-row-cond {
    font-size: 0.72rem;
}

.countries-add-form label {
    margin-bottom: 0;
}

.countries-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    align-items: center;
    margin: 0 0 0.85rem 0;
    padding: 0.6rem 0.75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
}

.countries-thresholds-fields {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.5rem;
}

/*
 * Поле порога решения: подпись и ввод в одну строку. Раньше здесь работал общий
 * класс .score-input, описанный по-разному в трёх местах файла; в этом блоке он
 * делал подпись флекс-элементом с ограничением ширины, и у длинной «порог
 * проверки» поле не помещалось в строку и уезжало вниз. Класс убран совсем.
 */
.threshold-field {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    white-space: nowrap;
}

.threshold-field-name {
    display: inline-flex;
    align-items: center;
    font-size: 0.85rem;
    color: var(--muted);
}

.threshold-field input {
    width: 4.2rem;
    padding: 0.25rem 0.35rem;
    font-size: 0.9rem;
    line-height: 1.2;
    text-align: center;
}

/* ---------------------------------------------------------------------------
   Настройки трекера в отдельном окне: шестерёнка и само окно.

   Пороги решения и группа в телеграме лежали двумя формами над таблицей стран
   и занимали первый экран страницы, к которой относятся не они, а правила по
   странам. Открывают их редко, поэтому убраны в окно.
   --------------------------------------------------------------------------- */
.btn-tracker-settings {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    color: var(--muted);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: color 0.15s, border-color 0.15s, background 0.15s, transform 0.15s;
}

.btn-tracker-settings:hover {
    color: var(--primary);
    border-color: var(--primary);
    background: var(--bg);
    /* Шестерёнка поворачивается под курсором: иконка настроек узнаётся по
       форме, а поворот подсказывает, что она нажимается */
    transform: rotate(45deg);
}

.btn-tracker-settings:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.tset {
    width: min(36rem, calc(100vw - 2rem));
    max-height: calc(100vh - 4rem);
    overflow: auto;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.18);
}

.tset::backdrop {
    background: rgba(24, 24, 27, 0.45);
}

.tset-inner {
    margin: 0;
    padding: 0;
}

.tset-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 1.1rem;
    border-bottom: 1px solid var(--border);
}

.tset-title {
    display: block;
    font-size: 1rem;
}

.tset-subject {
    font-size: 0.85rem;
}

.tset-close {
    flex: none;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--muted);
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
}

.tset-close:hover {
    background: var(--bg);
    color: var(--text);
}

/* Сообщение внутри окна, а не на странице под ним: страницу за затемнением
   не видно, и ответ на нажатие кнопки в окне должен быть в этом же окне */
.tset-msg {
    margin: 0.85rem 1.1rem 0 1.1rem;
    padding: 0.5rem 0.7rem;
    border-radius: 8px;
    font-size: 0.85rem;
}

.tset-msg.is-good {
    background: rgba(22, 163, 74, 0.1);
    color: var(--success);
}

.tset-msg.is-bad {
    background: rgba(220, 38, 38, 0.1);
    color: var(--danger);
}

.tset-section {
    padding: 0.9rem 1.1rem;
}

.tset-section + .tset-section {
    border-top: 1px solid var(--border);
}

.tset-section-title {
    margin: 0;
    font-size: 0.9rem;
}

.tset-section-hint {
    margin: 0.2rem 0 0.75rem 0;
    font-size: 0.8rem;
}

.tset-fields {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem 1.5rem;
}

/* Кнопка к правому краю: между настройкой и действием нужен воздух, иначе
   кнопка читается как третье поле формы */
.tset-fields > .btn {
    margin-left: auto;
}

/* Токен и номер группы столбиком: в строку они не встают из-за длины токена,
   а перенос флексом рвал бы подпись и поле по разным строкам */
.tset-fields--stacked {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.6rem;
}

.tset-fields--stacked .threshold-field {
    width: 100%;
    gap: 0.75rem;
}

/* Подписи одной ширины, поля занимают весь остаток строки. Общее правило поля
   порога задаёт ширину под трёхзначное число: в такое поле не видно даже начала
   токена, а номер группы из тринадцати знаков читается по одной цифре. Ширину
   перебиваем отсюда, из двух классов: отдельный класс на само поле давал тот же
   вес селектора, и правило под числа, стоящее в файле ниже, побеждало. */
.tset-fields--stacked .threshold-field-name {
    flex: none;
    width: 8.5rem;
}

.tset-fields--stacked .threshold-field input {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    text-align: left;
    padding-left: 0.5rem;
}

.tset-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.85rem;
}

/* Кнопки собственной полосой внизу окна: отступ им даёт секция, и отбивать их
   ещё и сверху незачем — иначе между чертой и кнопками образуется провал */
.tset-section > .tset-actions:first-child {
    margin-top: 0;
}

.tset-note {
    margin: 0.75rem 0 0 0;
    font-size: 0.8rem;
}

.countries-toolbar-affiliate {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    padding-right: 0.75rem;
    border-right: 1px solid var(--border);
}

.countries-toolbar-affiliate label,
.countries-toolbar-label {
    font-size: 0.8rem;
    color: var(--muted);
}

.countries-toolbar-affiliate input,
.countries-toolbar-affiliate select {
    width: 6rem;
    padding: 0.35rem 0.5rem;
    background: #fff;
    border: 1px solid #d4d4d8;
    border-radius: 6px;
    color: var(--text);
    font-size: 0.85rem;
}

.countries-toolbar-affiliate select {
    width: auto;
}

.countries-toolbar-affiliate input:focus,
.countries-toolbar-affiliate select:focus {
    outline: none;
    border-color: var(--primary);
}

/* Удаление трекера — к правому краю, подальше от повседневных кнопок */
.countries-toolbar-danger {
    margin-left: auto;
}

.countries-search {
    display: flex;
    align-items: center;
    margin: 0;
}

.countries-search input {
    width: min(260px, 100%);
    padding: 0.35rem 0.6rem;
    background: #fff;
    border: 1px solid #d4d4d8;
    border-radius: 6px;
    color: var(--text);
    font-size: 0.85rem;
}

.countries-search input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.22);
}

.countries-filter-count {
    font-size: 0.8rem;
    white-space: nowrap;
}

.countries-table-wrap {
    overflow-x: auto;
    overflow-y: visible;
    -webkit-overflow-scrolling: touch;
    border-radius: 10px;
    /* Ширина видимой области — для переноса полей в панели редактирования под строкой */
    container-type: inline-size;
    container-name: countries-scroll;
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.countries-table {
    /* Ширина колонки задана числом, а не содержимым: колонка закреплена при
       скролле, и от неё же отсчитывается позиция колонки со страной. Иконка,
       которая в неё не влезла, уезжает под соседнюю ячейку — поэтому ширину
       диктует количество иконок: 1.75rem на каждую, 0.1rem на зазор,
       0.4rem на отступы ячейки. Три иконки: правка, клон, история */
    --countries-edit-col-w: 6.15rem;
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    /* visible: иначе ::after-подсказки у левого края обрезаются (overflow + translate -50%) */
    overflow: visible;
    min-width: 900px;
}

/* Четвёртая иконка — разбор гео, её видит только администратор */
.countries-table.has-review-icon {
    --countries-edit-col-w: 8rem;
}

.countries-th-edit,
.countries-cell-edit {
    position: sticky;
    left: 0;
    z-index: 3;
    width: var(--countries-edit-col-w);
    min-width: var(--countries-edit-col-w);
    max-width: var(--countries-edit-col-w);
    padding: 0.35rem 0.2rem;
    text-align: center;
    vertical-align: middle;
    background: var(--surface);
    box-shadow: 1px 0 0 var(--border);
}

.countries-table thead th.countries-th-edit {
    z-index: 5;
    background: #e4e4e7;
    vertical-align: middle;
    color: var(--muted);
}

.countries-th-edit-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0.75;
}

.countries-th-country,
.countries-cell-country {
    position: sticky;
    left: var(--countries-edit-col-w);
    z-index: 2;
    background: var(--surface);
    box-shadow: 1px 0 0 var(--border);
}

.countries-table thead th.countries-th-country {
    z-index: 4;
    background: var(--bg);
    vertical-align: bottom;
}

.countries-table thead tr.countries-table-head-groups th.countries-th-group {
    /* Влево, а не по центру: при горизонтальном скролле подпись группы
       уезжает за край экрана и колонки читаются как чужая группа. */
    text-align: left;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: var(--muted);
    padding: 0.4rem 0.35rem;
    background: #e4e4e7;
    border-bottom: 1px solid var(--border);
}

.countries-table thead tr.countries-table-head-cols th {
    white-space: nowrap;
}

/* Граница между группами колонок — иначе «tmsf» (балл) и «tmsf сек» (порог) сливаются */
.countries-table th.is-group-start,
.countries-table td.is-group-start {
    border-left: 1px solid #c8c8cd;
}

.countries-table thead th.countries-th-metric,
.countries-table thead th.countries-th-check {
    text-align: center;
    min-width: 2.6rem;
    padding-left: 0.35rem;
    padding-right: 0.35rem;
}

.countries-table thead th.countries-th-actions {
    width: 1%;
    min-width: 8.5rem;
}

.countries-table tbody tr.countries-data-row.countries-row-alt > td {
    background: #fafafa;
}

.countries-table tbody tr.countries-data-row.countries-row-alt > td.countries-cell-edit,
.countries-table tbody tr.countries-data-row.countries-row-alt > td.countries-cell-country {
    background: #f4f4f5;
}

.countries-table tbody tr.countries-row-default > td {
    background: rgba(37, 99, 235, 0.06);
}

/* Закреплённые ячейки — только непрозрачный фон: полупрозрачный просвечивает
   колонками, которые уезжают под них при горизонтальном скролле. */
.countries-table tbody tr.countries-row-default > td.countries-cell-edit {
    background: #eef3fd;
    box-shadow: inset 3px 0 0 var(--primary), 1px 0 0 var(--border);
}

.countries-table tbody tr.countries-row-default > td.countries-cell-country {
    background: #eef3fd;
    box-shadow: 1px 0 0 var(--border);
}

.countries-table tbody tr.countries-row-default.countries-row-alt > td {
    background: rgba(37, 99, 235, 0.07);
}

.countries-table tbody tr.countries-row-default.countries-row-alt > td.countries-cell-edit {
    background: #ebf1fd;
    box-shadow: inset 3px 0 0 var(--primary), 1px 0 0 var(--border);
}

.countries-table tbody tr.countries-row-default.countries-row-alt > td.countries-cell-country {
    background: #ebf1fd;
    box-shadow: 1px 0 0 var(--border);
}

.countries-cell-num {
    text-align: center;
    font-variant-numeric: tabular-nums;
    font-size: 0.9rem;
}

/* Порог не задан для страны — показано унаследованное значение трекера */
.countries-cell-num.is-inherited {
    color: var(--muted);
    font-style: italic;
}

.countries-cell-check {
    text-align: center;
    font-size: 0.85rem;
    line-height: 1.2;
}

.countries-cell-check.is-on {
    color: var(--success);
    font-weight: 600;
}

.countries-cell-check.is-off {
    color: #a1a1aa;
}

.countries-table tr.is-expanded td.countries-cell-edit,
.countries-table tr.is-expanded td.countries-cell-country {
    background: #f0f4fe;
}

.countries-row-tools {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.1rem;
}

.btn-country-edit-icon,
.btn-country-clone-icon,
.btn-country-review-icon,
.btn-country-history-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--muted);
    opacity: 0.55;
    cursor: pointer;
    /* appearance гасит рамку и фон нативной кнопки, если стиль не догрузился */
    -webkit-appearance: none;
    appearance: none;
    transition: color 0.15s ease, background 0.15s ease, opacity 0.15s ease, box-shadow 0.15s ease;
}

/* Иконки в каждой строке перетягивают внимание с цифр, поэтому в покое они приглушены */
.countries-table tbody tr:hover .btn-country-edit-icon,
.countries-table tbody tr:hover .btn-country-clone-icon,
.countries-table tbody tr:hover .btn-country-review-icon,
.countries-table tbody tr:hover .btn-country-history-icon,
.countries-table tr.is-expanded .btn-country-edit-icon,
.countries-table tr.is-expanded .btn-country-clone-icon,
.countries-table tr.is-expanded .btn-country-review-icon,
.countries-table tr.is-expanded .btn-country-history-icon,
.btn-country-edit-icon:focus-visible,
.btn-country-clone-icon:focus-visible,
.btn-country-review-icon:focus-visible,
.btn-country-history-icon:focus-visible {
    opacity: 1;
}

.btn-country-edit-icon .icon-pencil,
.btn-country-clone-icon .icon-copy,
.btn-country-review-icon .icon-ai,
.btn-country-history-icon .icon-history {
    display: block;
    flex-shrink: 0;
}

.btn-country-edit-icon:hover,
.btn-country-clone-icon:hover,
.btn-country-review-icon:hover:not(:disabled),
.btn-country-history-icon:hover {
    color: var(--primary);
    background: rgba(37, 99, 235, 0.1);
}

.btn-country-edit-icon:focus-visible,
.btn-country-clone-icon:focus-visible,
.btn-country-review-icon:focus-visible,
.btn-country-history-icon:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.45);
}

/* Разбор идёт до полуминуты. Без явного признака работы кнопку жмут повторно */
.btn-country-review-icon:disabled {
    cursor: default;
    opacity: 0.3;
}

.btn-country-review-icon.is-busy {
    opacity: 1;
    color: var(--primary);
    animation: geo-review-pulse 1.1s ease-in-out infinite;
}

@keyframes geo-review-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

.countries-table tr.is-expanded .btn-country-edit-icon {
    color: var(--primary);
    background: rgba(37, 99, 235, 0.12);
}

/* Под строкой раскрыт разбор, а не форма: подсвечена должна быть та иконка,
   которая его открыла, иначе карандаш выглядит нажатым без причины */
.countries-table tr.is-review-open .btn-country-edit-icon {
    color: var(--muted);
    background: transparent;
}

.countries-table tr.is-review-open .btn-country-review-icon,
.countries-table tr.is-review-open .btn-country-history-icon {
    color: var(--primary);
    background: rgba(37, 99, 235, 0.12);
}

.country-detail-row > .country-detail-cell {
    padding: 0 !important;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
    position: sticky;
    left: 0;
    z-index: 6;
    vertical-align: top;
}

/* width на td в таблице не срабатывает — ограничиваем внутренний блок */
.country-detail-inner {
    width: var(--countries-scroll-w, 100cqi);
    max-width: var(--countries-scroll-w, 100cqi);
    min-width: 0;
    box-sizing: border-box;
}

.country-edit-panel {
    padding: 0.35rem 0.65rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    overflow: visible;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}

.country-edit-section {
    margin: 0;
    padding: 0.38rem 0.48rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    overflow: visible;
}

/* Секция с открытой подсказкой выше следующих блоков — иначе их фон перекрывает ::after */
.country-edit-panel .country-edit-section:has(.score-hint:hover) {
    position: relative;
    z-index: 28;
}

.countries-add-form-sectioned fieldset.config-block:has(.score-hint:hover) {
    position: relative;
    z-index: 28;
}

.country-edit-panel .country-edit-section--common {
    padding: 0.25rem 0.38rem;
}

.country-edit-panel .country-edit-section--common .country-edit-title {
    margin-bottom: 0.2rem;
}

.country-edit-title {
    margin: 0 0 0.35rem 0;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--muted);
}

.country-edit-actions {
    margin-top: 0.35rem;
    padding-top: 0.45rem;
    border-top: 1px solid var(--border);
    display: flex;
    gap: 0.45rem;
    flex-wrap: wrap;
}

.country-edit-panel .check-input {
    display: inline-flex;
    align-items: center;
    gap: 0.28rem;
    margin: 0;
    flex: 0 0 auto;
    min-width: 0;
    font-size: 0.72rem;
    line-height: 1.2;
    white-space: nowrap;
}

.country-edit-panel .check-input span {
    min-width: 0;
}

.country-edit-panel .check-input input[type="checkbox"] {
    flex-shrink: 0;
    margin: 0;
}

/* Форма «Добавить страну» — та же плотность */
.countries-add-form-sectioned .config-block {
    padding: 0.55rem 0.65rem;
    margin-bottom: 0.45rem;
}

.countries-add-form-sectioned fieldset.countries-fieldset--common {
    padding: 0.38rem 0.5rem;
    margin-bottom: 0.35rem;
}

.countries-add-form-sectioned .countries-fieldset-hint {
    margin-bottom: 0.35rem;
    font-size: 0.8rem;
}

.countries-add-form-sectioned .check-input {
    display: inline-flex;
    align-items: center;
    gap: 0.28rem;
    flex: 0 0 auto;
    font-size: 0.72rem;
    min-width: 0;
    white-space: nowrap;
}

.countries-add-form-sectioned .check-input span {
    min-width: 0;
}

.countries-add-form-sectioned fieldset.config-block legend {
    font-size: 0.78rem;
    font-weight: 600;
    padding: 0 0.35rem;
}

.countries-table th,
.countries-table td {
    padding: 0.5rem 0.75rem;
    text-align: left;
    border-bottom: 1px solid var(--border);
}

.countries-table th {
    background: var(--bg);
    color: var(--muted);
    font-size: 0.85rem;
}

.score-hint {
    position: relative;
    display: inline-block;
    margin-left: 0.25rem;
    width: 1em;
    height: 1em;
    font-size: 0.85rem;
    line-height: 1;
    color: var(--muted);
    cursor: help;
    opacity: 0.85;
    vertical-align: middle;
}

.score-hint:hover {
    color: var(--primary);
    opacity: 1;
}

.score-hint::after {
    content: attr(data-tooltip);
    position: absolute;
    /* Левый край совпадает с иконкой — не уезжает влево за экран/скролл как при translateX(-50%) */
    left: 0;
    right: auto;
    bottom: calc(100% + 6px);
    transform: none;
    z-index: 100;
    min-width: 180px;
    max-width: min(280px, calc(100vw - 12px));
    padding: 0.5rem 0.65rem;
    font-size: 0.8rem;
    line-height: 1.35;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 4px 14px rgba(15, 23, 42, 0.12);
    /* pre-line, а не normal: в строке сигнала одна иконка объясняет сразу балл,
       порог и галочку, и эти части разделены переводом строки в data-tooltip */
    white-space: pre-line;
    text-align: left;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.15s, visibility 0.15s;
    pointer-events: none;
}

.score-hint:hover::after {
    opacity: 1;
    visibility: visible;
}

.countries-table th .score-hint::after {
    min-width: 200px;
    max-width: min(320px, calc(100vw - 12px));
    /* В узкой ячейке заголовка иконка ближе к правому краю — подсказка растёт влево */
    left: auto;
    right: 0;
}

/* Панель под строкой таблицы: подсказка вверх уходит под sticky-колонки — показываем снизу от ⓘ */
.country-edit-panel .score-hint::after {
    top: calc(100% + 6px);
    bottom: auto;
    z-index: 50;
}

/* Форма «Добавить страну» (секции): первая ⓘ у края — подсказка снизу, как в панели редактирования */
.countries-add-form-sectioned .score-hint::after {
    top: calc(100% + 6px);
    bottom: auto;
    z-index: 50;
}

/*
 * Панель под строкой таблицы: абсолютный ::after обрезается overflow-x у обёртки и уходит под соседние секции.
 * Класс score-hint--fixed-viewport выставляет JS (--hint-tip-*); position: fixed — в слое viewport.
 */
.country-edit-panel .score-hint.score-hint--fixed-viewport::after,
.countries-add-form-sectioned .score-hint.score-hint--fixed-viewport::after {
    position: fixed !important;
    left: var(--hint-tip-left) !important;
    top: var(--hint-tip-top) !important;
    right: auto !important;
    bottom: auto !important;
    transform: none !important;
    z-index: 2147483646;
    max-width: var(--hint-tip-maxw, min(280px, calc(100vw - 16px)));
    min-width: 180px;
}

.countries-table td.actions {
    white-space: nowrap;
}

.countries-table tr.editing input.edit-input {
    width: 3rem;
    max-width: none;
    padding: 0.25rem;
}

.btn-small {
    padding: 0.3rem 0.5rem;
    font-size: 0.8rem;
}

.badge.role-admin { background: var(--primary); color: #fff; }
.badge.role-user { background: var(--border); color: var(--muted); }

.checkbox-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
    cursor: pointer;
}

.checkbox-label input[type="checkbox"] {
    width: auto;
    max-width: none;
}

/* ===== Страница пресетов ===== */

.presets-lead {
    max-width: 60rem;
    margin: 0.3rem 0 0 0;
    font-size: 0.85rem;
}

.presets-list {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    margin-top: 1rem;
}

.preset-card {
    padding: 0.7rem 0.9rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 4px solid var(--primary);
    border-radius: 8px;
}

/* Скрытый пресет остаётся в списке: его настройки нужны правилам, которые на нём стоят */
.preset-card--off {
    border-left-color: var(--border);
    opacity: 0.7;
}

.preset-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.3rem 0.8rem;
}

.preset-card-title {
    font-size: 1rem;
    font-weight: 600;
}

.preset-card-key {
    font-size: 0.75rem;
    color: var(--muted);
}

.preset-card-max b {
    color: var(--primary);
}

.preset-card-max,
.preset-card-uses {
    font-size: 0.8rem;
    color: var(--muted);
}

.preset-card-badge {
    padding: 0 0.4rem;
    border-radius: 999px;
    background: var(--bg);
    font-size: 0.7rem;
    color: var(--muted);
}

.preset-card-actions {
    margin-left: auto;
}

.preset-card-note {
    margin: 0.35rem 0 0 0;
    max-width: 62rem;
    font-size: 0.82rem;
    color: var(--muted);
}

/* Проверка есть в системе, но пресет про неё не знает: применение её не тронет */
.preset-card-missing {
    margin: 0.35rem 0 0 0;
    font-size: 0.8rem;
    color: var(--warning, #b45309);
}

.preset-editor {
    margin-top: 1.2rem;
}

.preset-form {
    padding: 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
}

.preset-form-head {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem 1.2rem;
    align-items: flex-end;
}

.preset-field {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    font-size: 0.78rem;
    color: var(--muted);
}

.preset-field input[type="text"],
.preset-field input[type="number"],
.preset-field textarea {
    padding: 0.3rem 0.45rem;
    font-size: 0.9rem;
}

.preset-field--num input {
    width: 5rem;
}

.preset-field--check {
    flex-direction: row;
    align-items: center;
    gap: 0.4rem;
}

.preset-field--wide {
    margin-top: 0.7rem;
}

.preset-field--wide textarea {
    max-width: 60rem;
}

.preset-form-common {
    margin-top: 1rem;
    padding-top: 0.7rem;
    border-top: 1px solid var(--border);
}

.preset-form-section {
    margin-top: 1rem;
}

.preset-form-section h3 {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0 0 0.4rem 0;
    font-size: 0.85rem;
}

.preset-form-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.9rem;
    margin-top: 1.2rem;
    padding-top: 0.8rem;
    border-top: 1px solid var(--border);
}

.preset-form-total {
    font-size: 0.85rem;
    color: var(--muted);
}

.preset-form-total b {
    font-size: 1.3rem;
    color: var(--primary);
}

.preset-form-msg {
    font-size: 0.8rem;
    color: var(--muted);
}

.preset-form-msg.is-error {
    color: var(--danger, #dc2626);
}

.preset-form-foot .btn:first-of-type {
    margin-left: auto;
}

/* ---------- Ключи доступа к приёмнику лидов ---------- */

.apikey-lead {
    max-width: 62ch;
}

.alert {
    padding: 0.75rem 1rem;
    border-radius: 6px;
    border: 1px solid transparent;
    margin: 0 0 1rem;
    font-size: 0.9rem;
}

.alert-ok {
    background: #ecfdf5;
    border-color: #a7f3d0;
    color: #047857;
}

.alert-err {
    background: #fef2f2;
    border-color: #fecaca;
    color: #b91c1c;
}

.apikey-howto {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 1rem 1.15rem;
    margin-bottom: 1.5rem;
    background: var(--surface);
}

.apikey-howto h3 {
    margin: 0 0 0.35rem;
    font-size: 0.95rem;
}

.apikey-howto .muted {
    margin-bottom: 0.6rem;
}

.apikey-howto .muted:last-child {
    margin-bottom: 0;
}

.apikey-code {
    margin: 0 0 0.75rem;
    padding: 0.75rem 0.9rem;
    background: #f8f8f9;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.82rem;
    line-height: 1.5;
    overflow-x: auto;
}

.apikey-card {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 1rem 1.15rem;
    margin-bottom: 1rem;
    background: var(--surface);
}

/* Трекер, который уже закрыт ключом, видно по левой кромке, не читая подписей */
.apikey-card.is-strict {
    border-left: 3px solid var(--success);
}

.apikey-card--orphan {
    border-left: 3px solid var(--warning);
}

.apikey-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-bottom: 0.75rem;
}

.apikey-name {
    font-weight: 600;
}

.apikey-slug {
    margin-left: 0.5rem;
    color: var(--muted);
    font-size: 0.85rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.apikey-badge {
    display: inline-block;
    padding: 0.15rem 0.45rem;
    border-radius: 4px;
    font-size: 0.78rem;
    white-space: nowrap;
}

.apikey-ok      { background: #ecfdf5; color: #047857; }
.apikey-ready   { background: #eff6ff; color: #1d4ed8; }
.apikey-partial { background: #fffbeb; color: var(--warning); }
.apikey-missing { background: #f4f4f5; color: var(--muted); }
.apikey-bad     { background: #fef2f2; color: #b91c1c; }

.apikey-keyrow {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 0.85rem;
}

.apikey-value {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: #f8f8f9;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.82rem;
    color: var(--text);
}

.apikey-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.85rem;
    margin-bottom: 0.85rem;
}

.apikey-table th {
    text-align: left;
    font-weight: 500;
    color: var(--muted);
    padding: 0.3rem 0.5rem;
    border-bottom: 1px solid var(--border);
}

.apikey-table td {
    padding: 0.35rem 0.5rem;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.apikey-table tr:last-child td {
    border-bottom: none;
}

.apikey-table .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.apikey-table code {
    font-size: 0.82rem;
}

.apikey-table .muted {
    margin: 0;
    font-size: 0.82rem;
}

.apikey-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.apikey-form {
    margin: 0;
}

/* ==========================================================================
   Пользователи: список и карточка доступа
   ========================================================================== */

.user-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin-bottom: 0.9rem;
}

.user-search {
    width: min(260px, 100%);
    padding: 0.35rem 0.6rem;
    background: #fff;
    border: 1px solid #d4d4d8;
    border-radius: 6px;
    color: var(--text);
    font-family: inherit;
    font-size: 0.85rem;
}

.user-search:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.22);
}

.user-toolbar .user-count {
    font-size: 0.82rem;
    color: var(--muted);
}

.user-toolbar .btn {
    margin-left: auto;
}

.user-list {
    display: grid;
    gap: 0.4rem;
    list-style: none;
    padding: 0;
    margin: 0;
}

.user-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.75rem;
    padding: 0.7rem 0.9rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
}

.user-row-login {
    font-weight: 600;
    font-size: 0.95rem;
    word-break: break-all;
}

.user-row-access {
    font-size: 0.82rem;
    color: var(--muted);
}

/* Права на трекеры перечисляем в строке: чаще всего их один-два, и ради
   ответа «а что у него есть» не хочется открывать правку */
.user-row-trackers {
    display: flex;
    flex-basis: 100%;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    margin: 0;
    font-size: 0.8rem;
    color: var(--muted);
}

.user-row-tracker {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
}

.user-row-tracker code {
    padding: 0.1rem 0.35rem;
    background: var(--bg);
    border-radius: 4px;
    font-size: 0.78rem;
    color: var(--text);
}

.user-row .btn {
    margin-left: auto;
}

.user-empty {
    margin: 0.5rem 0 0;
    font-size: 0.85rem;
    color: var(--muted);
}

/* -------------------- карточки формы -------------------- */

.user-card {
    margin-bottom: 0.9rem;
    padding: 1rem 1.15rem 1.1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
}

.user-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.75rem;
    margin-bottom: 0.8rem;
}

.user-card-title {
    font-size: 0.95rem;
    font-weight: 600;
}

.user-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 0 1rem;
}

.user-form .user-fields label {
    margin-bottom: 0;
}

.user-form .user-fields input {
    max-width: none;
}

.user-field-note {
    font-weight: 400;
    text-transform: none;
}

/* -------------------- выбор роли -------------------- */

.role-choice {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Радиокнопка спрятана, но не выключена: выбор остаётся клавиатурным,
   а рамку в фокусе рисуем самой карточке */
.role-option {
    position: relative;
    flex: 1 1 16rem;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}

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

.role-option:hover {
    border-color: var(--text);
}

.role-option:has(input:checked) {
    border-color: var(--primary);
    background: rgba(37, 99, 235, 0.06);
    box-shadow: inset 0 0 0 1px var(--primary);
}

.role-option:has(input:focus-visible) {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.role-option-name {
    display: block;
    font-size: 0.9rem;
    font-weight: 600;
}

.role-option:has(input:checked) .role-option-name {
    color: var(--primary);
}

.role-option-note {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.8rem;
    line-height: 1.4;
    color: var(--muted);
}

/* -------------------- доступ к трекерам -------------------- */

.uacc-count {
    font-size: 0.82rem;
    color: var(--muted);
}

.uacc-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-left: auto;
}

.uacc-search {
    width: min(200px, 100%);
    padding: 0.32rem 0.6rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text);
    font-family: inherit;
    font-size: 0.82rem;
}

.uacc-search:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.22);
}

/* Список прокручивается: пятнадцать трекеров с раскрытыми аффилиатами
   иначе уводят кнопку сохранения далеко вниз */
.uacc-list {
    display: grid;
    gap: 0.35rem;
    max-height: 24rem;
    overflow-y: auto;
    padding-right: 0.2rem;
}

.uacc-row {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 10px;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.uacc-row.is-on {
    background: var(--surface);
    border-color: rgba(37, 99, 235, 0.45);
}

.uacc-main {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.5rem 0.7rem;
    margin: 0;
    cursor: pointer;
}

.uacc-main input[type="checkbox"] {
    width: auto;
    max-width: none;
    margin: 0;
    flex: none;
}

.uacc-name {
    font-size: 0.9rem;
    font-weight: 500;
}

.uacc-slug {
    padding: 0.1rem 0.4rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 4px;
    font-family: ui-monospace, monospace;
    font-size: 0.75rem;
    color: var(--muted);
}

.uacc-row.is-on .uacc-slug {
    background: var(--surface);
}

.uacc-state {
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--muted);
}

.uacc-aff {
    display: none;
    align-items: center;
    gap: 0.5rem;
    padding: 0 0.7rem 0.6rem 2.05rem;
}

.uacc-row.is-on .uacc-aff {
    display: flex;
}

.uacc-aff-label {
    flex: none;
    font-size: 0.78rem;
    color: var(--muted);
}

.uacc-chips {
    display: flex;
    flex: 1;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
    padding: 0.25rem 0.35rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
}

.uacc-chips:focus-within {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
}

.uacc-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.1rem 0.15rem 0.1rem 0.5rem;
    background: rgba(37, 99, 235, 0.1);
    border-radius: 999px;
    font-size: 0.8rem;
    color: var(--primary);
}

/* Повторный ID не добавляем — вспышкой показываем, что он уже есть */
@keyframes uacc-dup {
    from { background: rgba(220, 38, 38, 0.25); }
    to   { background: rgba(37, 99, 235, 0.1); }
}

.uacc-chip.is-dup {
    animation: uacc-dup 0.9s ease;
}

.uacc-chip-text {
    font-variant-numeric: tabular-nums;
}

.uacc-chip-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.1rem;
    height: 1.1rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.6;
}

.uacc-chip-x:hover {
    background: rgba(37, 99, 235, 0.22);
    opacity: 1;
}

.uacc-chip-x:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.5);
    opacity: 1;
}

.uacc-input {
    flex: 1 1 9rem;
    min-width: 7rem;
    padding: 0.15rem 0.2rem;
    border: none;
    background: transparent;
    color: var(--text);
    font: inherit;
    font-size: 0.85rem;
}

.uacc-input:focus {
    outline: none;
}

.uacc-empty,
.uacc-hint {
    margin: 0.6rem 0 0;
    font-size: 0.8rem;
    color: var(--muted);
}

@media (max-width: 560px) {
    /* Вложенная прокрутка на узком экране мешает больше, чем помогает */
    .uacc-list {
        max-height: none;
        overflow: visible;
    }

    .uacc-aff {
        flex-wrap: wrap;
        padding-left: 0.7rem;
    }

    .uacc-tools {
        width: 100%;
        margin-left: 0;
    }

    .uacc-search {
        width: 100%;
    }
}
