/* Леса сайта документации. В кит не входят.

   Правило то же, что у живой спецификации: здесь допустимо только то, что
   принадлежит САЙТУ. Если для показа компонента понадобилось его
   дооформить — значит, в ките дыра, и чинить надо кит.

   Раскладку, навигацию, прозу, поля, кнопки и панель даёт кит. Здесь —
   логотип, поиск, оглавление, сцена примера и подсветка кода. */


/* ── Шапка и логотип ────────────────────────────────────────────────────── */

.site-logo {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  color: var(--text-primary); text-decoration: none;
}
.site-logo:hover { background: var(--surface-hover); }
.site-logo-mark { flex: none; inline-size: 18px; block-size: 18px; color: var(--accent-mark); }
.site-logo-name {
  font-size: var(--text-lg); font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-tight); line-height: 1;
}

/* ── Поиск ──────────────────────────────────────────────────────────────── */

/* Поиск ужимается, но НЕ ДО НУЛЯ. Пока минимум был нулевой, на 390px поле
   сжималось до 18 пикселей: переключатели плотности и темы забирали 411 из
   390 доступных, шапка переполнялась на 83px и заводила документу
   горизонтальную прокрутку.

   Теперь у поля есть пол, а переключатели уехали в поповер и ширину больше
   не отнимают. Перенос строки в шапке при этом снова разрешён — его гасил
   сайт, хотя кит ставит его намеренно и объясняет почему. */
.site-search {
  position: relative;
  flex: 1 1 12rem;
  min-inline-size: 8rem;
  max-inline-size: 20rem;
}

/* Сайту здесь принадлежит только МЕСТО плашки на странице: где она висит и
   докуда растёт. Поверхность — рамка, радиус, фон, тень, внутренний отступ —
   приходит от `inst-popover`.

   Панель для этого не годится: у неё другой радиус и другая поверхность, а
   тени нет вовсе — приписанная ей тень поповера даёт две разные плашки на
   одном экране. */
.site-results {
  position: absolute; inset-inline: 0; inset-block-start: calc(100% + var(--space-3));
  z-index: var(--z-popover);
  max-block-size: 60vh; overflow: auto;
}
.site-results[hidden] { display: none; }

/* Ряд результата — двухстрочный, и своего класса в ките у него нет: пара
   «заголовок + раздел» это содержимое поиска, а не компонент. Метрика взята у
   `inst-menu-item` целиком — радиус, отступ, поверхность наведения, — потому
   что ряд внутри плавающей плашки обязан выглядеть как ряд внутри плавающей
   плашки, где бы он ни стоял.

   Разделительных линий нет: у меню их нет, а линия между пунктами превращает
   короткий список в таблицу. */
.site-result {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: inherit; text-decoration: none;
}
.site-result:hover, .site-result[aria-selected="true"] { background: var(--surface-hover); }
.site-result-title { font-size: var(--text-sm); font-weight: var(--weight-medium); }
.site-result-group { font-size: var(--text-2xs); color: var(--text-muted); }
.site-result-empty {
  padding: var(--space-2) var(--space-3);
  color: var(--text-muted); font-size: var(--text-sm);
}

/* Тема и плотность живут в поповере, а не в ряду шапки.

   Причина не в экономии места на телефоне, хотя и в ней тоже. Голыми
   контролами переключатель плотности безымянен: одна из двух уникальных идей
   кита выглядела бы как три кнопки без подписи. Кнопка «Вид» даёт им имя. */
.site-view-body { display: flex; flex-direction: column; gap: var(--space-5); padding: var(--space-3); }
.site-view-row { display: flex; flex-direction: column; gap: var(--space-3); }
.site-theme { inline-size: 100%; }

/* Переключатель языка — ссылки внутри сегментированного контрола: смена
   языка это переход, а не состояние, и средний клик обязан работать. */
.site-lang {
  display: inline-flex; align-items: center; justify-content: center;
  min-block-size: calc(var(--control-h-md) - var(--space-2));
  padding-inline: var(--control-pad-md);
  border-radius: var(--radius-sm);
  color: var(--text-secondary); font-size: var(--text-sm); text-decoration: none;
}
.site-lang:hover { color: var(--text-primary); }
.site-lang[aria-checked="true"] {
  background: var(--surface-raised); color: var(--text-primary);
  font-weight: var(--weight-medium);
  box-shadow: 0 0 0 var(--hairline) var(--border);
}

/* ── Раскладка страницы ─────────────────────────────────────────────────── */

.site-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 14rem;
  gap: var(--space-9);
  max-inline-size: var(--container-max);
  margin-inline: auto;
  padding: var(--space-7) var(--space-8) var(--space-10);
}
.site-layout--splash { grid-template-columns: minmax(0, 1fr); }

/* Проза справочника — --text-sm с прозаическим интерлиньяжем, ровно как
   пояснения в живой спецификации.

   Не --text-md, который .inst-prose ставит по умолчанию: 15px это тело
   ответа агента внутри панели, где абзац короткий и стоит среди данных.
   Здесь абзацев подряд десятки, и на такой длине 15/1.65 читается крупно
   и рыхло — кит про плотность, и справочник не имеет права быть рыхлее
   того, что описывает.

   Побочно чинится лестница: между h3 (17) и прозой (13) появляется
   настоящий шаг, которого при 15px не было. */
.site-body {
  max-inline-size: none;
  font-size: var(--text-sm);
  line-height: var(--leading-prose);
}

/* Вертикальный ритм внутри раздела.
   `.inst-prose` расставляет его прямым потомкам, а между ней и абзацем стоит
   <section>: до этого правила абзацы шли встык, без единого просвета. */
.site-body :is(.doc-hero, .doc-s) > * + * { margin-block-start: var(--space-5); }
/* 68ch — мера читаемости, и она нужна только тексту. Живой пример и
   таблица справочника меряются содержимым и выходят на всю колонку.
   Считается от прямого родителя-раздела, а не от тела: с появлением
   <section> проза перестала быть прямым потомком .site-body, и мера
   молча отвалилась бы на всех страницах разом. */
.site-body :is(.doc-hero, .doc-s) > :is(p, ul, ol, blockquote, h3, h4) {
  max-inline-size: 68ch;
}

/* ── Опознание страницы ─────────────────────────────────────────────────── */

/* Первый экран отвечает на четыре вопроса, и все четыре — до прокрутки:
   что это (раздел и имя), можно ли этому верить (зрелость), где это лежит
   (исходник), как это выглядит (главный пример).

   Зрелость и исходник — не украшение: без первого непонятно, можно ли верить
   написанному ниже, без второго — где это лежит. */
.doc-id { margin-block-end: var(--space-6); }

/* Подпись раздела — китовая идиома тихой метки: --text-2xs, --text-muted,
   --leading-ui. Ровно та же, что у .inst-nav-label, где эта работа уже
   делается.

   Капса с трекингом здесь нет: третий принцип конституции называет его
   дословно — «заголовок капсом с трекингом кричит громче числа, которое он
   подписывает». Во всём ките text-transform не встречается ни разу, и сайту
   заводить его нечем оправдать. */
.doc-id-group {
  margin: 0 0 var(--space-2);
  font-size: var(--text-2xs); color: var(--text-muted);
  line-height: var(--leading-ui);
}

.doc-id-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4);
  margin-block-start: var(--space-4);
  font-size: var(--text-xs);
}
.doc-id-source { color: var(--text-muted); }

/* Бейдж JS — ссылка на раздел, а не отметка.
   Читатель, увидевший его в шапке, идёт за одним: что вызвать. Поэтому у
   бейджа есть адрес, а объяснение стоит рядом текстом, а не прячется в
   `title`: подсказку не видно с тачскрина и не слышно скринридеру. */
.site-js { text-decoration: none; }
.site-js:hover { border-color: var(--border-strong); }
.doc-id-note { color: var(--text-muted); }

/* ── Шапка страницы: определение и главный пример ───────────────────────── */

/* Первый абзац — определение компонента, а не первый абзац прозы. Он крупнее
   тела и стоит в один-два ряда: тот, кто пришёл со страницы другого кита,
   должен за секунду понять, на что смотрит, и только потом начать читать. */
/* Мера остаётся 68ch — та же, что у всей прозы и у .inst-page-desc в ките.
   Своей меры здесь нет: две меры читаемости на одну страницу — это параметр
   в двух экземплярах. */
/* Ведущий абзац отличается тоном, а не кеглем: кегль у всей прозы теперь
   один, и лишняя ступень тут была бы украшением. */
.doc-hero > p:first-of-type {
  margin-block-start: 0;
  color: var(--text-secondary);
}

/* Главный пример — вход в компонент, а не иллюстрация к абзацу. Сцена выше
   обычной и стоит вплотную к определению: между ними нет ни заголовка, ни
   пояснения, потому что показывать надо сразу. */
.demo--hero { margin-block: var(--space-6) 0; }
.demo--hero .demo-root { padding-block: var(--space-8); }

/* ── Разделы ────────────────────────────────────────────────────────────── */

/* Раздел — отсек, а не абзац с подзаголовком.

   Отличает его воздух, а не линейка: четырнадцать волосков на странице
   читаются решёткой и спорят с содержимым, ради которого страница написана.
   Тот же довод, по которому у кита нет разделительных линий в меню и в
   боковой колонке. */
.doc-s { scroll-margin-block-start: var(--space-6); }
/* Тот же воздух и перед первым разделом: он идёт за главным примером, и
   шов между шапкой и содержанием ничем не отличается от шва между
   разделами. */
:is(.doc-hero, .doc-s) + .doc-s { margin-block-start: var(--space-10); }

.doc-s-title {
  margin: 0 0 var(--space-5);
  font-size: var(--text-xl);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  max-inline-size: none;
}
.doc-s > :first-child + * { margin-block-start: 0; }

/* «Связанное» — не абзац со ссылками через точку, а ряд переходов. Пока это
   был поток текста, пять ссылок подряд читались как одно предложение, и
   выбрать из них было нельзя. */
.doc-s[data-section="related"] p {
  display: flex; flex-wrap: wrap; gap: var(--space-3);
  max-inline-size: none;
}
.doc-s[data-section="related"] a {
  display: inline-flex; align-items: center;
  min-block-size: var(--control-h-sm);
  padding-inline: var(--control-pad-sm);
  border: var(--hairline) solid var(--border-control);
  border-radius: var(--radius-md);
  color: var(--text-secondary); text-decoration: none;
  font-size: var(--text-sm);
}
.doc-s[data-section="related"] a:hover {
  background: var(--surface-hover); color: var(--text-primary);
}
/* Разделители «·» между ссылками в разметке больше не нужны — их работу
   делает промежуток. Прячутся, а не вычищаются из семидесяти страниц. */
.doc-s[data-section="related"] p { font-size: 0; }
.doc-s[data-section="related"] a { font-size: var(--text-sm); }

/* ── Правила: так и не так ──────────────────────────────────────────────── */

/* Правило дизайн-системы — данные, а не проза: у него есть знак и его читают
   сравнением. Обычным Markdown это выразить нечем — «**Не используйте**
   кнопку для навигации» ничем не отличается от соседнего абзаца. */
/* Ровно две колонки, а не auto-fit.
   Пары «так / не так» идут в разметке подряд, и на трёх колонках ряд поехал бы
   так: do · dont · do / dont · do · dont — то есть сравнение, ради которого
   правила и стоят рядом, сломалось бы именно на широком экране. */
.rule-row {
  display: grid; gap: var(--space-5);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-block: var(--space-6);
}
/* Порог — 60rem, тот же, на котором боковая колонка становится ящиком.
   Своего порога здесь нет: третий breakpoint, отличающийся от существующих
   на 32 пикселя, — дубликат, а дубликат это будущее расхождение. */
@media (width < 60rem) {
  .rule-row { grid-template-columns: minmax(0, 1fr); }
}

/* Сайту здесь принадлежит место на странице, а не вид: поверхность, значок
   тона, метрика и цвет приходят от `.inst-note`. Своё — только то, чего у
   сноски нет: она рассчитана на строку в потоке, а пара правил стоит в
   колонке и должна тянуться до её низа. */
.rule {
  align-items: stretch;
  padding-block: var(--space-4);
}
.rule > * { max-inline-size: none; }

/* Знак несёт СЛОВО, а не только цвет: закон кита распространяется и на
   документацию о ките. Значок сноски уже сказал то же самое картинкой —
   слово повторяет это для тех, кто картинку не видит. */
.rule-tag {
  margin: 0;
  font-size: var(--text-2xs); font-weight: var(--weight-medium);
  line-height: var(--leading-ui);
  color: var(--tone-ink);
}
.rule-head {
  display: block;
  margin-block-start: var(--space-2);
  color: var(--text-primary); font-weight: var(--weight-normal);
  font-size: var(--text-sm);
}

/* Тело заметки кита. inst-note — флексбокс со значком в первой позиции, и без
   собственного потока абзацы вставали бы в строку рядом со значком. */
.note-body { min-inline-size: 0; }
.note-body > * { max-inline-size: none; margin-block: 0; }
.note-body > * + * { margin-block-start: var(--space-4); }
.site-body .inst-note { margin-block: var(--space-6); }

/* Разделы боковой колонки разделены воздухом, а не линиями: одиннадцать
   линеек в одной колонке читаются как решётка и спорят с содержимым. */
.inst-shell-aside .inst-nav-group + .inst-nav-group { margin-block-start: var(--space-6); }

.site-source {
  margin-block-start: var(--space-9);
  padding-block-start: var(--space-5);
  border-block-start: var(--hairline) solid var(--border-subtle);
  font-size: var(--text-sm); color: var(--text-muted);
}

/* ── Оглавление ─────────────────────────────────────────────────────────── */

.site-toc {
  position: sticky; inset-block-start: var(--space-7);
  align-self: start; display: flex; flex-direction: column; gap: var(--space-1);
  max-block-size: calc(100dvh - var(--space-10)); overflow: auto;
  font-size: var(--text-sm);
}
.site-toc-item {
  padding: var(--space-2) var(--space-4);
  border-inline-start: var(--size-marker) solid transparent;
  color: var(--text-secondary); text-decoration: none;
}
/* Вложенность показывает отступ, а не второй кегль: два размера в одном
   списке из семнадцати строк читаются как две разные вещи. */
.site-toc-item[data-level="3"] { padding-inline-start: var(--space-7); color: var(--text-muted); }
.site-toc-item:hover { color: var(--text-primary); }
.site-toc-item[aria-current="true"] {
  border-inline-start-color: var(--accent-mark); color: var(--text-primary);
}

/* ── Живой пример ───────────────────────────────────────────────────────── */

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

.demo {
  margin: var(--space-6) 0;
  border: var(--hairline) solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-raised);
}

.demo-bar {
  display: flex; align-items: center; gap: var(--space-2);
  padding-inline: var(--space-5);
  min-block-size: var(--control-h-lg);
  border-block-end: var(--hairline) solid var(--border-subtle);
  background: var(--surface-sunken);
  font-size: var(--text-xs); color: var(--text-muted);
}

/* Три точки — единственная вольность на весь сайт. Они не имитируют
   систему, а сообщают «это окно, а не абзац», и делают это быстрее любой
   подписи. */
.demo-chrome {
  flex: none; inline-size: 34px; block-size: var(--size-dot);
  background:
    radial-gradient(circle 3px at 3px 50%, var(--border-strong) 99%, transparent) 0 0/14px 100% no-repeat,
    radial-gradient(circle 3px at 3px 50%, var(--border-strong) 99%, transparent) 11px 0/14px 100% no-repeat,
    radial-gradient(circle 3px at 3px 50%, var(--border-strong) 99%, transparent) 22px 0/14px 100% no-repeat;
}

.demo-label { flex: 1 1 auto; }

/* ── Сцена ────────────────────────────────────────────────────────────────

   Пример живёт в потоке страницы и наследует тему справочника: `.inst-theme`
   берёт цвет и фон из токенов, а тема кита работает на любом поддереве.
   Своего переключателя у примера нет — ручка одна, в шапке.

   Сцена ведёт себя как `.inst-cluster` — китовый примитив ряда, а не как
   собственная выдумка. Выравнивание по ЦЕНТРУ: в ряду из элементов разной
   высоты — аватары трёх размеров, кнопка рядом с полем — верхняя кромка
   выстраивает их лесенкой, и ряд перестаёт читаться рядом. */

.demo-stage { display: block; }

.demo-root {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-7);
}

/* Блочное занимает всю ширину сцены, а не жмётся в ряд. */
.demo-root > :is(.inst-panel, .inst-card, .inst-table, .inst-form, .inst-log,
                 .inst-diff, .inst-approval, .inst-failure, .inst-calendar,
                 .inst-timeline, .inst-lanes, .inst-budget, .inst-tree,
                 .inst-empty, .inst-banner, .inst-note, .inst-metric-row,
                 .inst-stack, .inst-field, .inst-props, .inst-kv, .inst-shell,
                 .inst-stepper, .inst-section, .inst-page-header, .inst-split,
                 .inst-grid, .inst-container, .inst-accordion, .inst-toasts,
                 .inst-fieldset, .inst-crumbs, .inst-pager, .inst-toolbar,
                 .inst-theme,
                 [role="listbox"], [role="grid"], [role="tree"], [role="log"],
                 [role="group"], [role="tablist"]) {
  flex: 1 1 100%;
}

/* Сегментированный контрол — контрол, и ширину берёт по содержимому.
   Роли `radiogroup` в списке выше нет намеренно: её носит именно он, а
   `.inst-segmented` объявлен `inline-flex`. Растянутый на всю сцену, он
   показывает утопленную дорожку во всю сцену и три кнопки в её углу. */

/* Оболочка приложения занимает сцену целиком — она и есть экран, и высоту
   берёт `100dvh`. В потоке страницы это означает пример во весь экран, поэтому
   сцена задаёт ей свой потолок. Поле снимается ТОЛЬКО ради оболочки: без
   :has() правило било бы по всем примерам подряд, и ряд метрик прилипал к
   краям. */
.demo-root:has(> .inst-shell) { padding: 0; gap: 0; }
.demo-root > .inst-shell { block-size: 30rem; border: 0; border-radius: 0; }

/* Календарь — сетка на семь колонок без собственной ширины: растянутый на
   всю сцену месяц читается лентой, а не месяцем. */
.demo-root > .inst-calendar { flex: 0 1 24rem; }

/* Мера, слайдер и спарклайн меряют горизонталь: без явной основы флекс
   сжимает их в ноль, и сцена выглядит пустой. */
.demo-root > :is(.inst-meter, .inst-slider, .inst-sparkline, .inst-meter-row) {
  flex: 1 1 100%;
}

/* Тултип раскрывается ВВЕРХ и позиционирован абсолютно: без запаса сверху он
   уходит под полосу сцены. Отрицательную координату подгонкой высоты не
   вылечить. */
.demo-root:has(.inst-tooltip) { padding-block-start: 4.5rem; }

/* ── Показ материала ──────────────────────────────────────────────────────

   Рампа, образец поверхности и строка шкалы — НЕ компоненты кита, и классов
   в ките у них не будет: это не части интерфейса, а способ посмотреть на сам
   материал.

   Цвет и размер приходят инлайном через --c и --v. Это канал ДАННЫХ, а не
   оформления: показываемое значение и есть содержание примера — тот же
   случай, что ширина заливки меры. */

.ramp { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 2px; inline-size: 100%; }
.ramp-step {
  block-size: 34px; border-radius: var(--radius-xs); background: var(--c);
  box-shadow: inset 0 0 0 var(--hairline) var(--border-subtle);
}
.ramp-scale { margin-block-start: var(--space-2); }
.ramp-scale > span {
  font-family: var(--font-mono); font-size: var(--text-2xs);
  color: var(--text-muted); text-align: center;
}

.swatches {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--space-4); inline-size: 100%;
}
.sw { border: var(--hairline) solid var(--border); border-radius: var(--radius-md); overflow: hidden; }
.sw-chip { block-size: 42px; background: var(--c); }
.sw-cap {
  padding: var(--space-3) var(--space-4); font-size: var(--text-2xs);
  color: var(--text-muted); font-family: var(--font-mono);
}

.scale-row {
  display: flex; align-items: baseline; gap: var(--space-6);
  padding-block: var(--space-3); inline-size: 100%;
  border-block-end: var(--hairline) solid var(--border-subtle);
}
.scale-cap {
  flex: none; inline-size: 5rem; font-family: var(--font-mono);
  font-size: var(--text-2xs); color: var(--text-muted);
}
.scale-sample { font-size: var(--v); }

/* ── Разметка примера: свёрнута ─────────────────────────────────────────── */

/* Ручка прижата к столу примера снизу и выглядит его частью, а не отдельным
   блоком: это продолжение примера, а не новый раздел. */
.demo-code { border-block-start: var(--hairline) solid var(--border-subtle); }

.demo-code-head {
  display: flex; align-items: center; gap: var(--space-3);
  min-block-size: var(--control-h-md);
  padding-inline: var(--space-5);
  background: var(--surface-sunken);
  color: var(--text-muted); font-size: var(--text-xs);
  cursor: pointer; list-style: none;
}
.demo-code-head::-webkit-details-marker { display: none; }
.demo-code-head:hover { color: var(--text-primary); }

.demo-code-head::before {
  content: ""; flex: none;
  inline-size: var(--size-chevron); block-size: var(--size-chevron);
  background: currentColor;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M4.75 3 7.75 6 4.75 9' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: rotate var(--dur-1) var(--ease-out);
}
.demo-code[open] > .demo-code-head::before { rotate: 90deg; }

/* ── Справочник ─────────────────────────────────────────────────────────── */

/* Одна таблица с постоянными колонками вместо шести с разными. Ширины
   заданы явно: имя и вид не должны прыгать от страницы к странице, иначе
   постоянство колонок теряется ровно там, ради чего затевалось. */
.api { overflow-x: auto; margin-block: var(--space-6); }

.api-table {
  inline-size: 100%; border-collapse: collapse;
  font-size: var(--text-sm); line-height: var(--leading-ui);
}
.api-table th {
  text-align: start; font-weight: var(--weight-normal); color: var(--text-muted);
  padding: var(--space-3) var(--pad-cell-x);
  border-block-end: var(--hairline) solid var(--border);
  white-space: nowrap;
}
.api-table td {
  padding: var(--row-pad-y) var(--pad-cell-x);
  border-block-end: var(--hairline) solid var(--border-subtle);
  vertical-align: baseline;
}
.api-table tbody tr:hover td { background: var(--surface-hover); }
.api-table { min-inline-size: 34rem; }
.api-table th:nth-child(1), .api-table td:nth-child(1) { inline-size: 1%; white-space: nowrap; }
/* Колонка «Что делает» держит свою ширину, а не отдаёт её значению: за
   справочником приходят читать именно её. */
.api-table th:nth-child(3), .api-table td:nth-child(3) { min-inline-size: 18rem; }

/* Значение не переносится, пока короткое, и переносится, когда длинное:
   у --font-mono оно в девяносто знаков, и nowrap распирал им таблицу так,
   что колонка «Что делает» уезжала за край. */
.api-table th:nth-child(2), .api-table td:nth-child(2) { inline-size: 1%; }
.api-table td:nth-child(2) > code {
  display: inline-block;
  max-inline-size: 22rem;
  overflow-wrap: anywhere;
}

.api-name { color: var(--text-primary); }
/* Прочерк «значения нет» — это ТЕКСТ, а не украшение, поэтому muted, а не
   faint: у faint порог 3:1, он для линий и разделителей. Поймано проверкой по
   отрисованным пикселям — текстовый гейт сюда не смотрит, docs.css в него не
   входит. Было 3,63:1 при норме 4,5. */
.api-none { color: var(--text-muted); }

/* Кнопка копирования в строке справочника.

   Стоит ПЕРЕД значением, а не после: имена в колонке выровнены по левому
   краю, и кнопка после них плясала бы по горизонтали вслед за длиной имени.

   Видна по наведению на строку и по фокусу — но не спрятана от тачскрина:
   ниже 60rem она видна всегда, потому что наведения там нет. */
/* Кнопка и значение — одна строка, и рвать её нельзя: перенос оставляет
   значок копирования висеть отдельно от того, что он копирует. Длинному
   значению разрешено переноситься внутри самого `<code>` — там разрыв
   безобиден, а ячейке от него не тесно. */
.api-cell { white-space: nowrap; }
/* Длинному значению перенос внутри `<code>` возвращается: у --font-mono оно
   бывает в девяносто знаков, и nowrap распирал бы им таблицу. Разрыв внутри
   значения безобиден — в отличие от разрыва между значком и значением. */
.api-cell > code { white-space: normal; overflow-wrap: anywhere; }
.api-copy {
  margin-inline-end: var(--space-2);
  vertical-align: baseline;
  color: var(--text-faint);
  opacity: 0; transition: opacity var(--dur-1) var(--ease-out);
}
.api-table tbody tr:hover .api-copy,
.api-copy:focus-visible { opacity: 1; }
.api-copy:hover { color: var(--text-primary); }
/* Ответ на нажатие. Атрибут ставит кит; цвет объявлен ЗДЕСЬ, потому что цвет
   покоя объявлен здесь же: стили сайта лежат вне слоёв и выигрывают у кита по
   его собственному правилу. Кит красит `[data-copied]` для приложения,
   которое `.inst-copy` не трогает, — этот случай не наш.

   Видимость держится тем же атрибутом: кнопка проявляется по наведению
   строки, а курсор к моменту ответа нередко уже ушёл. */
.api-copy[data-copied] { opacity: 1; }
.api-copy[data-copied="true"] { color: var(--ok-text); }
.api-copy[data-copied="false"] { color: var(--err-text); }

@media (width < 60rem) {
  .api-copy { opacity: 1; }
}

/* Строка-заголовок вида. Утопленная поверхность, а не жирное начертание:
   она делит список, но не спорит с именами, которые здесь главные.
   Первой группе верхняя линия не нужна — над ней уже шапка таблицы. */
.api-group > th {
  padding: var(--space-4) var(--pad-cell-x) var(--space-2);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-weight: var(--weight-medium);
  font-size: var(--text-xs);
  border-block: var(--hairline) solid var(--border-subtle);
}
.api-table tbody tr.api-group:first-child > th { border-block-start: none; }

/* ── Код ────────────────────────────────────────────────────────────────── */

.code-block { position: relative; }
.code-block pre {
  margin: 0; overflow: auto; scrollbar-gutter: stable;
  padding: var(--space-5) var(--pad-panel);
  background: var(--surface-sunken);
  border-radius: var(--radius-md);
  font-size: var(--text-xs); line-height: 1.6;
}
.code-block--demo pre { border-radius: 0; border-block-start: var(--hairline) solid var(--border-subtle); }
.code-block code { font-size: inherit; }

/* Кнопка копирования ВИДНА ВСЕГДА, просто тихая.

   Она была прозрачной до наведения — то есть не существовала для тачскрина и
   для того, кто не знает, что она там есть. Наведение может усиливать
   элемент, но не вводить его в бытие.

   Иконочная, а не со словом: подпись «копировать» на узком экране наезжала на
   первую строку кода. */
.code-copy {
  position: absolute;
  inset-block-start: var(--space-3); inset-inline-end: var(--space-3);
  color: var(--text-muted);
  opacity: 0.6; transition: opacity var(--dur-1) var(--ease-out);
}
.code-block:hover .code-copy,
.code-copy:hover,
.code-copy:focus-visible { opacity: 1; }
.code-copy[data-copied] { opacity: 1; }
.code-copy[data-copied="true"] { color: var(--ok-text); }
.code-copy[data-copied="false"] { color: var(--err-text); }

/* Два значка в разметке, переключение — здесь. Подменить href у <use>
   стилями нельзя, а менять его скриптом значило бы вернуть сайту
   обработчик, который только что стал поведением кита. */
.copy-i-done { display: none; }
.inst-copy[data-copied="true"] .copy-i { display: none; }
.inst-copy[data-copied="true"] .copy-i-done { display: block; }

/* Место под кнопку в блоке кода: без него длинная первая строка уходит под
   неё. Полоса прокрутки у <pre> своя, поэтому отступ ставится содержимому. */
.code-block pre { padding-inline-end: calc(var(--control-h-sm) + var(--space-5)); }

/* Подсветка на три цвета из палитры кита. Шестьдесят цветов на макете из
   хайрлайнов кричали бы громче кода, который подсвечивают. */
.t-tag  { color: var(--accent-text); font-weight: var(--weight-normal); }
.t-attr { color: var(--ok-text);     font-weight: var(--weight-normal); }
.t-val  { color: var(--text-primary); font-weight: var(--weight-normal); }
.t-com  { color: var(--text-faint);  font-style: normal; }

/* ── Таблицы в прозе ────────────────────────────────────────────────────── */

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

   Первая: таблица распирала ДОКУМЕНТ. Четыре колонки с предложением в каждой
   не помещаются в колонку прозы никак, и горизонтальная прокрутка доставалась
   всей странице — вместе с шапкой, оглавлением и навигацией. Теперь скролл
   свой у каждой таблицы (.table-wrap), а страница остаётся на месте.

   Вторая: `white-space: nowrap` у шапки. С ним колонка резервирует ширину по
   самому длинному заголовку, и содержимому остаётся то, что уцелело.

   Третья: имена классов. `inst-dialog-foot--end` — двадцать один знак без
   пробела; браузер рвал его посреди слова или распирал колонку. Теперь имя не
   рвётся, а на узком экране таблица уезжает в свой скролл. */
.table-wrap {
  overflow-x: auto;
  scrollbar-gutter: stable;
  margin-block: var(--space-6);
}

.site-body table {
  inline-size: 100%; border-collapse: collapse;
  /* Минимум — точка, с которой таблица уходит в скролл вместо того, чтобы
     сжимать колонки до одного слова в строке. */
  min-inline-size: 32rem;
  font-size: var(--text-sm); line-height: var(--leading-ui);
}
.site-body th {
  text-align: start; font-weight: var(--weight-normal); color: var(--text-muted);
  padding: var(--space-3) var(--pad-cell-x);
  border-block-end: var(--hairline) solid var(--border);
}
.site-body td {
  padding: var(--row-pad-y) var(--pad-cell-x);
  border-block-end: var(--hairline) solid var(--border-subtle);
  vertical-align: baseline;
  overflow-wrap: break-word;
}
/* Имя класса или токена не рвётся посреди слова: разорванный
   `inst-dialog-foot--end` перестаёт быть именем, которое можно скопировать. */
.site-body :is(td, th) > code { white-space: nowrap; }

/* Шапка из пустых ячеек прячется целиком.

   Таблицы «Доступность» и «Свойства» пишутся как `| | |` — у них нет
   заголовков колонок, потому что колонки здесь это «что» и «как», и называть
   их незачем. Пустая полоса над ними выглядела ошибкой вёрстки. */
.site-body thead:not(:has(th:not(:empty))) { display: none; }

/* Цитата — тихая врезка, а не второе предупреждение: жёлтая заливка тут
   означала бы тон, а тон в ките носит сноска. Метрика взята у неё же. */
.site-body blockquote {
  margin-block: var(--space-6);
  padding: var(--space-3) var(--pad-panel);
  border-inline-start: var(--size-marker) solid var(--border-strong);
  color: var(--text-secondary);
  font-size: var(--text-sm); line-height: var(--leading-ui);
}
.site-body blockquote > * + * { margin-block-start: var(--space-4); }

/* ── Лестница заголовков ───────────────────────────────────────────────────

   Кит даёт заголовку экрана --text-xl и объявляет --text-2xl «только для
   чисел-героев». Для инструмента это верно: главное на экране — данные, и
   заголовок не имеет права кричать громче числа, которое подписывает.

   Справочник — единственная поверхность, где данных нет. Здесь герой это
   сам текст, поэтому название страницы берёт --text-2xl. Иначе оно
   совпадает с --text-xl у h2, и на странице с десятью разделами название
   не отличается от них ничем — что и происходило.

   Шкала остаётся китовой, ни одной новой ступени не заведено:
   27 · 21 · 17 · 15. */

.site-body .inst-page-title {
  font-size: var(--text-2xl);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.site-body :is(h2, h3, h4) { scroll-margin-block-start: var(--space-6); }

/* Шаг h3 → проза всего 2px, и разницы в кегле не хватает. Подраздел
   отделяется воздухом сверху: расстояние читается быстрее двух пикселей. */
.site-body h3 { margin-block-start: var(--space-7); }
.site-body h3 + * { margin-block-start: var(--space-4); }

/* ── Узкий экран ────────────────────────────────────────────────────────── */

/* Оглавление уходит первым и рано: до 78rem оно съедает 272px из рабочей
   области, и колонка прозы становится у́же собственной меры читаемости.
   Навигация по странице ценна, но не ценой самой страницы. */
@media (width < 78rem) {
  .site-layout { grid-template-columns: minmax(0, 1fr); }
  .site-toc { display: none; }
}

/* Ниже 60rem колонка становится выезжающим ящиком — это делает САМ КИТ по
   классу inst-shell-aside--drawer. Здесь не осталось ни одного правила про
   неё, и это правильный признак: два механизма на одну работу расходятся
   всегда. */
@media (width < 60rem) {
  .site-layout { padding-inline: var(--space-6); }
}

/* ── Галерея иконок ───────────────────────────────────────────────────────
   Список печатается из спрайта, поэтому растёт вместе с китом. Сетка
   интринсик: ячеек столько, сколько поместится. */
.icon-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: var(--space-3);
  margin-block: var(--space-5);
  max-inline-size: none;
}
.icon-cell {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  font-size: var(--text-xs);
}
.icon-note { color: var(--text-muted); }

/* Марка GitHub.

   Не `.inst-icon`: тот ставит `fill: none; stroke: currentColor` — язык
   штриховых значков кита, и залитая форма под ним пропадает целиком. Свои
   presentation-атрибуты на <svg> классу проигрывают, поэтому размер и
   заливка объявлены здесь.

   Цвет — currentColor: марка живёт внутри кнопки и обязана гаснуть и
   загораться вместе с ней. */
.site-github {
  inline-size: var(--size-icon);
  block-size: var(--size-icon);
  fill: currentColor;
  stroke: none;
}

/* Умолчание справочника — чистый серый.

   Кит по умолчанию тёплый (`--hue-neutral: 75`, `--tint: 1`), и это его
   решение, а не сайта: у приложения на ките оттенок нейтрали — часть его
   собственного характера. Справочник же показывает компоненты, а не себя,
   и любой уклон нейтрали читается как свойство ПОКАЗЫВАЕМОГО.

   Селектор с `:not([data-theme])` обязателен. Голый `:root` перебил бы и
   выбранную в переключателе тему: `--tint` она не переопределяет, поэтому
   «светлая тёплая» осталась бы серой, и переключатель начал бы врать. Так
   уклон снимается только там, где темы не выбирали, а системная светлая и
   тёмная продолжают работать как работали. */
:root:not([data-theme]) { --tint: 0; }
