/*
  AuditLLM — компоненты. Источник: шаблон v2, раздел «Компоненты».
  Каждый компонент ложится на существующий класс: .btn, .field, .tip,
  .summary-card, .data-table, .notice. Имена прежних компонентов сохранены,
  чтобы панель оператора (/admin) продолжала работать.
*/

/* ── Кнопки ──────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 56px;
  padding: 0 var(--sp-6);
  font-family: var(--font-sans);
  font-size: var(--fs-button);
  font-weight: 600;
  line-height: 1;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--field-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur) ease, border-color var(--dur) ease, color var(--dur) ease;
}
.btn:hover { background: var(--paper-sunk); text-decoration: none; }
.btn:active { background: var(--line); }
.btn[disabled], .btn[aria-disabled="true"], .btn:disabled {
  background: var(--paper-sunk);
  border-color: var(--line);
  color: var(--muted);
  cursor: not-allowed;
}
.btn-primary {
  background: var(--rust);
  border-color: var(--rust);
  color: #FFFFFF;
}
.btn-primary:hover { background: var(--rust-hover); border-color: var(--rust-hover); color: #FFFFFF; }
.btn-primary:active { background: var(--rust-hover); }
.btn-primary[disabled], .btn-primary[aria-disabled="true"] {
  background: var(--paper-sunk);
  border-color: var(--line);
  color: var(--muted);
}
.btn-dark { background: var(--forest); border-color: var(--forest); color: var(--on-forest); }
.btn-dark:hover { background: var(--forest-2); border-color: var(--forest-2); color: var(--on-forest); }
.btn-outline { background: transparent; border-color: var(--field-border); color: var(--ink); }
.btn-outline:hover { background: var(--card); }
.btn-danger { background: var(--bad); border-color: var(--bad); color: #FFFFFF; }
.btn-danger:hover { background: #7F2517; border-color: #7F2517; color: #FFFFFF; }
.btn-danger[disabled], .btn-danger[aria-disabled="true"] {
  background: var(--paper-sunk);
  border-color: var(--line);
  color: var(--muted);
}
.btn-quiet {
  background: transparent;
  border-color: transparent;
  color: var(--rust-hover);
  padding: 0 var(--sp-3);
  min-height: var(--tap);
}
.btn-quiet:hover { background: var(--rust-soft); color: var(--rust-hover); }
.btn-sm { min-height: 44px; padding: 0 var(--sp-4); font-size: var(--fs-caption); }
.btn-lg { min-height: 64px; font-size: var(--fs-body); padding: 0 var(--sp-7); }
.btn-block { width: 100%; }
.btn .arrow { font-family: var(--font-sans); font-weight: 500; }
.section--forest .btn-outline, .console .btn-outline { border-color: var(--forest-3); color: var(--on-forest); }
.section--forest .btn-outline:hover, .console .btn-outline:hover { background: var(--forest-2); }

/* ── Метки, значки, статусы ──────────────────────────────────────────────── */
.chip {
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  background: var(--paper-sunk);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-size: var(--fs-micro);
  font-weight: 600;
  color: var(--ink-2);
  white-space: nowrap;
  line-height: 1.4;
}
.chip--mono { font-family: var(--font-mono); font-weight: 500; letter-spacing: -0.01em; }
.chip--beta { background: var(--rust-soft); color: var(--rust-hover); }
.chip--plain { background: transparent; border-color: var(--line); }
.chip--express {
  border: 1px dashed var(--good);
  background: transparent;
  color: var(--good);
  border-radius: var(--radius-pill);
}
.chip--sm { padding: 2px 8px; }
.chip--wrap { white-space: normal; overflow-wrap: anywhere; max-width: 100%; }
a.chip:hover { text-decoration: none; border-color: var(--line-strong); }
button.chip { font: inherit; font-size: var(--fs-micro); font-weight: 600; cursor: pointer; min-height: 32px; padding: 4px 10px; }
button.chip:hover { border-color: var(--line-strong); }

.level {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-micro);
  font-weight: 600;
  white-space: nowrap;
  line-height: 1.4;
}
.level::before { font-size: 0.9em; line-height: 1; }
.level--measured { background: var(--good-soft); color: var(--good); }
.level--measured::before { content: "●"; }
.level--deviation { background: var(--warn-soft); color: var(--warn); }
.level--deviation::before { content: "▲"; }
.level--substitution_suspected { background: var(--bad-soft); color: var(--bad); }
.level--substitution_suspected::before { content: "■"; }
.level--confirmed_external { background: var(--forest); color: var(--on-forest); }
.level--confirmed_external::before { content: "◆"; }
.level--none, .level--insufficient { background: var(--paper-sunk); color: var(--muted); }
.level--none::before, .level--insufficient::before { content: "○"; }
.level--plain { background: transparent; border: 1px solid var(--line); color: var(--ink-2); }

.status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-micro);
  font-weight: 600;
  color: var(--ink-2);
  background: var(--paper-sunk);
  border-radius: var(--radius-pill);
  padding: 4px 10px;
}
.status::before { color: var(--muted); }
.status--public::before { content: "●"; color: var(--good); }
.status--private::before { content: "◐"; color: var(--ink-2); }
.status--unverified::before { content: "○"; }
.status--verified::before { content: "●"; color: var(--good); }
.status--official::before { content: "●"; color: var(--rust); }

.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-micro);
  font-weight: 600;
  background: var(--paper-sunk);
  color: var(--ink-2);
}
.tag-accent { background: var(--rust-soft); color: var(--rust-hover); }
.tag-warn { background: var(--warn-soft); color: var(--warn); }
.tag-good { background: var(--good-soft); color: var(--good); }
.tag-bad { background: var(--bad-soft); color: var(--bad); }
.tag-beta { background: var(--rust-soft); color: var(--rust-hover); }

/* ── Карточки ────────────────────────────────────────────────────────────── */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
}
.card--flush { padding: 0; overflow: hidden; }
.card--sunk { background: var(--paper-sunk); }
.card--forest { background: var(--forest); border-color: var(--forest); color: var(--on-forest); }
.card--forest h2, .card--forest h3, .card--forest h4 { color: var(--on-forest); }
.card--forest .muted, .card--forest .hint { color: var(--on-forest-muted); }
.card--plain { background: transparent; }
.card--tight { padding: var(--sp-5); }
.card-head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--sp-5);
}
.card-head h2, .card-head h3 { margin: 0; }
.card-head--ruled { border-bottom: 1px solid var(--line); padding-bottom: var(--sp-4); }
.card > :last-child { margin-bottom: 0; }

/* ── Уведомления ─────────────────────────────────────────────────────────── */
.notice {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  padding: var(--sp-4) var(--sp-5);
  background: var(--paper-sunk);
  border-radius: var(--radius);
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--ink-2);
}
.notice::before {
  flex: 0 0 auto;
  font-size: 15px;
  line-height: 1.35;
}
.notice > * { margin: 0; }
.notice strong, .notice b { display: block; color: var(--ink); }
.notice--info::before { content: "ⓘ"; color: var(--ink-2); }
.notice--warn { background: var(--warn-soft); color: var(--warn); }
.notice--warn::before { content: "⚠"; }
.notice--warn strong { color: var(--warn); }
.notice--good { background: var(--good-soft); color: var(--good); }
.notice--good::before { content: "✓"; }
.notice--good strong { color: var(--good); }
.notice--bad { background: var(--bad-soft); color: var(--bad); }
.notice--bad::before { content: "⊖"; }
.notice--bad strong { color: var(--bad); }
.notice--sunk { background: var(--paper-sunk); }
.notice + .notice { margin-top: var(--sp-3); }
.notice a { color: inherit; text-decoration: underline; }

/* Прежнее имя: блок-примечание в панели оператора. */
.note-box {
  display: block;
  padding: var(--sp-4) var(--sp-5);
  background: var(--paper-sunk);
  border-left: 3px solid var(--line-strong);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: var(--fs-caption);
  line-height: 1.5;
  margin: 0 0 var(--sp-4);
}
.note-box.info { border-left-color: var(--good); background: var(--good-soft); }
.note-box.bad { border-left-color: var(--bad); background: var(--bad-soft); }
.info, .bad { border-radius: var(--radius); }
.bad { color: var(--bad); }

/* ── Оценка ──────────────────────────────────────────────────────────────── */
.report-body { margin-block: var(--sp-6); }
.report-body .stat-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.report-body .stat small { font-size: var(--fs-caption); }
.report-body .scale-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.report-body .console-links a { display: inline-flex; align-items: center; min-height: var(--tap); }
@media (min-width: 1440px) {
  .report-body .stat-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.summary-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  padding: var(--sp-6);
}
.summary-card--express { border-style: dashed; }

.score { display: grid; gap: var(--sp-4); }
.score-value {
  font-family: var(--font-display);
  font-size: var(--fs-score);
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: -0.02em;
  color: var(--ink);
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
}
.score-value small {
  font-family: var(--font-sans);
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
}
/* Без оценки на месте числа стоит прочерк: тем же кеглем он выглядел бы чёрной плашкой. */
.score-value--none {
  font-size: var(--fs-h2);
  line-height: 1.1;
  color: var(--muted);
  letter-spacing: 0;
}
.score-grade {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.2;
}
.score-grade::before { font-size: 0.7em; }
.score-grade--excellent { color: var(--good); }
.score-grade--excellent::before { content: "●"; }
.score-grade--good { color: var(--good-2); }
.score-grade--good::before { content: "●"; }
.score-grade--issues { color: var(--warn); }
.score-grade--issues::before { content: "▲"; }
.score-grade--poor { color: var(--bad); }
.score-grade--poor::before { content: "■"; }
.score-grade--insufficient { color: var(--muted); }
.score-grade--insufficient::before { content: "○"; }

/* Шкала summary-v1: 0–49 слабый, 50–69 замечания, 70–84 хорошо, 85–100 отлично. */
.scale { display: grid; gap: var(--sp-2); }
.scale-track {
  position: relative;
  height: 10px;
  border-radius: var(--radius-pill);
  background: linear-gradient(to right,
    var(--bad-soft) 0 50%,
    var(--warn-soft) 50% 70%,
    var(--good-soft) 70% 85%,
    var(--good-soft-2, var(--good-soft)) 85% 100%);
}
.scale-track--insufficient { background: var(--paper-sunk); }
.scale-marker {
  position: absolute;
  top: -7px;
  width: 2px;
  height: 24px;
  background: var(--ink);
  border-radius: 2px;
  transform: translateX(-1px);
}
.scale-marker::before {
  content: "";
  position: absolute;
  top: -5px;
  left: 50%;
  transform: translateX(-50%);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ink);
}
/* Деления стоят на своих значениях: 50/70/85 совпадают с порогами полос трека. */
.scale-ticks { position: relative; height: 1.4em; font-size: var(--fs-micro); color: var(--muted); font-family: var(--font-mono); }
.scale-ticks span { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.scale-ticks span:nth-child(1) { left: 0; transform: none; }
.scale-ticks span:nth-child(2) { left: 50%; }
.scale-ticks span:nth-child(3) { left: 70%; }
.scale-ticks span:nth-child(4) { left: 85%; }
.scale-ticks span:nth-child(5) { left: 100%; transform: translateX(-100%); }
.scale-legend { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2) var(--sp-4); font-size: var(--fs-caption); }
@media (min-width: 620px) { .scale-legend { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* Маркер держится первой строки подписи: при переносе он не «уезжает» вниз по центру блока. */
.scale-legend span { display: inline-flex; align-items: baseline; gap: 6px; color: var(--ink-2); }
.scale-legend i { font-style: normal; }

/* Компоненты оценки: подпись, вес, полоса, балл. */
.components { display: grid; gap: var(--sp-4); }
.component { display: grid; gap: 6px; }
.component-head { display: flex; gap: var(--sp-3); align-items: baseline; justify-content: space-between; }
.component-head strong { font-size: var(--fs-caption); }
.component-head .weight { color: var(--muted); font-size: var(--fs-micro); }
.component-bar { height: 8px; border-radius: var(--radius-pill); background: var(--paper-sunk); overflow: hidden; }
.component-bar span { display: block; height: 100%; background: var(--good); border-radius: var(--radius-pill); }
.component-bar span.is-warn { background: var(--warn); }
.component-bar span.is-bad { background: var(--bad); }
.component-note { color: var(--muted); font-size: var(--fs-micro); }
.component-score { font-family: var(--font-mono); font-size: var(--fs-caption); font-weight: 600; }

/* Три знаменателя: задачи, ответы, запросы. */
.denominators { display: grid; gap: var(--sp-5); grid-template-columns: 1fr; }
@media (min-width: 700px) { .denominators { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.denominator { display: grid; gap: var(--sp-1); }
.denominator b { font-family: var(--font-display); font-size: clamp(24px, 1.6rem + 1vw, 34px); font-weight: 600; line-height: 1.1; }
.denominator b em { font-style: normal; color: var(--muted); font-weight: 500; }
.denominator small { color: var(--ink-2); }
.denominator .fault { color: var(--bad); font-weight: 600; }

/* ── Полоса показателей (лесная) ─────────────────────────────────────────── */
/* Слот показателей: заполненный — отбивает следующий блок, пустой — не занимает места. */
.stat-slot:not(:empty) { margin-bottom: var(--sp-6); }
/* Шкала оценки не прилипает к строке меток над ней (карточка «Статус оценки»). */
.scale-box { margin-top: var(--sp-5); }

.stat-strip {
  background: var(--forest);
  color: var(--on-forest);
  border-radius: var(--radius-lg);
  padding: var(--sp-5) var(--sp-6);
  display: grid;
  /* Подпись, значение и примечание — общие строки для всех колонок: значение не съезжает,
     если подпись перенеслась на две строки. */
  column-gap: var(--sp-5);
  row-gap: 4px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: auto auto auto;
}
@media (min-width: 860px) { .stat-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* Пять показателей (сводка аккаунта) — на широком экране в одну строку. */
@media (min-width: 860px) { .stat-strip--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.stat { display: grid; gap: 4px; min-width: 0; grid-row: span 3; grid-template-rows: subgrid; }
.stat dt, .stat-label {
  font-size: var(--fs-micro);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--on-forest-muted);
  margin: 0;
}
.stat dd, .stat-value {
  margin: 0;
  font-family: var(--font-mono);
  font-size: clamp(1.25rem, 1rem + 1vw, 1.75rem);
  font-weight: 500;
  line-height: 1.15;
  color: var(--on-forest);
  overflow-wrap: anywhere;
}
.stat--plain dd, .stat--plain .stat-value { font-family: var(--font-display); }
.stat small { color: var(--on-forest-muted); }
.stat-strip--paper { background: var(--paper-sunk); color: var(--ink); }
.stat-strip--paper .stat dd, .stat-strip--paper .stat-value { color: var(--ink); }
.stat-strip--paper dt, .stat-strip--paper .stat-label, .stat-strip--paper small { color: var(--muted); }

/* ── Строка фактов (провайдер, модель, набор задач, шкала, запуск) ────────── */
/* Шапка отчёта: заголовок, метки и полоса метаданных не липнут друг к другу. */
/* Шапка отчёта: заголовок с плашками отделяется и от крошек сверху, и от таблицы с замерами снизу. */
.report-head { align-items: flex-end; gap: var(--sp-5); margin-bottom: var(--sp-6); }
.report-head h1 { margin-bottom: var(--sp-5); }
.report-head-chips { gap: var(--sp-3); }

/* Колонки считаются от ширины самого блока, а не окна: тот же список стоит и во всю ширину
   страницы, и внутри узкой карточки модели, где фиксированные 3–6 колонок наезжали друг на друга. */
.meta-strip {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr));
  padding: var(--sp-6) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.meta-strip > div { min-width: 0; }
.meta-strip dt {
  font-size: var(--fs-micro);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 4px;
}
.meta-strip dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: var(--ink);
  overflow-wrap: anywhere;
}
.meta-strip dd a { color: var(--ink); }

/* Пошаговая проверка сертификата: команда и кнопка «Скопировать» стоят в одной строке,
   чтобы не приходилось выделять текст в тёмном блоке вручную. */
.verify-card { margin-top: var(--sp-5); }
.verify-steps { margin: 0; padding-left: 1.4em; display: grid; gap: var(--sp-5); }
.verify-steps > li::marker { color: var(--rust); font-weight: 700; }
.verify-steps h3 { margin: 0 0 var(--sp-2); }
.verify-steps p { margin: 0 0 var(--sp-3); max-width: 68ch; font-size: var(--fs-caption); color: var(--ink-2); }
.verify-cmd { display: flex; gap: var(--sp-3); align-items: flex-start; flex-wrap: wrap; }
.verify-cmd .json { flex: 1 1 340px; margin: 0; }
.verify-cmd .btn { flex: none; }

/* Адрес отчёта (/check/<id>): статичную форму проверки не показываем ни кадра —
   её место займёт отчёт, который собирает скрипт. Признак ставит /view-mode.js. */
html[data-view="report"] #checkView .split > :first-child { display: none; }
html[data-view="report"] #formRoot { min-height: 320px; }

/* ── Вкладки, крошки, раскрывающиеся разделы ─────────────────────────────── */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: center;
  font-size: var(--fs-micro);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
  /* Воздух с двух сторон: под шапкой сайта и между крошками и заголовком страницы.
     Мелкая строка крошек вплотную к крупному заголовку читалась как его часть. */
  margin: 0 0 var(--sp-6);
  padding: var(--sp-7) 0 0;
  list-style: none;
}
/* Одиночная крошка повторяет заголовок страницы и только занимает место: не показываем её. */
.crumbs:has(> *:only-child) { display: none; }
/* Там, где крошек нет, первый блок страницы сам отбивается от шапки. */
main > .row:first-child { padding-top: var(--sp-5); }
/* Обычная инлайн-строка: все пункты живут в одном строковом боксе и выравниваются
   по базовой линии сами. Флекс-обёртки давали сдвиг последнего пункта на 4 px. */
.crumbs { align-items: baseline; }
.crumbs > * { display: inline; }
.crumbs > * + *::before { content: "/"; color: var(--line-strong); margin: 0 var(--sp-2); }
.crumbs a { color: var(--muted); }
.crumbs a:hover { color: var(--rust-hover); }
.crumbs [aria-current="page"] { color: var(--ink-2); }

.tabs { display: flex; flex-wrap: wrap; gap: var(--sp-5); border-bottom: 1px solid var(--line); margin: 0 0 var(--sp-6); padding: 0; list-style: none; }
.tab {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: var(--sp-3) 0;
  min-height: var(--tap);
  font: inherit;
  font-weight: 600;
  font-size: var(--fs-caption);
  color: var(--ink-2);
  cursor: pointer;
  text-decoration: none;
}
.tab:hover { color: var(--ink); text-decoration: none; }
.tab[aria-selected="true"], .tab[aria-current="page"] { color: var(--ink); border-bottom-color: var(--rust); }

.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--paper-sunk);
  border-radius: var(--radius-sm);
}
.segmented button, .segmented a {
  appearance: none;
  border: 0;
  background: transparent;
  border-radius: 6px;
  padding: 8px 14px;
  min-height: 44px;
  font: inherit;
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.segmented button[aria-selected="true"], .segmented a[aria-current="page"] { background: var(--card); color: var(--ink); box-shadow: var(--shadow-card); }
.segmented .count-badge { color: var(--muted); font-family: var(--font-mono); font-size: var(--fs-micro); }

.toolbar { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: flex-end; margin: 0 0 var(--sp-5); }
.toolbar .field { margin-bottom: 0; flex: 1 1 220px; }
.toolbar .field--select { flex: 0 1 220px; }
/* Фильтры истории измерений: длинный селект не растягивает ряд, короткие не рвут правый край. */
.toolbar .field--wide { flex: 1 1 220px; }
@media (max-width: 480px) { .toolbar .field, .toolbar .field--select, .toolbar .field--wide { flex: 1 1 100%; } }
.filters { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; }

.disclosure {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.disclosure + .disclosure { margin-top: var(--sp-3); }
/* Раскрывающийся блок под таблицей не слипается с ней. */
.table-wrap + .disclosure, .data-table + .disclosure, .disclosure--stacked { margin-top: var(--sp-5); }
.disclosure > summary {
  display: flex;
  gap: var(--sp-4);
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-5) var(--sp-6);
  cursor: pointer;
  list-style: none;
  min-height: var(--tap);
  font-weight: 600;
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary::after {
  content: "▾";
  color: var(--muted);
  font-size: 12px;
  transition: transform var(--dur) ease;
}
.disclosure[open] > summary::after { transform: rotate(180deg); }
.disclosure > summary .summary-meta { color: var(--muted); font-weight: 500; font-size: var(--fs-caption); margin-left: auto; }
.disclosure .disclosure-body { padding: 0 var(--sp-6) var(--sp-6); }

/* Архивные фильтры сужают длинные списки, не меняя сами измерения. */
.provider-model-filter, .model-offering-filter { max-width: 28rem; margin: 0 0 var(--sp-5); }
.provider-model-filter p, .model-offering-filter p { margin: 0; }
.provider-offering[hidden] { display: none; }
.provider-offering .disclosure { background: var(--paper-sunk); }
.provider-offering .disclosure .meta-strip { margin-top: var(--sp-4); }
.provider-offering .disclosure dd small { display: block; margin-top: var(--sp-2); color: var(--muted); font-size: var(--fs-caption); }
.provider-offering .disclosure ul { padding-left: var(--sp-5); margin: var(--sp-3) 0; }
.records .cell-open a { display: inline-flex; align-items: center; min-height: var(--tap); font-weight: 600; white-space: nowrap; }

/* ── Подсказка «?» ───────────────────────────────────────────────────────── */
/* Кнопку «?» создаёт nav.js (button.tip + data-tip), текст показывается в общем
   bubble-элементе .tip-bubble, поэтому стилизуются оба. */
button.tip, .tip {
  appearance: none;
  position: relative;
  background: none;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  width: 20px;
  height: 20px;
  min-height: 0;
  padding: 0;
  margin-left: 6px;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  color: var(--muted);
  cursor: help;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  flex: 0 0 auto;
}
button.tip:hover { border-color: var(--ink-2); color: var(--ink); }
/* Область нажатия не меньше 44 px, сам значок остаётся маленьким. */
button.tip::after { content: ""; position: absolute; inset: -12px; }
.console button.tip { border-color: var(--forest-3); color: var(--on-forest-muted); }
.console button.tip:hover { border-color: var(--on-forest); color: var(--on-forest); }
.tip-bubble {
  position: absolute;
  z-index: 1000;
  max-width: min(320px, calc(100vw - 24px));
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  background: var(--forest);
  color: var(--on-forest);
  font: 400 13px/1.5 var(--font-sans);
  letter-spacing: 0;
  text-transform: none;
  box-shadow: 0 10px 30px rgba(20, 32, 26, .28);
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .14s ease, transform .14s ease;
}
.tip-bubble.on { opacity: 1; transform: none; }
.tip-bubble::after {
  content: "";
  position: absolute;
  left: calc(var(--arrow-x, 50%) - 6px);
  bottom: -6px;
  border: 6px solid transparent;
  border-bottom: 0;
  border-top-color: var(--forest);
}
.tip-bubble.below::after { bottom: auto; top: -6px; border: 6px solid transparent; border-top: 0; border-bottom-color: var(--forest); }
[data-tip] { cursor: help; }

/* ── Поля консоли проверки (тёмная панель) ───────────────────────────────── */
.console {
  background: var(--forest);
  color: var(--on-forest);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
}
@media (min-width: 768px) { .console { padding: var(--sp-6); } }
.console-head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
  justify-content: space-between;
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--forest-3);
  margin-bottom: var(--sp-4);
  font-size: var(--fs-micro);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--on-forest-muted);
}
.console-head .console-live { display: inline-flex; align-items: center; gap: 8px; color: var(--on-forest); }
.console-head .console-live::before { content: "●"; color: var(--rust-on-forest); font-size: 10px; }
.console h1, .console h2, .console h3 { color: var(--on-forest); }
.console .lede { color: var(--on-forest-muted); }
.console-field { margin-bottom: var(--sp-4); }
.console-field > label, .console-field .field-label {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--on-forest-muted);
  margin-bottom: var(--sp-2);
}
.console-field .field-num { margin-left: auto; font-family: var(--font-mono); color: var(--on-forest-muted); font-weight: 500; }
.console-field input, .console-field select, .console-field textarea {
  background: var(--card);
  border-color: var(--card);
  color: var(--ink);
}
.console-field .hint, .console-note { color: var(--on-forest-muted); font-size: var(--fs-micro); }
.console-field .card .hint { color: var(--muted); }
.console-examples { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.console-examples button {
  appearance: none;
  font: inherit;
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--on-forest);
  background: var(--forest-2);
  border: 1px solid var(--forest-3);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  min-height: var(--tap);
  cursor: pointer;
}
.console-examples button:hover { background: var(--forest-3); }
/* Публичность отчёта — одна строка рядом с кнопкой запуска, а не блок в пол-экрана:
   гость видит главный факт, поля и кнопка остаются в одном экране. */
.privacy-note {
  margin: var(--sp-3) 0;
  font-size: var(--fs-micro);
  line-height: 1.5;
  color: var(--on-forest-muted);
}
.privacy-note::before { content: "⊕"; color: var(--rust-on-forest); margin-right: var(--sp-2); }
.privacy-note a { color: var(--rust-on-forest); text-decoration: underline; text-underline-offset: 2px; }
.privacy-note a:hover { color: var(--on-forest); }
.console-links { display: flex; flex-wrap: wrap; gap: var(--sp-5); margin-top: var(--sp-4); font-size: var(--fs-caption); font-weight: 600; }
/* Читаются на своём фоне: на бумаге — ржавый, в тёмной консоли и лесной карточке — кремовый. */
.console-links a { color: var(--accent-text); }
.console .console-links a, .card--forest .console-links a, .section--forest .console-links a { color: var(--on-forest); }
.console .btn-primary { width: 100%; justify-content: space-between; }
.console.console--light { background: var(--card); color: var(--ink); border: 1px solid var(--line); }
.console.console--light .console-head { border-bottom-color: var(--line); color: var(--muted); }
.console.console--light .console-field > label { color: var(--ink-2); }
.console.console--light .console-note, .console.console--light .console-field .hint { color: var(--muted); }
/* Ссылка внутри примечания: на тёмном фоне --rust-hover даёт 1,8:1, нужен светлый акцент. */
.console .console-note a { color: var(--rust-on-forest); }
.console.console--light .console-note a { color: var(--rust-hover); }
/* Длинная подпись опции не обрезается посреди слова без многоточия. */
.console-field select, .field select { text-overflow: ellipsis; }

/* ── Выбор ID модели у провайдера ────────────────────────────────────────── */
/* Кнопки стоят в поле рядом с ID модели, а список раскрывается окном поверх страницы:
   карточка проверки не растёт, кнопка запуска остаётся на месте. */
.mp { position: relative; margin-top: var(--sp-3); }
/* Поле с выбором модели шире остальных: кнопке, поиску и списку нужна вся ширина консоли,
   иначе кнопки переносятся на вторую строку и карточка растёт. */
.console-field.has-model-picker, .field.has-model-picker { grid-column: 1 / -1; }
.mp-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
.mp .btn { min-height: var(--tap); }
/* Пока адрес или ключ не заполнены, кнопка подсказывает это видом, но остаётся нажимаемой:
   по нажатию она объясняет, чего именно не хватает. */
.mp-actions .btn.mp-not-ready { border-style: dashed; color: var(--muted); }
.console .mp-actions .btn {
  background: var(--forest-2);
  border-color: var(--forest-3);
  color: var(--on-forest);
  font-size: var(--fs-caption);
  padding: 0 var(--sp-4);
}
.console .mp-actions .btn:hover { background: var(--forest-3); }
.console .mp-actions .btn.mp-not-ready { color: var(--on-forest-muted); }
.console .mp-actions .btn[disabled] { background: var(--forest-2); border-color: var(--forest-3); color: var(--on-forest-muted); cursor: progress; }
.console.console--light .mp-actions .btn { background: var(--card); border-color: var(--field-border); color: var(--ink); }
.console.console--light .mp-actions .btn:hover { background: var(--paper-sunk); }

/* Строка состояния загрузки: это результат действия, а не пояснение к полю, поэтому она не берёт
   класс .console-note — на коротких экранах пояснения скрываются, а результат обязан быть виден. */
.mp-status { display: flex; align-items: flex-start; gap: var(--sp-2); margin: var(--sp-2) 0 0; color: var(--muted); font-size: var(--fs-micro); }
.console .mp-status { color: var(--on-forest-muted); }
.mp-status[hidden] { display: none; }
.mp-status[data-state="warn"], .mp-status[data-state="error"] { color: var(--bad); }
.console .mp-status[data-state="warn"], .console .mp-status[data-state="error"] { color: var(--rust-on-forest); }
.mp-status[data-state="loading"]::before {
  content: "";
  flex: none;
  width: 10px;
  height: 10px;
  margin-top: .45em;
  border-radius: 50%;
  background: currentColor;
}
@media (prefers-reduced-motion: no-preference) {
  .mp-status[data-state="loading"]::before { animation: pulse-soft 1.4s var(--ease-soft) infinite; }
}

/* Окно списка лежит поверх страницы: форма под ним не перестраивается.
   Живёт прямо в body и позиционируется от экрана (координаты считает скрипт), поэтому его
   не ловит контекст наложения карточки и сквозь него не просвечивает текст нижнего слоя.
   z-index выше кнопки «наверх» (40) и ниже шапки с меню (1000). */
.mp-panel {
  position: fixed;
  left: var(--mp-left, var(--sp-3));
  width: var(--mp-width, min(420px, calc(100vw - 2 * var(--sp-3))));
  z-index: 60;
  max-height: var(--mp-room, min(420px, 62vh));
  min-width: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  background: var(--card);
  background-color: var(--card);
  color: var(--ink);
  border: 1px solid var(--field-border);
  border-radius: var(--radius);
  box-shadow: 0 16px 40px rgba(12, 24, 18, .32);
}
/* Окно раскрывается вверх — так список не уезжает за нижний край и не закрывает кнопку запуска. */
.mp-panel[data-placement="top"] { bottom: var(--mp-bottom, 0); }
/* Места нет ни сверху, ни снизу: окно занимает свободную высоту экрана целиком. */
.mp-panel[data-placement="bottom"] { top: var(--mp-top, 0); }
.mp-panel[data-placement="sheet"] {
  top: var(--mp-top, 0);
  bottom: auto;
  height: var(--mp-height, auto);
  max-height: none;
}
/* В окне на всю высоту список занимает всё свободное место, а не свои обычные 340px. */
.mp-panel[data-placement="sheet"] .mp-list { max-height: none; }
.mp-panel[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  /* backwards, а не both: залитая анимация оставила бы на окне transform. */
  .mp-panel { animation: unfold var(--motion-2) var(--ease-out) backwards; }
}
/* Поиск — первая строка окна: список прокручивается под ней и не наезжает на поле ввода. */
.mp-search-row { padding: var(--sp-3); border-bottom: 1px solid var(--line); }
.mp-search {
  width: 100%;
  min-height: var(--tap);
  padding: 0 var(--sp-3);
  font: inherit;
  font-size: var(--fs-caption);
  color: var(--ink);
  background: var(--paper-sunk);
  border: 1px solid var(--field-border);
  border-radius: var(--radius-sm);
}
.mp-search:focus-visible { outline: 2px solid var(--rust); outline-offset: 1px; }
/* Высота списка ограничена: окно не занимает весь экран, а внутри списка есть своя прокрутка. */
.mp-list { max-height: min(340px, 44vh); overflow-y: auto; overscroll-behavior: contain; padding: var(--sp-2); }
.mp-group + .mp-group { margin-top: var(--sp-2); }
.mp-vendor {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0 0 var(--sp-1);
  padding: var(--sp-1) var(--sp-2);
  background: var(--paper-sunk);
  border-radius: var(--radius-sm);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
}
.mp-option {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-3);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  overflow-wrap: anywhere;
  cursor: pointer;
}
.mp-option:hover { background: var(--paper-sunk); }
.mp-option:focus-visible { outline: 2px solid var(--rust); outline-offset: -2px; }
.mp-option[aria-selected="true"] { background: var(--rust-soft); font-weight: 600; }
.mp-empty, .mp-more { margin: 0; padding: var(--sp-3); color: var(--muted); font-size: var(--fs-caption); }
.mp-more { border-top: 1px solid var(--line); }
.mp-more[hidden] { display: none; }

/* Скрытые нетекстовые модели — нижняя строка того же окна: карточка проверки из-за неё не растёт. */
.mp-hidden { margin: 0; padding: 0 var(--sp-3); border-top: 1px solid var(--line); color: var(--muted); }
.mp-hidden[hidden] { display: none; }
.mp-hidden summary { display: flex; align-items: center; min-height: var(--tap); cursor: pointer; font-size: var(--fs-micro); }
.mp-hidden-note { margin: var(--sp-2) 0 0; max-width: 62ch; font-size: var(--fs-micro); }
.mp-hidden ul { margin: var(--sp-2) 0 var(--sp-3); padding-left: 1.1em; max-height: 180px; overflow-y: auto; font-size: var(--fs-micro); }
.mp-hidden li { margin-bottom: var(--sp-1); overflow-wrap: anywhere; }

/* ── Живой ход проверки ──────────────────────────────────────────────────── */
.run-progress { display: grid; gap: var(--sp-3); }
.run-progress-head { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: baseline; justify-content: space-between; }
.run-progress-head strong { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; }
.run-progress-track { height: 10px; border-radius: var(--radius-pill); background: var(--paper-sunk); overflow: hidden; }
.run-progress-track span { display: block; height: 100%; background: var(--rust); border-radius: var(--radius-pill); transition: width var(--dur) linear; }
.run-log { display: grid; gap: var(--sp-2); margin: 0; padding: 0; list-style: none; font-size: var(--fs-caption); }
.run-log li { display: flex; gap: var(--sp-3); align-items: baseline; justify-content: space-between; padding: var(--sp-2) 0; border-bottom: 1px solid var(--line); }
.run-log li:last-child { border-bottom: 0; }
.run-log .ok::before { content: "✓"; color: var(--good); }
.run-log .fail::before { content: "✕"; color: var(--bad); }
.run-log .wait::before { content: "…"; color: var(--muted); }

/* ── Таблицы-компоненты ──────────────────────────────────────────────────── */
.matrix { width: 100%; border-collapse: collapse; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; }
.matrix th, .matrix td { padding: var(--sp-4); border-bottom: 1px solid var(--line); font-size: var(--fs-caption); text-align: left; }
.matrix thead th { font-size: var(--fs-micro); letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--muted); font-weight: 600; }
.matrix tbody tr:last-child td { border-bottom: 0; }
.matrix td.num, .matrix th.num { font-family: var(--font-mono); text-align: right; }
.matrix tbody tr:hover { background: var(--paper-sunk); }

/* ── Пустые состояния и состояния запроса ────────────────────────────────── */
/* Подпись секции перед карточкой состояния: без отбивки они слипались (4 px). */
main .section > .hint { margin-bottom: var(--sp-4); }

.empty, .state {
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  padding: var(--sp-7) var(--sp-6);
  background: var(--card);
  display: grid;
  gap: var(--sp-3);
  justify-items: start;
  text-align: left;
}
.empty h2, .empty h3, .state h2, .state h3 { margin: 0; font-size: var(--fs-h3); }
/* Заголовок пустого состояния переносится по смыслу, а не одним словом на второй строке. */
.callout h2, .empty h2, .empty h3, .state h2, .state h3 { text-wrap: balance; }
.empty p, .state p { color: var(--muted); max-width: 62ch; margin: 0; }
.empty--compact { padding: var(--sp-6); }
.state-error { border-style: solid; border-color: var(--bad); background: var(--bad-soft); }
.state-error p { color: var(--bad); }
.state-error h2, .state-error h3 { color: var(--bad); }
.state-loading { border-style: solid; background: var(--paper-sunk); border-color: var(--line); }
.state-text { color: var(--muted); }

/* ── Измерения: интервалы, полосы, диаграммы ─────────────────────────────── */
.ci {
  position: relative;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--paper-sunk);
  min-width: 90px;
}
.ci-fill { position: absolute; inset: 0 auto 0 0; background: var(--good-soft); border-radius: var(--radius-pill); }
.ci-range { position: absolute; top: 0; bottom: 0; background: var(--good); opacity: .35; border-radius: var(--radius-pill); }
.ci-range::after { content: none; }
.ci-dot { position: absolute; top: 50%; width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; border-radius: 50%; background: var(--good); }
.ci--warn .ci-fill { background: var(--warn-soft); }
.ci--warn .ci-range { background: var(--warn); }
.ci--warn .ci-dot { background: var(--warn); }
.ci--bad .ci-fill { background: var(--bad-soft); }
.ci--bad .ci-range { background: var(--bad); }
.ci--bad .ci-dot { background: var(--bad); }
.ci--none .ci-dot { background: var(--muted); }

.cat-rows { display: grid; gap: var(--sp-4); }
.cat-row { display: grid; gap: var(--sp-2); }
.cat-row-head { display: flex; gap: var(--sp-4); align-items: baseline; justify-content: space-between; }
.cat-row-head strong { font-size: var(--fs-caption); }
.cat-tally { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.cat-tally li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-3); align-items: center; font-size: var(--fs-caption); }
.cat-tally .bar { position: relative; height: 6px; background: var(--paper-sunk); border-radius: var(--radius-pill); overflow: hidden; }
.cat-tally .bar i { position: absolute; inset: 0 auto 0 0; background: var(--good); }

.levelbar { display: flex; height: 8px; border-radius: var(--radius-pill); overflow: hidden; min-width: 64px; background: var(--paper-sunk); }
.levelbar span { display: block; }
.levelbar .seg-measured { background: var(--good); }
.levelbar .seg-deviation { background: var(--warn); }
.levelbar .seg-substitution_suspected { background: var(--bad); }
.levelbar .seg-confirmed_external { background: var(--forest); }
.levelbar-empty { color: var(--muted); font-size: var(--fs-micro); }

.lat { display: grid; gap: var(--sp-3); }
.lat-row { display: grid; gap: 6px; }
.lat-label { font-size: var(--fs-caption); font-weight: 600; }
.lat-value { font-size: var(--fs-micro); color: var(--muted); font-family: var(--font-mono); }
.lat-track { position: relative; height: 8px; background: var(--paper-sunk); border-radius: var(--radius-pill); }
.lat-med { position: absolute; inset: 0 auto 0 0; background: var(--rust); border-radius: var(--radius-pill); }
.lat-p90 { position: absolute; top: -3px; width: 2px; height: 14px; background: var(--ink); }

/* Точечная диаграмма «Время до первого токена»: каждая точка — задача с ответом. */
/* Подпись метрики и значок «?» держатся вместе: иначе значение уезжает на строку вниз. */
.provider-offering dt { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; column-gap: 6px; }
.provider-offering dt > .tip { margin-top: 1px; }

.dotplot { display: grid; gap: var(--sp-3); }
.dotplot-row { display: grid; gap: 6px; }
.dotplot-label { display: flex; gap: var(--sp-3); justify-content: space-between; align-items: baseline; font-size: var(--fs-caption); }
.dotplot-track {
  position: relative;
  height: 26px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.dotplot-track i {
  position: absolute;
  top: 50%;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: var(--rust);
}
.dotplot-track i.unanswered { background: transparent; border: 1px solid var(--warn); border-radius: 1px; width: 6px; height: 6px; }
.dotplot-track .rule { position: absolute; top: 0; bottom: 0; border-left: 1px dashed var(--line-strong); }
.dotplot-track .rule--median { border-left-style: solid; border-left-color: var(--ink); }
.dotplot-legend { display: flex; flex-wrap: wrap; gap: var(--sp-4); font-size: var(--fs-micro); color: var(--muted); }
.dotplot-legend span { display: inline-flex; align-items: center; gap: 6px; }
.dotplot-legend i { width: 7px; height: 7px; border-radius: 50%; background: var(--rust); font-style: normal; }
.dotplot-legend i.unanswered { background: transparent; border: 1px solid var(--warn); border-radius: 1px; }
/* Деления идут по всей ширине трека; «секунд» выведено из потока и стоит под последним делением. */
.dotplot-axis { position: relative; display: flex; justify-content: space-between; padding-bottom: 1.35em; font-size: var(--fs-micro); color: var(--muted); font-family: var(--font-mono); }
.dotplot-axis .dotplot-unit { position: absolute; right: 0; bottom: 0; }

/* Надёжность запросов: сетка исходов. */
.outcome-grid { display: flex; flex-wrap: wrap; gap: 4px; max-width: 340px; }
.outcome-grid i { width: 18px; height: 18px; border-radius: 3px; background: var(--good); font-style: normal; }
.outcome-grid i.timeout { background: var(--warn); }
.outcome-grid i.streamCut { background: var(--bad); }
.outcome-grid i.rateLimited { background: var(--paper-sunk); border: 1px solid var(--line-strong); }
.outcome-legend { display: grid; gap: 6px; font-size: var(--fs-caption); }
.outcome-legend span { display: grid; grid-template-columns: 18px 1fr auto; gap: var(--sp-3); align-items: center; }
.outcome-legend i { width: 14px; height: 14px; border-radius: 3px; background: var(--good); font-style: normal; }
.outcome-legend i.timeout { background: var(--warn); }
.outcome-legend i.streamCut { background: var(--bad); }
.outcome-legend i.rateLimited { background: var(--paper-sunk); border: 1px solid var(--line-strong); }

/* Графики (SVG из charts.js) */
.chart { width: 100%; height: auto; display: block; overflow: visible; }
.chart text { font-family: var(--font-mono); font-size: 10px; fill: var(--muted); }
.chart .grid { stroke: var(--line); stroke-width: 1; }
.chart .axis { stroke: var(--line-strong); stroke-width: 1; }
.chart .line { fill: none; stroke: var(--rust); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .fill { fill: var(--chart-band); stroke: none; }
.chart .band { fill: var(--chart-band); stroke: none; }
.chart .dot { fill: var(--rust); }
.chart .marker { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 3; }
.chart .marker-label { fill: var(--muted); }
.chart .whisker { stroke: var(--line-strong); stroke-width: 1.5; }
.chart .track { fill: var(--paper-sunk); }
.chart .value { fill: var(--ink); font-weight: 600; }
.chart .p90 { stroke: var(--ink); stroke-width: 1; stroke-dasharray: 3 3; }
.chart .chart-point { cursor: pointer; }
.chart .point-hit { fill: transparent; }
.chart .point-guide { stroke: var(--line-strong); stroke-width: 1; opacity: 0; }
.chart .point-tip { opacity: 0; pointer-events: none; }
.chart .point-tip rect { fill: var(--forest); }
.chart .point-tip text { fill: var(--on-forest); }
.chart .chart-point:hover .point-tip,
.chart .chart-point:focus-visible .point-tip,
.chart .chart-point:focus .point-tip { opacity: 1; }
.chart .chart-point:hover .point-guide,
.chart .chart-point:focus .point-guide { opacity: 1; }
.chart .chart-point:focus .dot { r: 5; }
.spark .line { stroke-width: 1.6; }
.spark .dot { r: 2.5; }
.chart-box { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--sp-5); }
.chart-controls { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: flex-end; margin-bottom: var(--sp-5); }
.chart-controls .field { margin: 0; }

/* ── Списки, доказательства, ключ-значение ───────────────────────────────── */
.kv-list { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--sp-2) var(--sp-4); font-size: var(--fs-caption); }
.kv-list dt { color: var(--muted); font-weight: 600; }
.kv-list dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.evidence-list { display: grid; gap: var(--sp-2); margin: 0; padding: 0; list-style: none; font-size: var(--fs-caption); }
.evidence-list a { font-family: var(--font-mono); }
.check-list { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); }
.check-list label { display: inline-flex; gap: var(--sp-2); align-items: center; min-height: var(--tap); font-weight: 600; font-size: var(--fs-caption); }
.json, pre.json {
  background: var(--forest);
  color: var(--on-forest);
  padding: var(--sp-4);
  border-radius: var(--radius);
  overflow: auto;
  max-height: 360px;
  font-size: var(--fs-micro);
  line-height: 1.5;
}

/* ── Записи (карточки-строки на мобиле) ──────────────────────────────────── */
.record-list { display: grid; gap: var(--sp-3); margin: 0; padding: 0; list-style: none; }
.record {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--sp-4);
  display: grid;
  gap: var(--sp-2);
}
.record-head { display: flex; gap: var(--sp-3); align-items: center; justify-content: space-between; }
.record-title { font-family: var(--font-mono); font-weight: 600; font-size: var(--fs-caption); overflow-wrap: anywhere; }
.record-meta { display: flex; flex-wrap: wrap; gap: var(--sp-3); font-size: var(--fs-caption); color: var(--muted); }
.record-foot { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; justify-content: space-between; }

/* ── Шаги (как это работает) ─────────────────────────────────────────────── */
.steps { display: grid; gap: var(--sp-5); grid-template-columns: 1fr; counter-reset: step; }
@media (min-width: 700px) { .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.step { display: grid; gap: var(--sp-2); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.step::before { counter-increment: step; content: "0" counter(step); font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--rust-hover); }
.step h3 { font-family: var(--font-sans); font-size: var(--fs-body); margin: 0; }
.step p { color: var(--muted); font-size: var(--fs-caption); margin: 0; }
.step--plain::before { content: none; }

/* ── Прочее ──────────────────────────────────────────────────────────────── */
.beta-note {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--rust-soft);
  color: var(--rust-hover);
  font-size: var(--fs-micro);
  font-weight: 600;
}
.callout {
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  align-items: center;
  justify-content: space-between;
}
.callout h2 { margin: 0 0 var(--sp-2); }
.callout p { margin: 0; color: var(--muted); max-width: 56ch; }
.banner-dark {
  background: var(--forest);
  color: var(--on-forest);
  border-radius: var(--radius-lg);
  padding: var(--sp-5) var(--sp-6);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  align-items: center;
  justify-content: space-between;
}
.banner-dark h2 { color: var(--on-forest); font-size: var(--fs-h3); margin: 0 0 4px; }
.banner-dark p { color: var(--on-forest-muted); margin: 0; font-size: var(--fs-caption); }
.banner-dark .banner-mark { font-family: var(--font-mono); color: var(--rust-on-forest); font-size: var(--fs-h3); }

.hero { padding-block: var(--sp-8) var(--sp-9); }
/* Первый экран: утверждение и рабочая форма стоят рядом и делят ширину почти поровну. */
.hero-grid { display: grid; grid-template-columns: 1fr; gap: var(--sp-8); align-items: start; }
@media (min-width: 1000px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(40px, 9vw, 140px); }
}
.section--hero { padding-top: var(--sp-6); }
.accent { font-style: italic; color: var(--rust); }
.accent-light { font-style: italic; color: var(--rust-on-forest); }
.console-title { font-size: var(--fs-h3); margin: 0 0 6px; }
.depth-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-5); }
.depth-list li { display: grid; gap: 4px; padding-left: var(--sp-6); position: relative; }
.depth-list li::before { content: "✓"; position: absolute; left: 0; top: 0; color: var(--good); font-weight: 600; }
.depth-list strong { font-size: var(--fs-body); }
.depth-list span { color: var(--muted); font-size: var(--fs-caption); }
.hero-h1 { font-size: var(--fs-h1); line-height: var(--lh-head); }
.hero-h1 em { font-style: italic; color: var(--rust); }
.hero-points { display: grid; gap: var(--sp-3); margin: var(--sp-6) 0; padding: 0; list-style: none; }
.hero-points li { display: flex; gap: var(--sp-3); align-items: baseline; font-size: var(--fs-caption); color: var(--ink-2); }
.hero-points li::before { content: "◇"; color: var(--rust); font-size: 13px; }
.hero-form { position: relative; }
.hero-last {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
  justify-content: space-between;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-3) var(--sp-4);
  margin-top: var(--sp-4);
  font-size: var(--fs-caption);
}
.hero-last .label { font-size: var(--fs-micro); letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--muted); }

.depth-cards { display: grid; gap: var(--sp-5); grid-template-columns: 1fr; }
@media (min-width: 900px) { .depth-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.depth-card { border-radius: var(--radius-lg); padding: var(--sp-6); display: grid; gap: var(--sp-4); align-content: start; }
.depth-card--paper { background: var(--card); border: 1px solid var(--line); }
.depth-card--forest { background: var(--forest); color: var(--on-forest); }
.depth-card--forest h2, .depth-card--forest h3 { color: var(--on-forest); }
.depth-card--forest .muted, .depth-card--forest .hint, .depth-card--forest .depth-number small { color: var(--on-forest-muted); }
.depth-card .depth-number { font-family: var(--font-display); font-size: clamp(2.5rem, 2rem + 2vw, 3.5rem); font-weight: 600; line-height: 1; }
.depth-card .depth-number small { font-family: var(--font-sans); font-size: var(--fs-caption); font-weight: 500; color: var(--muted); margin-left: var(--sp-2); }
.depth-card ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.depth-card li { display: flex; gap: var(--sp-3); font-size: var(--fs-caption); }
.depth-card li::before { content: "✓"; color: var(--good); }
.depth-card--forest li::before { color: var(--good-soft); }

.sample-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-xl); padding: var(--sp-6); display: grid; gap: var(--sp-5); }
.sample-card--real { border: 2px dashed var(--good-2); }
.sample-head { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; justify-content: space-between; font-size: var(--fs-micro); color: var(--muted); }
.sample-task { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-2) var(--sp-4); padding: var(--sp-3) 0; border-top: 1px solid var(--line); font-size: var(--fs-caption); }
.sample-task span { color: var(--muted); }
.sample-task .ok { color: var(--good); font-weight: 600; }

/* Короткий экран ноутбука: поджимаем консоль, чтобы кнопка запуска была видна без прокрутки.
   Ступени по высоте: сначала отступы, затем вторичные пояснения. Факты о ключе и текстах
   остаются на месте — они в блоке «Не сохраняется», а не в подсказках полей. */
@media (max-height: 900px) {
  .section--hero { padding-top: var(--sp-3); }
  .hero-grid { padding-top: var(--sp-4); }
  .console { padding: var(--sp-4); }
  .console-field { margin-bottom: var(--sp-3); }
  .privacy-note { margin: var(--sp-3) 0; }
  .console .lede { margin-bottom: var(--sp-3); }
  /* Подсказки под полями уходят: те же факты остаются в блоке «Не сохраняется». */
  .console-field .hint, .console-field .console-note { display: none; }
  .console { padding-bottom: var(--sp-3); }
}
@media (max-height: 900px) {
  .console-head { display: none; }
  .console .lede { display: none; }
  .console-title { margin-bottom: 2px; }
  .privacy-note { line-height: 1.4; }
}
/* Совсем короткий экран: карточка обязана попасть в окно целиком.
   Строка о публичности отчёта поджимается, примеры адресов и заголовок уходят. */
@media (max-height: 900px) {
  .hero-grid { padding-top: var(--sp-3); }
  /* Узкая колонка карточки переносит текст сильнее, поэтому поджимаем и содержимое:
     примеры адресов и заголовок — удобство, а не суть, их можно убрать на коротком экране. */
  .console { padding: var(--sp-3) var(--sp-4); }
  .console-title { font-size: var(--fs-body); margin-bottom: 4px; }
  .console-examples { display: none; }
  .console-field { margin-bottom: var(--sp-2); }
  .console-field > label { font-size: 10px; }
  .privacy-note { margin: 4px 0; line-height: 1.4; }
}
/* Поля встают в два столбца только там, где сама карточка стоит в половине страницы
   (hero-grid делится на две колонки от 1000px). На узком экране карточка занимает всю
   ширину, и два столбца сделали бы поля по 180px: текст обрезается, а списки вылезают. */
@media (min-width: 1000px) and (max-height: 900px) {
  .console { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--sp-3); }
  .console > :not(.console-field) { grid-column: 1 / -1; }
}

/* ── Движение компонентов ────────────────────────────────────────────────── */
/* Карточки и строки мягко отзываются на наведение: подсказка, что элемент живой. */
.card:hover, .provider-offering:hover, .depth-card--paper:hover, .sample-card:hover {
  border-color: var(--line-strong);
  box-shadow: 0 2px 10px rgb(20 32 26 / 6%);
}
.records tbody tr { transition: background-color var(--motion-1) var(--ease-out); }
.records tbody tr:hover { background: var(--paper-sunk); }
.console, .console-field input, .console-field select { transition: border-color var(--motion-1) var(--ease-out), background-color var(--motion-1) var(--ease-out); }

/* Раскрытые секции появляются, а не прыгают. */
@keyframes unfold {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: no-preference) {
  .disclosure[open] > .disclosure-body, details[open] > .disclosure-body { animation: unfold var(--motion-2) var(--ease-out) both; }
  .tip-bubble { animation: unfold var(--motion-1) var(--ease-out) both; }
}

/* Загрузка: мягкая пульсация вместо статичной плашки. */
@keyframes pulse-soft {
  0%, 100% { opacity: 1; }
  50% { opacity: .62; }
}
@media (prefers-reduced-motion: no-preference) {
  .state-loading { animation: pulse-soft 1.4s var(--ease-soft) infinite; }
}

/* Тосты и кнопка «наверх» въезжают коротко, без пружин. */
@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: no-preference) {
  .toast:not([hidden]) { animation: toast-in var(--motion-2) var(--ease-out) both; }
  .to-top:not([hidden]) { animation: toast-in var(--motion-2) var(--ease-out) both; }
}
.to-top { transition: opacity var(--motion-1) var(--ease-out), transform var(--motion-1) var(--ease-out), color var(--motion-1) var(--ease-out), border-color var(--motion-1) var(--ease-out); }
.to-top:hover { transform: translateY(-2px); }

/* Переход между страницами: короткое проявление вместо белой вспышки.
   Работает в браузерах с View Transitions, в остальных просто нет. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: fade-out var(--motion-1) var(--ease-out) both; }
::view-transition-new(root) { animation: rise var(--motion-2) var(--ease-out) both; }
@keyframes fade-out { to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* ── Полоса прокрутки ────────────────────────────────────────────────────── */
/* Тонкая, в цвет линий, ржавая при наведении. Chrome/Safari/Edge и Firefox. */
html { scrollbar-color: var(--line-strong) var(--paper-sunk); scrollbar-width: thin; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--paper-sunk); }
::-webkit-scrollbar-thumb { background: var(--line-strong); border: 3px solid var(--paper-sunk); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: var(--rust); }
::-webkit-scrollbar-corner { background: var(--paper-sunk); }

/* ── Кнопка «наверх» ─────────────────────────────────────────────────────── */
/* Появляется на длинных страницах; размер и контраст — как у остальных действий. */
.to-top {
  position: fixed;
  right: var(--sp-6);
  bottom: var(--sp-6);
  z-index: 40;
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  font-size: 20px;
  line-height: 1;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  box-shadow: 0 2px 12px rgb(20 32 26 / 14%);
  cursor: pointer;
}
.to-top[hidden] { display: none; }
.to-top:hover { color: var(--rust-hover); border-color: var(--rust); }
.to-top:focus-visible { outline: 3px solid var(--rust); outline-offset: 2px; }
@media (max-width: 480px) { .to-top { right: var(--sp-4); bottom: var(--sp-4); width: 44px; height: 44px; } }
@media print { .to-top { display: none; } }

/* ── Рейтинг провайдеров: ТОП по широте доказательств ───────────────────── */
/* Блок стоит над таблицей каталога: карточки с баллом и разбором, из чего он
   сложился. Цвета — только токены; акцент один, у первого места. */
.rating { margin: 0 0 var(--sp-8); }
.rating[hidden] { display: none; }
.rating-head { max-width: 68ch; margin-bottom: var(--sp-6); }
.rating-head h2 { margin: var(--sp-2) 0 var(--sp-3); }
.rating-head > p:last-child { margin: 0; color: var(--muted); font-size: var(--fs-lead); line-height: var(--lh-lead); }

.rating-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
@media (min-width: 900px) { .rating-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.rating-card {
  display: grid;
  gap: var(--sp-3);
  align-content: start;
  padding: var(--sp-6);
  background: var(--card);
  border: 1px solid var(--line);
  border-top: 3px solid var(--line-strong);
  border-radius: var(--radius-lg);
}
.rating-card--first { border-top-color: var(--rust); box-shadow: var(--shadow-card); }
.rating-place {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: var(--fs-micro);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
}
.rating-place-number {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.rating-card--first .rating-place-number { color: var(--rust-hover); }
.rating-name { margin: 0; font-family: var(--font-display); font-size: var(--fs-h3); }
.rating-name a { color: var(--ink); }
.rating-status { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.rating-score { margin: var(--sp-2) 0 0; display: flex; align-items: baseline; gap: var(--sp-2); }
.rating-score-value {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.25rem, 1.4rem + 2.4vw, 3rem);
  line-height: 1;
  letter-spacing: -0.02em;
}
.rating-score-max { font-size: var(--fs-caption); color: var(--muted); }
.rating-facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-2);
  font-size: var(--fs-caption);
  line-height: 1.45;
  color: var(--ink-2);
}
.rating-facts li { position: relative; padding-left: var(--sp-4); }
.rating-facts li::before { content: "—"; position: absolute; left: 0; color: var(--line-strong); }
.rating-cert { margin: 0; font-size: var(--fs-caption); color: var(--good); }
.rating-note { margin: 0; font-size: var(--fs-micro); color: var(--muted); }
.rating-note--block { margin-top: var(--sp-5); font-size: var(--fs-caption); }
.rating-open { margin-top: var(--sp-2); font-size: var(--fs-button); font-weight: 600; }
.rating-foot {
  max-width: 92ch;
  margin: var(--sp-6) 0 0;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-size: var(--fs-caption);
  color: var(--muted);
}

/* Колонка «Балл» в таблице каталога: число и пометки не переносятся по строкам. */
.cell-score { white-space: nowrap; }
.cell-score .num { font-family: var(--font-mono); font-weight: 600; }
.cell-score .tag, .cell-score .chip { margin-left: var(--sp-2); }
@media (max-width: 768px) {
  .cell-score { white-space: normal; }
  .cell-score .tag, .cell-score .chip { margin-left: 0; margin-right: var(--sp-2); }
}

/* ── Публичные эндпоинты OMSS, открытые как HTML (lib/omss/pages.mjs) ────── */
/* Публичная часть ключа — PEM: переводы строк значимы, а строки длинные.
   Без pre-wrap ключ схлопнулся бы в одну строку, без anywhere — распёр бы узкую колонку. */
.key-pem {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: var(--fs-micro);
  line-height: 1.5;
  color: var(--ink-2);
}
