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

/* ===== Токены: светлая тема ===== */
:root {
    --color-bg: #f7f5f0;
    --color-surface: #ffffff;
    --color-surface-muted: #efece3;
    --color-border: #e1dccf;
    --color-border-strong: #cdc4ac;
    --color-text: #24211c;
    /* Единственный приглушённый тон текста. Отдельный ещё более светлый
       --color-text-faint здесь стоял раньше — на проверке контраста
       (WCAG 1.4.3, 4.5:1 для некрупного текста) он не дотягивал даже до
       3:1 на фоне: 2.75:1 к --color-bg, 2.99:1 к --color-surface. Поднять
       его до проходного значения означало свести к тому же тону, что и
       --color-text-muted, — раз запас яркости кончился на этом самом
       muted, разводить их дальше некуда: используем один проверенный
       тон везде, где раньше стоял «более тихий» вариант. */
    --color-text-muted: #6f6a5c;
    --color-accent: #2b5a82;
    --color-error: #a02f2f;

    /* Плашки статуса: пара фон/текст на каждое значение ItemStatus,
       плюс включена/выключена для ленты. Приглушённые тона — это не
       светофор, а пометка на полях. Каждая пара проверена на 4.5:1
       фон/текст — это её собственный контекст чтения, а не страница
       вокруг. */
    --badge-new-bg: #eceae2;
    --badge-new-fg: #57534a;
    --badge-selected-bg: #dce8f2;
    --badge-selected-fg: #2b5a82;
    --badge-extracted-bg: #dcefe9;
    --badge-extracted-fg: #1f6f5c;
    --badge-drafted-bg: #eae2f4;
    --badge-drafted-fg: #5b3f8f;
    --badge-published-bg: #dff0df;
    --badge-published-fg: #2a702d;
    --badge-rejected-bg: #f7ecd9;
    --badge-rejected-fg: #8a5a1f;
    --badge-failed-bg: #f8dede;
    --badge-failed-fg: #a02f2f;
    --badge-enabled-bg: #dff0df;
    --badge-enabled-fg: #2a702d;
    --badge-disabled-bg: #efece3;
    --badge-disabled-fg: #686356;

    --color-warning: #8f5f1c;
    --color-focus-ring: #2b5a82;

    --font-sans:
        system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

    --text-heading: 1.75rem;
    --text-subheading: 1.25rem;
    --text-body: 1rem;
    --text-service: 0.8125rem;

    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;

    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 16px;

    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.06), 0 1px 1px rgba(0, 0, 0, 0.04);

    --content-table: 72rem;
    --content-reading: 44rem;
}

/* ===== Токены: тёмная тема — то же назначение, другие значения ===== */
@media (prefers-color-scheme: dark) {
    :root {
        --color-bg: #171511;
        --color-surface: #201d18;
        --color-surface-muted: #2a261f;
        --color-border: #3a352c;
        --color-border-strong: #4d4636;
        --color-text: #ece7dc;
        --color-text-muted: #a89f8d;
        --color-accent: #86b6e0;
        --color-error: #f0a3a3;

        --badge-new-bg: #2e2b24;
        --badge-new-fg: #b7b0a0;
        --badge-selected-bg: #1f3548;
        --badge-selected-fg: #8ec2ea;
        --badge-extracted-bg: #16332c;
        --badge-extracted-fg: #7fd0b9;
        --badge-drafted-bg: #2c2140;
        --badge-drafted-fg: #c3a8ee;
        --badge-published-bg: #1c3320;
        --badge-published-fg: #8fd996;
        --badge-rejected-bg: #3a2d14;
        --badge-rejected-fg: #e0b269;
        --badge-failed-bg: #3a1c1c;
        --badge-failed-fg: #f0a3a3;
        --badge-enabled-bg: #1c3320;
        --badge-enabled-fg: #8fd996;
        --badge-disabled-bg: #2e2b24;
        --badge-disabled-fg: #a89f8d;

        --color-warning: #e0b269;
        --color-focus-ring: #86b6e0;

        --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 1px rgba(0, 0, 0, 0.35);
    }
}

/* ===== Сброс и типографика ===== */
*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    color-scheme: light dark;
}

body {
    margin: 0;
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-sans);
    font-size: var(--text-body);
    line-height: 1.6;
}

h1,
h2 {
    font-weight: 600;
    /* Заголовки крупнее и плотнее строчного текста — редакционная иерархия,
       не служебная. */
    line-height: 1.2;
    letter-spacing: -0.01em;
}

h1 {
    font-size: var(--text-heading);
    margin: 0 0 var(--space-5);
}

h2 {
    font-size: var(--text-subheading);
    margin: 0 0 var(--space-3);
}

a {
    color: var(--color-accent);
}

/* Видимый фокус — единственный способ пользоваться админкой с клавиатуры.
   :focus-visible не трогает мышиный клик, поэтому обычная стилизация
   кнопок не гасит его незаметно для себя. */
a:focus-visible,
button:focus-visible,
input:focus-visible {
    outline: 3px solid var(--color-focus-ring);
    outline-offset: 2px;
}

/* ===== Разметка страницы ===== */
header {
    border-bottom: 1px solid var(--color-border);
    background: var(--color-surface);
}

.header-inner {
    max-width: var(--content-table);
    margin: 0 auto;
    padding: var(--space-4) var(--space-5);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    flex-wrap: wrap;
}

header nav {
    display: flex;
    gap: var(--space-5);
    flex-wrap: wrap;
}

header nav a {
    color: var(--color-text-muted);
    text-decoration: none;
    font-size: var(--text-service);
    letter-spacing: 0.02em;
    text-transform: uppercase;
    padding-bottom: var(--space-1);
    border-bottom: 2px solid transparent;
}

header nav a:hover {
    color: var(--color-text);
}

/* Текущая страница помечена подчёркиванием цветом акцента — не жирностью,
   чтобы строка навигации не прыгала при переходах. */
header nav a.active {
    color: var(--color-text);
    border-bottom-color: var(--color-accent);
}

.logout-form {
    margin: 0;
}

.btn-quiet {
    background: none;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    font-size: var(--text-service);
    padding: var(--space-1) var(--space-3);
    cursor: pointer;
}

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

main {
    max-width: var(--content-table);
    margin: 0 auto;
    padding: var(--space-6) var(--space-5) var(--space-7);
}

/* Колонка для чтения постов — уже общей ширины таблиц, так измерение
   строки не растягивается за пределы удобного для глаза. */
.reading {
    max-width: var(--content-reading);
    margin: 0 auto;
}

/* ===== Таблицы: только горизонтальные линии, без сетки ===== */
table {
    width: 100%;
    border-collapse: collapse;
}

th,
td {
    text-align: left;
    padding: var(--space-3) var(--space-3) var(--space-3) 0;
    border-bottom: 1px solid var(--color-border);
    vertical-align: top;
}

th {
    font-size: var(--text-service);
    color: var(--color-text-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

tbody tr:hover {
    background: var(--color-surface-muted);
}

/* Заголовок новости и то, что относится к нему: русский вариант заголовка
   и причина отказа теперь живут одной колонкой под ним, а не тянут
   отдельные столбцы через всю таблицу. */
.headline {
    color: var(--color-text);
}

.headline-draft {
    color: var(--color-text-muted);
    font-style: italic;
    margin-top: var(--space-1);
}

/* Причина отказа и мнение модели — один и тот же служебный текст под
   заголовком: на главной они идут одной строкой, на странице ленты
   мнение стоит само по себе. */
.reject-reason,
.rating-reason {
    color: var(--color-text-muted);
    font-size: var(--text-service);
    margin-top: var(--space-1);
}

.muted {
    color: var(--color-text-muted);
    font-size: var(--text-service);
}

/* Оценка — крупная цифра с моноширинными (табличными) цифрами, чтобы
   колонка не дрожала при сортировке. */
.score {
    font-size: 1.25rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.score-empty {
    color: var(--color-text-muted);
    font-weight: 400;
}

.warning {
    color: var(--color-warning);
    font-weight: 600;
}

/* Строка выключенной ленты помечена целиком, а не одной ячейкой — она не
   участвует в сборе, и это должно быть видно с одного взгляда на список.
   Раньше это делалось цветом текста помимо --color-text-muted, но
   заголовок ленты и прочие данные строки — это то, что человек должен
   суметь прочитать, а не орнамент; приглушать их контрастом ниже нормы
   ради «выключенности» неправильно. Метка — фон плюс плашка статуса
   (badge-disabled), а не пониженная читаемость текста. */
tr.row-disabled {
    background: var(--color-surface-muted);
    color: var(--color-text-muted);
}

tr.row-disabled a {
    color: inherit;
}

/* ===== Плашки статуса ===== */
.badge {
    display: inline-block;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-lg);
    font-size: var(--text-service);
    font-weight: 600;
    white-space: nowrap;
}

.badge-new {
    background: var(--badge-new-bg);
    color: var(--badge-new-fg);
}

.badge-selected {
    background: var(--badge-selected-bg);
    color: var(--badge-selected-fg);
}

.badge-extracted {
    background: var(--badge-extracted-bg);
    color: var(--badge-extracted-fg);
}

.badge-drafted {
    background: var(--badge-drafted-bg);
    color: var(--badge-drafted-fg);
}

.badge-published {
    background: var(--badge-published-bg);
    color: var(--badge-published-fg);
}

.badge-rejected {
    background: var(--badge-rejected-bg);
    color: var(--badge-rejected-fg);
}

.badge-failed {
    background: var(--badge-failed-bg);
    color: var(--badge-failed-fg);
}

.badge-enabled {
    background: var(--badge-enabled-bg);
    color: var(--badge-enabled-fg);
}

.badge-disabled {
    background: var(--badge-disabled-bg);
    color: var(--badge-disabled-fg);
}

/* ===== Фильтры и сортировка: ряд плашек-ссылок ===== */
.filters,
.sort {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-3);
    font-size: var(--text-service);
    color: var(--color-text-muted);
}

.pill {
    display: inline-block;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-lg);
    border: 1px solid var(--color-border);
    color: var(--color-text-muted);
    text-decoration: none;
}

.pill:hover {
    border-color: var(--color-border-strong);
    color: var(--color-text);
}

.pill.active {
    background: var(--color-accent);
    border-color: var(--color-accent);
    color: var(--color-surface);
}

/* ===== Карточки: форма добавления ленты, форма входа ===== */
.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: var(--space-5);
    margin-top: var(--space-6);
}

.auth-card {
    max-width: 24rem;
    margin: var(--space-7) auto;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: var(--space-6);
}

/* ===== Формы ===== */
form label {
    display: block;
    margin-bottom: var(--space-4);
    font-size: var(--text-service);
    color: var(--color-text-muted);
}

form input {
    display: block;
    width: 100%;
    margin-top: var(--space-1);
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-body);
    font-family: inherit;
    color: var(--color-text);
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
}

/* Списки в формах выглядят как поля ввода. Отдельное правило, а не
   добавление `select` в селектор `form input`, нужно уже потому, что тот
   селектор целится в тег `<input>` и на `<select>` не действует. Сейчас
   оба правила совпадают побайтово — но разойдись стиль полей и списков
   впоследствии, разница могла бы появиться только здесь. */
form label select {
    display: block;
    width: 100%;
    margin-top: var(--space-1);
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-body);
    font-family: inherit;
    color: var(--color-text);
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
}

button,
form button {
    font-family: inherit;
    font-size: var(--text-body);
    padding: var(--space-2) var(--space-4);
    background: var(--color-accent);
    color: var(--color-surface);
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

button:hover {
    filter: brightness(1.1);
}

/* Кнопка включения/выключения ленты — рядовая, а не главное действие
   строки, поэтому тише основной кнопки формы. Свой класс, а не селектор
   по вложенности (td form button): будущая форма в ячейке не должна
   унаследовать этот вид просто оттого, что она внутри <td>. */
.btn-toggle {
    background: none;
    color: var(--color-accent);
    border: 1px solid var(--color-border-strong);
    padding: var(--space-1) var(--space-3);
    font-size: var(--text-service);
}

.error {
    color: var(--color-error);
    font-size: var(--text-service);
    margin-bottom: var(--space-4);
}

/* ===== Опубликованное: карточки постов ===== */
.post-card {
    padding: var(--space-6) 0;
    border-bottom: 1px solid var(--color-border);
}

.post-card:first-child {
    padding-top: 0;
}

.post-card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
}

.post-card-head h2 {
    margin: 0;
}

.post-time {
    flex-shrink: 0;
    color: var(--color-text-muted);
    font-size: var(--text-service);
    white-space: nowrap;
}

.post-body {
    /* ~65 символов в строке — то, ради чего вообще существует измерение
       в типографике: длинную строку глаз теряет при переносе. */
    max-width: 65ch;
    white-space: pre-wrap;
    margin: var(--space-4) 0;
}

.hashtags {
    margin: 0 0 var(--space-2);
}

.hashtag {
    color: var(--color-accent);
    font-size: var(--text-service);
    margin-right: var(--space-2);
}

.post-meta {
    color: var(--color-text-muted);
    font-size: var(--text-service);
    margin: 0;
}

/* ===== Пагинация ===== */
.pager {
    display: flex;
    gap: var(--space-4);
    margin-top: var(--space-5);
    font-size: var(--text-service);
}

/* Смена режима ленты: список и кнопка в одну строку, чтобы ячейка таблицы
   не растягивалась по высоте. `form input` выше задаёт блочный вид и
   ширину в 100% — для <select> в ячейке это не годится. */
.mode-form {
    display: flex;
    gap: var(--space-2);
    align-items: center;
}

.mode-form select {
    padding: var(--space-1) var(--space-2);
    font-size: var(--text-service);
    font-family: inherit;
    color: var(--color-text);
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
}

/* Панель массовой правки под таблицей лент. Форма связана с галочками в
   строках атрибутом form, а не вложенностью, — стоять она может только
   отдельным блоком, и выглядит как карточка. */
.bulk-panel {
    margin-top: var(--space-5);
}

.bulk-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.bulk-row:last-child {
    margin-bottom: 0;
}

/* Подпись и поле в одну строку — правило `form label` выше делает подпись
   блочной, а здесь она стоит слева от контрола. */
.bulk-row label,
.mode-form label {
    display: inline;
    margin-bottom: 0;
    white-space: nowrap;
}

/* Числовое поле в ряду не растягивается на всю ширину, как обычное поле
   формы: часы — это два-три знака, а не строка. */
.bulk-row input[type="number"],
.mode-form input[type="number"] {
    display: inline-block;
    width: 7rem;
    margin-top: 0;
}

/* Колонка окна — цифры в табличном начертании, чтобы не дрожала. */
.numeric {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ===== Страница ленты: состояние опроса парами «что — значение» ===== */
.feed-state {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: var(--space-4);
    margin: 0 0 var(--space-6);
    padding: var(--space-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
}

.feed-state dt {
    font-size: var(--text-service);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.feed-state dd {
    margin: var(--space-1) 0 0;
    /* Текст последней ошибки приходит от чужого сервера и бывает длинным:
       переносим по любому месту, иначе он растягивает всю сетку. */
    overflow-wrap: anywhere;
}

/* Формы правки на странице ленты стоят в ряд, а не одна под другой:
   поля у них короткие, и вертикальный столбик из двух строк выглядел бы
   длиннее, чем есть. */
.card .mode-form {
    margin-bottom: var(--space-4);
}

.card .mode-form:last-of-type {
    margin-bottom: 0;
}

/* ===== Страница прогонов: список стадий внутри строки таблицы ===== */
.stage-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.stage-list li {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.stage-name {
    color: var(--color-text-muted);
    font-size: var(--text-service);
    min-width: 6rem;
}
