@import "./tokens.css";
/* GoodWink — стили кабинета.
   Источник правды: cabinet/web/static/styles.css — его отдаёт кабинет.
   Копия для Claude Design: design-system/src/styles.css
   (`npm run sync-css` в design-system/, расхождение ловит `npm test`).
   Оттуда её берёт /design-sync как cssEntry — поэтому макеты в Claude Design
   выглядят ровно как живой кабинет.
   Обновлено из Claude Design 24.07.2026 (рефреш: плотность, две темы,
   таблица данных — липкая шапка, закреплённый первый столбец, сортировка,
   фильтр по столбцу). Накат пришёл без импорта токенов — первая строка файла
   добавлена при применении, без неё все var() пустые.
   NB: не писать в комментариях строку импорта целиком (со скобками и путём):
   валидатор /design-sync ищет импорты регуляркой по всему файлу, комментарии не
   вырезает, и упоминание в тексте валит синк как [CSS_IMPORT_MISSING].
   Освежено в Claude Design 20.10.2026 (пакет cabinet-refresh, причины правок —
   его why.md): одна высота у всех контролов (--ctl-h), действия экрана у
   правого края, каталог и корзина без лишних рамок и переносов, единый маркер
   сводок, подчёркнутые ссылки в тексте, отмеченная строка таблицы видна, цвет,
   тень и радиус — только из токенов, контраст текста не ниже 4.5:1 в обеих
   темах и трёх акцентах, на телефоне — контролы 40px и вкладки шапки крупнее.
   Разметка и имена классов не менялись. */
*{box-sizing:border-box}
/* Нативные части контролов — в цвет темы. Без color-scheme в тёмной теме
   флажки строк были белыми квадратами, а раскрытый список select и полосы
   прокрутки — светлыми; без accent-color флажок «Текст сравнивать без учёта
   регистра» и выбор строк таблицы красились браузерным синим мимо акцента */
:root{color-scheme:dark;accent-color:var(--accent)}
[data-theme="light"]{color-scheme:light}
/* `hidden` должен побеждать любой display из класса: UA-правило [hidden] слабее
   селектора по классу, и кнопка `.iconbtn` (display:inline-flex) оставалась
   видимой, хотя скрипт её прятал — в карточке записи так висело «удалить
   событие» от прошлого открытого события. */
[hidden]{display:none!important}
body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 var(--font);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
::selection{background:var(--accent-soft-2)}
a{color:var(--accent);text-decoration:none}
a:hover{color:var(--accent-2);text-decoration:underline;text-underline-offset:2px}
/* Фокус с клавиатуры — то же кольцо, что у кнопок и полей: у ссылок и
   сводок <details> оставалась браузерная обводка мимо обеих тем */
a:focus-visible,summary:focus-visible{outline:none;box-shadow:var(--ring)}
/* Ссылка внутри абзаца и плашки подчёркнута всегда: её отличал только цвет,
   а бирюза рядом с серым --text-2 почти той же яркости (WCAG 1.4.1). Кнопки,
   вкладки, ссылки «Помощи» и имена каталога — без черты: они и так отдельные
   элементы; ссылка-код (имя таблицы в .sub) — тоже, её выделяет плашка кода */
:is(p,.msg) a:not(.btn):not(:has(>code)){text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);text-underline-offset:3px}
:is(p,.msg) a:not(.btn):hover{text-decoration-color:currentColor}

/* ——— шапка ——— */
/* Три якорные зоны: лого | вкладки | тема+имя+выход. Высота — из --bar-h,
   а не из суммы паддингов: «почти одинаковые» высоты контролов в ряду читаются
   как элементы из разных мест. Ширину бара держит общее правило `.bar,main`
   в «каркасе страницы» ниже — иначе шапка и содержимое разъезжаются.
   Вкладки — `header nav`, а не голый `nav`: с Э7 у «Помощи» свои <nav
   class="toc">, и правила шапки доставались им — на телефоне каждая группа
   ссылок становилась коробкой высотой 40px со своей прокруткой. */
header{position:sticky;top:0;z-index:20;background:color-mix(in srgb,var(--surface) 88%,transparent);backdrop-filter:blur(10px);border-bottom:1px solid var(--border)}
.bar{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:20px;height:var(--bar-h)}
.logo{display:inline-flex;align-items:center;gap:9px;font-family:var(--mono);font-weight:600;font-size:1.02rem;letter-spacing:-.01em;color:var(--text)}
/* ореол квадрата — обводкой, а не тенью с литеральной геометрией */
.logo::before{content:"";width:11px;height:11px;border-radius:calc(var(--r-sm) / 2);background:var(--accent);outline:3px solid var(--accent-soft)}
.logo:hover{text-decoration:none;color:var(--text)}
header nav{height:100%;display:flex;gap:2px;min-width:0;overflow-x:auto}
header nav a{position:relative;display:inline-flex;align-items:center;height:100%;padding:0 12px;white-space:nowrap;color:var(--text-2);font-weight:500;font-size:.9rem;transition:color .12s,background .12s}
header nav a:hover{color:var(--text);background:var(--surface-2);text-decoration:none}
header nav a.on{color:var(--text)}
/* подчёркивание активной вкладки прибито к границе бара, а не отсчитано
   от текста (bottom:-12px ломался от любой правки кегля или паддинга) */
header nav a.on::after{content:"";position:absolute;left:12px;right:12px;bottom:0;height:2px;background:var(--accent)}
.bar-end{display:flex;align-items:center;gap:10px;justify-self:end}
/* тумблер темы — самый тихий контрол шапки: рамка появляется под мышью, а
   не спорит с вкладками и именем кабинета */
.bar-end>.iconbtn{width:var(--ctl-h);height:var(--ctl-h);border-color:transparent}
.sp{margin-left:auto}
.bar-end>a{color:var(--text-2);font-size:.86rem}
.bar-end>a:hover{color:var(--text)}
/* имя кабинета в шапке — ссылка в настройки (Э1-1.4 plan-ux-fixes) */
.bar-end>a.who{font-weight:600;display:inline-flex;align-items:center;gap:5px}
.bar-end>a.who svg{width:14px;height:14px;flex:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.bar-end>a.who.on{color:var(--text)}

/* ——— каркас страницы ——— */
/* Ширину держат вместе `.bar` и `main` одним правилом, иначе шапка и
   содержимое разъезжаются. Числа руками не подгонять: и потолок, и поля
   выводятся из токенов (--page-max, --page-pad), поля растут с экраном.
   Одна ширина у всех экранов (план 2, 5.1; решение владельца 02.09.2026):
   узкой колонки .narrow больше нет — переход между вкладками не должен
   выглядеть как переход на другой сайт. Меру чтения держат сами тексты
   (.sub, .measure, абзацы справки). */
.bar,main{max-width:var(--page-max);margin:0 auto;padding-inline:var(--page-pad)}
main{padding-top:26px;padding-bottom:60px}
/* вход — своя раскладка: узкая колонка по центру, без шапки кабинета */
main.login{max-width:360px;padding-top:8vh}
main.login .logo{font-size:1.6rem;font-weight:700;margin-bottom:6px}
main.login button{width:100%;margin-top:16px}
/* публичная страница «спасибо» — её видит посетитель сайта клиента */
main.thanks{padding-top:48px}
h1{font-size:1.5rem;font-weight:600;letter-spacing:-.02em;margin:0 0 5px;text-wrap:balance}
/* h2 у экрана — раздел страницы («Вебхуки», «API и прямой доступ к базе»,
   «Экспорт» на «Интеграциях»). Своего правила у него не было, и браузерный
   1.5em/0.83em каждый раз подгоняли инлайном. */
h2{font-size:1.12rem;font-weight:600;letter-spacing:-.01em;margin:22px 0 10px;text-wrap:balance}
/* text-wrap:pretty — без висячих строк из одного слова («18.11.2026» одной
   строкой под метой партии корзины) */
.sub{color:var(--text-2);margin:0 0 22px;max-width:70ch;text-wrap:pretty}

/* ——— карточки ——— */
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r-lg);padding:18px;margin-bottom:16px;box-shadow:var(--elev-1),var(--hair)}
.card>*:first-child{margin-top:0}
.card>*:last-child{margin-bottom:0}
/* Заголовок карточки — прямой <b> внутри неё. Правила у него не было, и кегль
   задавали инлайном (в справке — пять раз подряд), отчего одинаковые по роли
   заголовки на разных экранах вышли разного размера. */
/* снизу 8px: кнопка «Сделать бэкап» и таблица «Последние бэкапы» стояли
   вплотную к заголовку — у <b> отступа не было, у них сверху тоже */
.card>b{display:block;font-size:1.05rem;margin-bottom:8px}
/* второй заголовок в той же карточке отбивается от предыдущего блока */
.card>b:not(:first-child){margin-top:16px}
/* пилюля сразу за заголовком — в его строке («48 строк · Вебинар: март»
   и «источник удалён»): блочный <b> сталкивал её на отдельную строку */
.card>b:has(+.pill){display:inline-block;margin-right:8px;vertical-align:middle}
.card>b+.pill{vertical-align:middle}
/* мета под заголовком карточки (партия корзины, таблица источника) — часть
   заголовка, а не вводный абзац экрана: отбивка снизу 14px, а не 22, и без
   меры 70ch — одна строка меты не переносится посреди срока «удалится сама» */
.card>.sub{margin:0 0 14px;max-width:none}
/* форма первой в карточке: подпись первого поля не добавляет сверху свои
   14px — у карточки входа сверху было 32px, снизу 18 */
.card>form:first-child>:first-child{margin-top:0}

/* ——— формы ——— */
/* 14, а не 12: столько отбивали у себя 26 лейблов инлайном — это и есть
   настоящий шаг между блоком настройки и предыдущим текстом */
label{display:block;font-size:.8rem;font-weight:500;color:var(--text-2);margin:14px 0 5px}
/* Высота поля — --ctl-h: строка 20px, рамка 2×1px, остальное — паддинг.
   Та же формула у кнопок ниже, поэтому поле и его кнопка («Сохранить»,
   «Выпустить ключ») — одной высоты при любом значении токена */
input,select,textarea{width:100%;background:var(--bg);border:1px solid var(--border);border-radius:var(--r-sm);color:var(--text);padding:calc((var(--ctl-h) - 22px) / 2) 11px;font:inherit;line-height:20px;transition:border-color .12s,box-shadow .12s,background .12s}
input[type=checkbox],input[type=radio]{width:auto;padding:0}
/* поле внутри подписи («Разделитель», «Кодировка») наследовало её кегль
   .8rem и вес 500 — и выглядело не так, как соседние поля */
label>:is(select,input,textarea){font-size:.875rem;font-weight:400}
/* поле прямо в форме — не шире меры .measure: «Столбец-ключ» и «Имя
   представления» тянулись на всю карточку, на 1720px — в 1600px */
form>:is(input:not([type=checkbox]):not([type=radio]):not([type=file]),select,textarea){max-width:560px}
/* ряд действий в конце формы отбивается от последнего поля: у полей нет
   нижнего отступа, и «Сменить пароль», «Сохранить», «Разобрать», «Создать
   представление» стояли к полю вплотную. Форма из одной кнопки («Вернуть»,
   «Сделать бэкап»), форма-строка .inline, выборка и формы в ячейке и в окне
   не меняются */
form:not(.inline):not(.selform):not(td *):not(dialog *)>:is(button,.btn,div):last-child:not(:first-child){margin-top:16px}
/* background-COLOR, не сокращение `background`: сокращение сбрасывает
   background-repeat/position, и стрелка select (она из data:-URI) начинает
   тайлиться по всему полю. Правило светлой темы идёт после `select{...}`,
   поэтому сброс был бы виден только в светлой теме. */
[data-theme="light"] input,[data-theme="light"] select,[data-theme="light"] textarea{background-color:var(--surface)}
input::placeholder,textarea::placeholder{color:var(--muted)}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:var(--ring)}
/* Стрелка — шеврон из двух штрихов цвета --text-2, а не SVG в data:-URI: в
   URI цвет вписывался литералом (#9aa1ac и #586170 — копии токена), и светлой
   теме нужна была своя картинка. Градиент берёт токен сам — одна стрелка на
   обе темы и любую будущую палитру. Каждый штрих — диагональ квадрата 5px */
select{appearance:none;-webkit-appearance:none;padding-right:34px;cursor:pointer;
  background-image:linear-gradient(45deg,transparent calc(50% - .8px),var(--text-2) calc(50% - .8px),var(--text-2) calc(50% + .8px),transparent calc(50% + .8px)),linear-gradient(-45deg,transparent calc(50% - .8px),var(--text-2) calc(50% - .8px),var(--text-2) calc(50% + .8px),transparent calc(50% + .8px));
  background-size:5px 5px;background-repeat:no-repeat;background-position:right 17px center,right 12px center}

/* ——— кнопки ——— */
/* Кнопка — той же высоты, что поле и контролы ряда: паддинг из --ctl-h,
   строка 20px и рамка 1px у ВСЕХ кнопок (у сплошной — прозрачная). Раньше у
   сплошной рамки не было вовсе, и «Вернуть» (39.6px) стояла рядом с «Удалить
   окончательно сейчас» (41.6px) на два пикселя ниже. Кегль — как у кнопок
   ряда (.86rem), чтобы «Сохранить» в форме и «Выгрузить CSV» в шапке экрана
   были одним и тем же контролом */
button,.btn{font:inherit;cursor:pointer;background:var(--accent);color:var(--accent-ink);border:1px solid transparent;border-radius:var(--r-sm);padding:calc((var(--ctl-h) - 22px) / 2) 14px;font-weight:600;font-size:.86rem;line-height:20px;display:inline-flex;align-items:center;justify-content:center;gap:8px;transition:background .12s,box-shadow .12s,transform .06s}
button:not(.ghost),.btn:not(.ghost){box-shadow:var(--hair),var(--elev-1)}
button:hover:not(.ghost),.btn:hover:not(.ghost){background:var(--accent-2)}
button:active:not(.ghost),.btn:active:not(.ghost){transform:translateY(1px)}
button.ghost,.btn.ghost{background:transparent;color:var(--text-2);border:1px solid var(--border);font-weight:500}
button.ghost:hover,.btn.ghost:hover{color:var(--text);border-color:var(--border-2);background:var(--surface-2);text-decoration:none}
button:focus-visible,.btn:focus-visible{outline:none;box-shadow:var(--ring)}
button svg,.btn svg{width:16px;height:16px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* Недоступная кнопка — серая и читаемая (--muted на --surface-2: 5.4:1 и 4.6:1), а не
   полупрозрачная: opacity .5 роняла «▶ Выполнить» во время запроса и
   «Удалить выделенные» без выделения до 2.3–2.9:1. !important — как у [hidden]:
   «недоступно» сильнее любого вида кнопки (сплошной, обводной, опасной) и
   её ховера, а их правила специфичнее :disabled */
:is(button,.btn):disabled{opacity:1;cursor:not-allowed;background:var(--surface-2)!important;color:var(--muted)!important;border-color:var(--border)!important;box-shadow:none!important;transform:none!important}
input:disabled,select:disabled,textarea:disabled{cursor:not-allowed;color:var(--muted);background-color:var(--surface-2)}

/* ——— переключатель режима (сегменты) ——— */
/* «Каталог / SQL» — два вида одного раздела «Данные», а не два раздела:
   поэтому сегменты рядом с заголовком, а не пункт меню. Внутри — обычные
   ссылки. */
/* Высота — из --ctl-h, а не из суммы паддингов: сегмент стоит в одном ряду с
   кнопками, и «почти одинаковые» высоты читаются как контролы из разных
   мест. align-items:stretch + inline-flex у ссылки центрируют подпись внутри
   заданной высоты. */
.seg{display:inline-flex;align-items:stretch;box-sizing:border-box;height:var(--ctl-h);gap:2px;padding:2px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--r-sm)}
.seg a{display:inline-flex;align-items:center;padding:0 13px;border-radius:calc(var(--r-sm) - 2px);color:var(--text-2);font-size:.86rem;font-weight:500;line-height:1.2;white-space:nowrap;transition:color .12s,background .12s}
.seg a:hover{color:var(--text);background:var(--surface);text-decoration:none}
.seg a.on,.seg a.on:hover{background:var(--accent);color:var(--accent-ink);box-shadow:var(--elev-1)}

/* ——— шапка экрана ——— */
/* «← К данным», заголовок и действия экрана одним рядом: «Выгрузить CSV»,
   «Дедупликация», «Корзина» стоят в шапке, а не в ряду фильтров — там они
   читались бы как часть выборки, а не как действия. */
.pagehead{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.pagehead h1{margin:0;font-size:1.35rem}
/* Действия экрана — у правого края, как правый кластер шапки: у кнопок одно
   место на всех экранах, а не «сразу за заголовком», где их двигала длина
   названия. На телефоне — снова слева, под заголовком (блок узкого экрана) */
.pagehead>h1+*{margin-left:auto}
/* подзаголовок под шапкой с сегментами («Данные: Каталог / SQL») — отбивка, как у h1 */
.pagehead+.sub{margin-top:8px}
/* Кнопка с выпадающим меню (план 2, 3.2): <details class="menu"> без JS,
   summary выглядит кнопкой, список — карточкой под ней справа. */
.menu{position:relative}
.menu>summary{list-style:none;user-select:none}
.menu>summary::-webkit-details-marker{display:none}
.menu[open]>summary{color:var(--text);border-color:var(--border-2)}
/* меню — поднятая панель, как панель выборки: рамка --border-2 и радиус
   панели --r-md (было --border и радиус контрола) */
.menu-list{position:absolute;right:0;top:calc(100% + 4px);min-width:280px;z-index:30;display:flex;flex-direction:column;gap:2px;padding:6px;background:var(--surface);border:1px solid var(--border-2);border-radius:var(--r-md);box-shadow:var(--elev-2)}
.menu-sub{display:block;margin-top:2px;font-size:.76rem;color:var(--muted)}
/* все кнопки шапки — той же высоты, что сегменты: «← К данным» в 41px рядом с
   сегментами в 34px читается как кнопка из другого экрана */
.pagehead .btn{height:var(--ctl-h);box-sizing:border-box;padding:0 13px;font-size:.86rem}

/* ——— панель выборки: один ряд, одна высота ——— */
/* Все контролы от --ctl-h: «почти одинаковые» высоты в одном ряду читаются
   как контролы из разных мест. */
.toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 14px}
/* только прямые дети: `.toolbar button` захватывал бы и кнопки внутри
   раскрытых панелей выборки, раздувая их до высоты ряда */
.toolbar>.btn,.toolbar>button{height:var(--ctl-h);box-sizing:border-box;padding:0 13px;font-size:.86rem}

/* ——— таблицы (сердце платформы данных) ——— */
/* Высота — от окна, а не фиксированный потолок: 560px запирали таблицу в
   треть высокого экрана, под ней оставалась пустота, и получалось два скролла
   (страницы и внутренний). Вычет — шапка сайта, заголовок страницы и отступы. */
.tablewrap{max-height:calc(100vh - 260px);overflow:auto;border:1px solid var(--border);border-radius:var(--r-md);background:var(--surface)}
.tablewrap::-webkit-scrollbar{height:10px;width:10px}
.tablewrap::-webkit-scrollbar-thumb{background:var(--border-2);border-radius:var(--r-sm);border:2px solid var(--surface)}
table{width:100%;border-collapse:separate;border-spacing:0;font-size:.86rem}
thead th{position:sticky;top:0;z-index:2;text-align:left;color:var(--muted);font-weight:600;font-size:.76rem;letter-spacing:.01em;padding:9px 12px;background:var(--surface-2);border-bottom:1px solid var(--border);white-space:nowrap}
td{padding:8px 12px;border-bottom:1px solid var(--border);vertical-align:top}
tbody tr:last-child td{border-bottom:none}
tbody tr:nth-child(even) td{background:color-mix(in srgb,var(--surface-2) 45%,transparent)}
tbody tr:hover td{background:var(--surface-2)}
/* закреплённый первый столбец (выбор строки или первый столбец данных) — не теряется
   при прокрутке многих столбцов */
/* волосок справа у закреплённой ячейки — градиентом цвета --border, а не
   тенью 1px 0 0 (геометрия тени — литерал); фон этих ячеек поэтому задаётся
   background-color, а не сокращением, которое стёрло бы волосок */
.tablewrap table.records td:first-child,.tablewrap table.records th:first-child{position:sticky;left:0;z-index:1;background-image:linear-gradient(to left,var(--border) 1px,transparent 1px)}
.tablewrap table.records thead th:first-child{z-index:3}
.tablewrap table.records td:first-child{background-color:var(--surface)}
.tablewrap table.records tbody tr:nth-child(even) td:first-child{background-color:color-mix(in srgb,var(--surface-2) 45%,var(--surface))}
.tablewrap table.records tbody tr:hover td:first-child{background-color:var(--surface-2)}
/* Длинное значение (комментарий из формы) раздувало строку до трёх сотен
   пикселей и съедало половину таблицы. Показываем до трёх строк в ячейке не
   шире 200px (план 2, 5.4: шесть колонок влезают в 1117px без прокрутки),
   полностью — во всплывающем окне по клику (.cell.long, data/static/table.js)
   и в карточке строки. */
.tablewrap table.records tbody td{max-width:200px}
/* именно `break-word`, а не `anywhere`: `anywhere` обнуляет min-content ширину
   ячейки, и авто-раскладка таблицы ужимает столбцы до нескольких символов —
   короткий email начинает переноситься посреди слова. */
.tablewrap table.records .cell{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;line-clamp:3;overflow:hidden;overflow-wrap:break-word}
/* Структура в ячейке — значок со счётчиком, а не значение. Показывать её текстом
   нельзя (в ячейку приехал бы JSON во всю ширину), а прочерком — врать: прочерк
   означает «поля не пришло», а тут данные есть. Высота строки от значка не
   меняется: таблица должна читаться по вертикали. */
.tablewrap table.records .cell.struct{display:inline-flex;align-items:center;gap:4px;padding:1px 7px;
  border:1px solid var(--border);border-radius:var(--r-pill);background:var(--surface-2);
  color:var(--text-2);font-family:var(--mono);font-size:.78rem;white-space:nowrap;cursor:default}
/* JSON структуры — моноширинным в ограниченной рамке: в карточке строки и во
   всплывающем окне значения */
.structjson{margin:6px 0 0;max-width:420px;max-height:220px;overflow:auto;white-space:pre-wrap;
  overflow-wrap:anywhere;font-family:var(--mono);font-size:.74rem;line-height:1.35;color:var(--text-2);
  background:var(--surface-2);border:1px solid var(--border);border-radius:var(--r-sm);padding:6px 8px}
/* Значение ячейки — структура или длинный текст — открывается в общем окне
   (план 2, 5.5; находка № 24: окошко 80px внутри ячейки растило строку до
   270px) */
dialog.structdlg{max-width:min(760px,92vw)}
dialog.structdlg .structjson{margin:0;max-width:none;max-height:70vh;font-size:.8rem}
dialog.structdlg .dlg-h{display:flex;align-items:center;justify-content:space-between;gap:12px}
/* Числа (Э3-3.1 plan-ux-fixes): вправо, табличные цифры; полное значение —
   по клику (static/cabinet.js), в ячейке — округлённое по-русски. */
/* число под своим заголовком (план 5, 1.3; находка № 23): th.num вправо вместе
   со значениями, ширина числового столбца — по содержимому */
td.num,th.num{text-align:right;width:1%;white-space:nowrap}
.cell.num{font-variant-numeric:tabular-nums;white-space:nowrap}
.cell.num[data-full]{cursor:pointer;text-decoration:underline dotted var(--muted);text-underline-offset:3px}
.mono{font-family:var(--mono);font-size:.85em;font-variant-numeric:tabular-nums}
/* длинный адрес (опрос, webhook) переносится, а не распирает страницу на 375 (план 8, 1.5) */
.mono.wrap{overflow-wrap:anywhere}
td.mono,th.mono{font-variant-numeric:tabular-nums}

/* ——— пилюли статуса ——— */
/* четыре тона: acc — работает («готов», «доставлено»), off — выключено или
   ушло («закреплён», «источник удалён»), warn — ждёт или не легло («в
   очереди», «не легли»), bad — сломано («не получился», «отключён») */
.pill{display:inline-block;padding:2px 9px;border-radius:var(--r-pill);font-size:.72rem;font-weight:500;font-family:var(--mono)}
.pill.acc{background:var(--accent-soft);color:var(--accent)}
/* «выключено» — текстом --text-2: --muted на своей же подложке в светлой
   теме давал 4.28:1 («источник удалён», «закреплён»), --text-2 — 5.1 */
.pill.off{background:var(--muted-soft);color:var(--text-2)}
.pill.bad{background:var(--bad-soft);color:var(--bad)}
.pill.warn{background:var(--warn-soft);color:var(--warn)}

.chk{display:flex;align-items:center;gap:6px;color:var(--text);white-space:nowrap;font-size:.9rem;cursor:pointer}
.chk input{width:auto;margin:0}
/* подпись флажка длиннее строки — переносится, а не уезжает за край (форма рецепта) */
.chk.chk-wrap{white-space:normal;align-items:flex-start}
.chk.chk-wrap input{margin-top:.2em}

/* ——— чипы ——— */
/* ряд чипов-подписок: снизу отбивка, потому что под ним всегда форма «подписать» */
.chips{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:6px 0 8px}
/* чип-ссылка — быстрый выбор в панели выборки: «7 дней», «Без периода»,
   «Все столбцы» */
.chip{position:relative;display:inline-flex;align-items:center;gap:9px;height:var(--ctl-h);padding:0 13px;border:1px solid var(--border);border-radius:var(--r-md);background:var(--bg);color:var(--text-2);font-size:.85rem;line-height:1;white-space:nowrap;cursor:pointer;user-select:none;transition:border-color .12s,background .12s,color .12s}
[data-theme="light"] .chip{background-color:var(--surface)}
.chip:hover{border-color:var(--border-2);color:var(--text)}
/* компактный чип — ровно под высоту сегмента (.seg) и кнопок ряда: разница
   даже в пару пикселей читается как «контролы из разных мест». С 20.10.2026
   высота — сам токен --ctl-h (у .chip выше), а не сумма паддингов: прежний
   расчёт давал 34.5px против 34 у сегмента, а на телефоне не вырос бы до 40 */
.chip.sm{padding:0 12px;border-radius:var(--r-sm);font-size:.86rem;
  line-height:1.2;gap:7px}

/* «×» тега: цель не меньше 24×24 (WCAG 2.5.8) и без правил сплошной кнопки —
   button:not(.ghost) специфичнее .x и давал ей тень, а под мышью заливку
   акцентом: красный крестик на бирюзе */
.x{display:inline-flex;align-items:center;justify-content:center;min-width:24px;min-height:24px;border:none;background:transparent;color:var(--muted);cursor:pointer;font-size:1.15rem;line-height:1;padding:0 4px;border-radius:calc(var(--r-sm) - 2px)}
button.x:not(.ghost){box-shadow:none}
button.x:hover:not(.ghost){color:var(--bad);background:var(--bad-soft)}

/* ——— иконные кнопки ——— */
.iconbtn{position:relative;width:var(--ctl-h);height:var(--ctl-h);padding:0;flex:none;background:transparent;border:1px solid var(--border);border-radius:var(--r-sm);color:var(--text-2);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:color .12s,border-color .12s,background .12s}
.iconbtn:hover{color:var(--text);border-color:var(--border-2);background:var(--surface-2);opacity:1}
/* Иконная кнопка — обводная, как .ghost. Общие правила сплошной кнопки
   (button:not(.ghost) — тень, button:hover:not(.ghost) — заливка --accent-2)
   специфичнее .iconbtn и доставались ей: шеврон строки, тумблер темы, «+»
   черновика и «×» окна под мышью заливались акцентом, значок на нём — 1.5:1 */
button.iconbtn:not(.ghost){box-shadow:none}
button.iconbtn:hover:not(.ghost){background:var(--surface-2)}
button.iconbtn:focus-visible{box-shadow:var(--ring)}
.iconbtn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;pointer-events:none}
.iconbtn[data-tip]::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%) translateY(4px);background:var(--surface);color:var(--text);border:1px solid var(--border-2);padding:5px 9px;border-radius:var(--r-sm);font-size:.76rem;font-weight:400;line-height:1.2;white-space:nowrap;box-shadow:var(--elev-2);pointer-events:none;opacity:0;transition:opacity .12s,transform .12s;z-index:30}
.iconbtn[data-tip]::before{content:"";position:absolute;bottom:calc(100% + 3px);left:50%;transform:translateX(-50%);border:5px solid transparent;border-top-color:var(--border-2);pointer-events:none;opacity:0;transition:opacity .12s;z-index:30}
.iconbtn[data-tip]:hover::after,.iconbtn[data-tip]:focus-visible::after{opacity:1;transform:translateX(-50%) translateY(0)}
.iconbtn[data-tip]:hover::before,.iconbtn[data-tip]:focus-visible::before{opacity:1}
/* В столбце действий строки тултип прижат к правому краю, а не отцентрован по
   кнопке: столбец стоит у правого края страницы, и центрированная всплывашка
   торчала за него — прозрачная (opacity:0), но в раскладке живая, поэтому
   давала странице горизонтальную прокрутку на ЛЮБОЙ ширине (+28px на «Приёме»,
   ловилось У4 и выглядело как поломка вёрстки). Это тот самый «переворот у
   границы», который в готовых библиотеках делает коллизия-детектор; здесь
   край известен заранее, поэтому хватает правила. */
.rc-actions .iconbtn[data-tip]::after{left:auto;right:0;transform:translateY(4px)}
.rc-actions .iconbtn[data-tip]:hover::after,.rc-actions .iconbtn[data-tip]:focus-visible::after{transform:translateY(0)}
.rc-actions .iconbtn[data-tip]::before{left:auto;right:13px;transform:none}

.editpanel{margin-top:14px;padding-top:14px;border-top:1px solid var(--border)}
.editpanel[hidden]{display:none}
.iconbtn.chevron svg{transition:transform .15s}
.iconbtn.chevron.open svg{transform:rotate(180deg)}

/* ——— таблица «столбец — тип» ——— */
/* столбцы и типы в каталоге и «О таблице», «Таблицы источников», бэкапы,
   карточка строки (вариант .rowvals) */
table.fields{width:auto;min-width:min(420px,100%);border-collapse:collapse}
table.fields td,table.fields th{border-bottom:1px solid var(--border);padding:7px 10px}
table.fields thead th{position:static;background:none;border-bottom:1px solid var(--border)}
table.fields td:first-child,table.fields th:first-child{font-family:var(--mono);font-size:.85em;color:var(--text);text-align:left}
/* Столбцы после первого — по содержимому, но текст в них ВЛЕВО, а не по
   центру: в «Последних бэкапах» центр разбрасывал «кнопкой», пилюлю статуса и
   её пояснение по разным осям, а заголовок «тип» стоял не над выбором типа.
   Числа по-прежнему вправо — классом num */
table.fields td+td,table.fields th+th{text-align:left;width:1%;white-space:nowrap;padding-left:16px;padding-right:16px}
table.fields tbody tr:nth-child(even) td{background:none}
table.fields tbody tr:hover td{background:var(--surface-2)}
table.fields td.col-type{text-align:left;width:auto}
/* «Тип столбца»: выбор типа, кнопка и пилюля «закреплён» — одним рядом
   одной высоты; было поле в 27.5px рядом с кнопкой в 41.6 */
table.fields td.col-type form{display:flex;align-items:center;gap:8px}
table.fields td.col-type select{width:auto;height:var(--ctl-h);padding:0 28px 0 9px;font-size:.85rem;background-position:right 15px center,right 10px center}

/* Отключённый источник приглушён цветом текста, а не прозрачностью: opacity
   .55 роняла до 2.6:1 (2.2 в светлой теме) и подписи, и рабочие в этой строке
   «Включить» с меню «…» */
.rowcard.arch>.rc-main>b,.rowcard.arch .rc-stats>span{color:var(--text-2)}
.rowcard.arch .rc-meta,.rowcard.arch .rc-meta .mono,.rowcard.arch .rc-stats>span>small{color:var(--muted)}

details>summary{cursor:pointer;color:var(--text-2);font-size:.9rem;user-select:none;list-style:none}
details>summary::-webkit-details-marker{display:none}
/* Маркер сводки — один на кабинет: шеврон из двух штрихов цвета --muted, как
   значок chevron; вправо — свёрнуто, вниз — раскрыто. Было два разных:
   браузерный ▶ у «Создать источник», «О таблице», «Очистить источник» и
   текстовый «▸» у примеров. Меню «…» и панели выборки — кнопки, им маркер
   не нужен */
details:not(.menu):not(.sel-panel)>summary::before{content:"";display:inline-block;width:.42em;height:.42em;margin:0 .7em .14em .1em;border:solid var(--muted);border-width:0 1.5px 1.5px 0;transform:rotate(-45deg);transition:transform .15s}
details[open]:not(.menu):not(.sel-panel)>summary::before{transform:translateY(-.12em) rotate(45deg)}
details>summary:hover{color:var(--text)}
details[open]>summary{color:var(--text);margin-bottom:6px}
/* «Создать источник», «Как подключить к сайту» — заголовок карточки, как <b>
   у других карточек: тот же кегль и цвет, и в свёрнутом виде тоже */
details.card>summary{color:var(--text)}
details.card>summary>b{font-size:1.05rem}
.scrolly{max-height:340px;overflow:auto}
.tag{display:inline-flex;align-items:center;gap:6px;padding:4px 6px 4px 12px;border:1px solid var(--border);border-radius:var(--r-md);background:var(--bg);color:var(--text-2);font-size:.84rem;line-height:1}
[data-theme="light"] .tag{background-color:var(--surface)}

.checklist{max-height:320px;overflow:auto;border:1px solid var(--border);border-radius:var(--r-sm);padding:4px}
.chk-row{display:flex;align-items:center;gap:9px;padding:7px 9px;border-radius:calc(var(--r-sm) - 2px);font-size:.9rem;cursor:pointer;color:var(--text)}
.chk-row:hover{background:var(--surface-2)}
.chk-row input[type=checkbox]{width:auto;height:16px;margin:0;padding:0;accent-color:var(--accent);cursor:pointer}
/* свёрнутый пример внутри карточки (пример формы, опрос по адресу) */
details.example{margin:8px 0 0}
details.example>summary{cursor:pointer;list-style:none;color:var(--accent);font-size:.85rem}
details.example>summary::-webkit-details-marker{display:none}

/* стрелки порядка столбцов в панели «Столбцы» (план 3, 2.1): видны только у
   отмеченных строк — порядок есть только у того, что показывается */
.chk-move{margin-left:auto;display:flex;gap:2px;visibility:hidden}
.chk-row:has(input:checked) .chk-move{visibility:visible}
/* ↑↓ — вторичные кнопки строки, обводные: сплошной акцент давал десяток
   бирюзовых квадратов на каждый список столбцов */
.chk-move button{width:24px;height:22px;padding:0;font-size:.8rem;line-height:1;border-radius:calc(var(--r-sm) - 2px);background:transparent;color:var(--text-2);border:1px solid var(--border)}
.chk-move button:not(.ghost){box-shadow:none}
.chk-move button:hover:not(.ghost){background:var(--surface-2);color:var(--text);border-color:var(--border-2)}
dialog input[type=text],dialog select{width:100%}

/* ——— kv-таблица (API, журналы опроса и доставок) ——— */
.kv{width:100%;border-collapse:collapse;font-size:.86rem;margin-top:6px}
.kv td{padding:8px 10px;border-bottom:1px solid var(--border);vertical-align:top;color:var(--text)}
/* ключ строки (время в журнале, имя параметра API) — --text-2, а не
   акцентом: акцентный текст в кабинете значит «ссылка», а это не ссылка */
.kv td:first-child{white-space:nowrap;font-family:var(--mono);font-size:.82rem;color:var(--text-2);width:1%}
.kv tr:last-child td{border-bottom:none}
/* Пояснение под контролом или абзац справки. Своего margin у него не было, а
   носитель — <p> с браузерным `1em`: поэтому КАЖДОЕ употребление несло
   инлайновый отступ, и их набралось под шесть десятков. Одно правило вместо
   всех: 6px сверху, снизу ноль (следующий блок отбивается сам). */
.hint{color:var(--text-2);font-size:.88rem;margin:6px 0 0;text-wrap:pretty}
/* пояснение над карточкой («Платформа сама шлёт POST…» над вебхуком) — снизу
   ноль, у карточки сверху тоже: они стояли вплотную */
.hint+.card{margin-top:14px}
/* пояснение сразу под подписью — часть одного блока, отбивка меньше */
label+.hint{margin-top:2px}
.inline{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:6px}
/* форма-строка прямо в карточке — выпуск ключа API под списком ключей,
   подписка вебхука под чипами: отбита от того, что над ней, сильнее ряда
   контролов внутри формы */
.card>form.inline{margin-top:10px}
.inline select{width:auto;min-width:160px;max-width:100%}
.inline>label{min-width:0;max-width:100%}
/* своя кнопка выбора файла (план 8, 1.13): input живой, но невидимый */
.filepick{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.filepick label.btn{position:relative;overflow:hidden;margin:0}
.filepick input[type=file]{position:absolute;inset:0;opacity:0;width:100%;height:100%;cursor:pointer}
/* поле, забирающее остаток строки контролов; ширину сверху держит .measure */
.grow{flex:1;min-width:120px}
.muted{color:var(--muted)}
.msg{padding:10px 14px;border-radius:var(--r-sm);margin:0 0 16px;font-size:.9rem;border:1px solid transparent}
/* сообщение об ошибке внутри формы (а не баннером страницы) — отбивается от
   контрола, к которому относится */
p.msg{margin:8px 0 0}
/* та же плашка в настройках источника, когда в ней форма («Отменить
   загрузку»): <p> форму не держит, поэтому div — с тем же отступом */
.rc-panel>div.msg{margin:8px 0 0}
.msg.ok{background:var(--good-soft);color:var(--good);border-color:color-mix(in srgb,var(--good) 30%,transparent)}
/* ссылка в плашке — цветом самой плашки и подчёркнута: бирюза на зелёной
   подложке давала 2.8–4.3:1 и спорила с цветом плашки */
.msg a,.msg a:hover{color:inherit;text-decoration-color:currentColor}
/* выбор строки — чекбокс в первой (липкой) ячейке экрана таблицы */
.tablewrap table.records td input.sel{margin:0 6px 0 0;vertical-align:middle;cursor:pointer}
/* «Отменить загрузку» внутри плашки (Д2 plan-dedup): форма в строке, кнопка
   не выше текста плашки */
.msg form.undo{display:inline-block;margin-left:8px;vertical-align:middle}
.msg form.undo button{padding:2px 10px;font-size:.85rem}
.msg.err{background:var(--bad-soft);color:var(--bad);border-color:color-mix(in srgb,var(--bad) 30%,transparent)}
/* «Помощь» (Э7 плана пересмотра): ссылки на сайт документации — чипы в ряд;
   якоря карточек не прячутся под липкой шапкой */
.toc{display:flex;flex-wrap:wrap;gap:6px 10px;margin:0 0 18px}
.toc a{padding:4px 10px;border:1px solid var(--border);border-radius:var(--r-pill);font-size:.85rem;font-weight:500;white-space:nowrap;color:var(--text-2);transition:color .12s,background .12s}
.toc a:hover{color:var(--text);background:var(--surface-2);text-decoration:none}
.card[id]{scroll-margin-top:calc(var(--bar-h) + 12px)}
/* не успех и не ошибка — спокойный фон: «заявка уже в очереди», «отменять
   нечего» */
.msg.info{background:var(--accent-soft);color:var(--text);border-color:color-mix(in srgb,var(--accent) 30%,transparent)}
/* перенос — только там, где иначе не влезет (overflow-wrap:anywhere), а не
   на любой букве у края строки (word-break:break-all): «X-Goodwink-Signatur|e»
   и «_|meta» рвались, хотя целиком помещались на следующей строке */
code{font-family:var(--mono);background:var(--surface-2);padding:2px 6px;border-radius:calc(var(--r-sm) - 2px);font-size:.85em;overflow-wrap:anywhere}
/* клавиша в тексте справки: «Ctrl+Enter — выполнить» */
kbd{font-family:var(--mono);font-size:.8em;padding:1px 5px;border:1px solid var(--border-2);border-bottom-width:2px;border-radius:calc(var(--r-sm) - 2px);background:var(--surface-2);white-space:nowrap}

/* ——— диалоги ——— */
dialog{background:var(--surface);color:var(--text);border:1px solid var(--border-2);border-radius:var(--r-lg);box-shadow:var(--elev-2);max-width:min(680px,92vw);width:100%;max-height:90vh;padding:0}
dialog::backdrop{background:var(--scrim)}
/* модалка подтверждения (Э6-6.1 plan-ux-fixes): одна на кабинет, узкая; текст
   с переносами из JS (\n), опасная кнопка — красная и последняя */
dialog.confirm{max-width:min(460px,92vw)}
dialog.confirm [data-role=text]{margin:0;white-space:pre-line;line-height:1.5}
dialog.confirm .actions{display:flex;justify-content:flex-end;gap:8px}
/* текст на красном — свой токен --bad-ink: --accent-ink подобран к акценту,
   и с iris красная кнопка давала 3.1:1. Ховер — на ступень дальше от фона
   (подмесь --text), как --accent-2 у акцента, а не filter */
dialog.confirm button.danger{background:var(--bad);border-color:var(--bad);color:var(--bad-ink)}
dialog.confirm button.danger:hover{background:color-mix(in srgb,var(--bad) 85%,var(--text));border-color:transparent}
/* Прокручивается ОДНА зона внутри окна, а не окно целиком: строка с полусотней
   столбцов вырастала бы на 1200px, и на ноутбуке уезжала бы шапка с номером.
   Шапка остаётся на месте — данные прокручиваются под ней. */
dialog[open]{display:flex;flex-direction:column}
dialog>*{flex:none}
dialog .dlg-scroll{flex:1 1 auto;overflow:auto;min-height:0}
/* Шапка окна: заголовок слева, действия и «×» — справа */
.dlg-h{display:flex;align-items:flex-start;gap:16px;padding:15px 18px;border-bottom:1px solid var(--border)}
/* заголовок окна строки и окна значения — <b>, у подтверждения — .t: один вид */
.dlg-h .t,.dlg-h>b{font-weight:600;font-size:1.02rem;letter-spacing:-.01em}
.dlg-h .iconbtn{margin-left:auto}
.dlg-b{padding:14px 18px;border-bottom:1px solid var(--border)}
.dlg-b:last-of-type{border-bottom:none}
dialog pre{margin:0;padding:16px;overflow:auto;max-height:60vh;font-family:var(--mono);font-size:.8rem;white-space:pre-wrap;word-break:break-word}
/* Готовый к копированию кусок кода — пример формы, запрос curl, запрос
   представления, исходный запрос. До 05.08.2026 та же коробка была расписана
   инлайном в пяти местах, причём без рамки и с литеральным радиусом. */
pre.block{background:var(--bg);padding:12px;border-radius:var(--r-sm);border:1px solid var(--border);overflow:auto;font-family:var(--mono);font-size:.8rem}
[data-theme="light"] pre.block{background-color:var(--surface-2)}
.overflow{overflow-x:auto}

/* ── строка-карточка: ЕДИНСТВЕННАЯ форма «строки списка» в кабинете ─────────
   Источники, вебхуки и ключи API на «Интеграциях». До 05.08.2026 та же
   строка была написана трижды (.rowcard, .cardhead+.iconrow и флекс руками),
   и три копии успели разойтись: у одной действия прибиты к правому краю, у
   другой стоят вплотную к заголовку, у третьей мета красилась инлайном. Одна
   анатомия на всех: rc-main (сжимается и переносит мету) — rc-actions
   (ширину задают только кнопки, текст на неё не влияет никогда). Всё, что
   положили в карточку после этих двух, встаёт своей строкой во всю ширину —
   правило ниже, поэтому чипы и таблицы в шаблоне не требуют обёрток. */
.rowcard{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 18px;align-items:center;padding:14px 16px}
.rowcard .rc-main{min-width:0}
/* строка целиком кликабельна там, где раскрывает свои настройки */
.rowcard .rc-main[onclick]{cursor:pointer}
.rowcard .rc-main>b{font-size:.95rem}
.rowcard .rc-meta{display:flex;flex-wrap:wrap;align-items:center;gap:3px 8px;margin-top:5px;font-size:.8rem;color:var(--muted)}
/* мета переносится ПАЧКАМИ: внутри пачки перенос запрещён, иначе «последнее
   событие» отрывается от даты, а на следующей строке остаётся одинокая точка */
.rowcard .rc-meta>span{white-space:nowrap}
.rowcard .rc-meta .mono{color:var(--text-2)}
.rowcard .rc-actions{display:flex;gap:6px;align-items:center;flex:none}
.rowcard .rc-actions .iconbtn{width:var(--ctl-h);height:var(--ctl-h)}
/* действия карточки со словом (Э6-6.2 plan-ux-fixes, находка № 29): иконка +
   подпись вместо голой иконки с тултипом; опасное — красным и последним */
.act{height:var(--ctl-h);padding:0 10px;gap:6px;font-size:.86rem;white-space:nowrap}
/* секрет с кнопками рядом (Э6-6.3): адрес приёма, API-ключ */
.secretrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:4px 0 10px}
/* значение секрета — поле только для чтения той же высоты, что кнопки рядом,
   а не строчный код в 20px между кнопками в 34px; длинный адрес переносится */
.secretrow code{display:inline-flex;align-items:center;min-height:var(--ctl-h);padding:5px 10px;border:1px solid var(--border);border-radius:var(--r-sm);line-height:1.35;overflow-wrap:anywhere}
.act svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;pointer-events:none}
.act.danger{color:var(--bad)}
.act.danger:hover{color:var(--bad);border-color:var(--bad);background:var(--bad-soft)}
/* всё прочее содержимое карточки — своей строкой сетки на всю ширину:
   раскрытые настройки, секрет подписи, список подписок, журнал доставок */
.rowcard>:not(.rc-main):not(.rc-stats):not(.rc-actions){grid-column:1/-1}
.rowcard .rc-panel{margin-top:10px;border-top:1px solid var(--border)}
/* та же анатомия внутри карточки: список одного блока (ключи API на
   «Интеграциях»). Отличается только рамой — своей у него нет, разделяются
   строки волоском. */
.rowcard.inset{padding:9px 0;border-top:1px solid var(--border)}
.rowcard.inset:first-of-type{border-top:none}
/* заголовок такой строки бывает длинным (имя ключа — что ввели), поэтому
   одной строкой с многоточием */
.rowcard.inset .rc-main>b{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ── список ресурсов (план 4, Э2; правило «один объект — один облик»,
   находки № 2, 3, 17, 18 четвёртого прохода). Источник на «Источниках» —
   строка списка: название (строка раскрывает настройки), мета словами, числа
   справа в своих колонках, одно главное действие, остальное — меню «…».
   Рама одна на весь список (.rlist), строки разделяет волосок; карточка
   на каждый элемент читалась как список несвязанных объектов. */
.card.rlist{padding:0;overflow:visible}
/* поиск по имени над списком — от 8 объектов (план 5, 3.1) */
input.rsearch{max-width:320px;margin:0 0 10px}
.rlist>.rrow{border-top:1px solid var(--border)}
.rlist>.rrow:first-child{border-top:none}
.rowcard.rrow{grid-template-columns:minmax(0,1fr) auto auto;padding:12px 16px;transition:background .12s}
.rowcard.rrow:has(>.rc-main[onclick]:hover){background:var(--surface-2)}
.rowcard.rrow>.rc-main[onclick]:hover>b{color:var(--accent)}
/* числа — в своих колонках, табличными цифрами: сравниваются взглядом сверху вниз */
.rc-stats{display:flex;gap:16px;align-items:flex-start;flex:none}
.rc-stats>span{display:flex;flex-direction:column;align-items:flex-end;min-width:58px;white-space:nowrap;font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:.9rem;color:var(--text)}
.rc-stats>span>small{font-family:var(--font);font-size:.72rem;color:var(--muted);font-weight:400}
/* меню «…» строки: отключить, удалить — не кнопки одного веса с главным
   действием (находка № 3) */
.menu.more>summary.iconbtn{font-size:1.1rem;letter-spacing:1px;font-weight:600;line-height:1}
.menu.more .menu-list{min-width:220px}
.menu-list form{display:contents}
/* пункт — блок, а не колонка flex: значок встаёт в строку со словом
   («▭ Отключить»), вторая строка (.menu-sub) — под ними; в колонке flex
   значок стоял отдельной строкой над словом */
.menu-list button{display:block;width:100%;padding:8px 10px;border:0;border-radius:calc(var(--r-sm) - 2px);background:none;color:var(--text);font:inherit;font-size:.9rem;text-align:left;cursor:pointer;box-shadow:none}
.menu-list button:hover{background:var(--surface-2)}
.menu-list button.danger{color:var(--bad)}
.menu-list button.danger:hover{background:var(--bad-soft)}
.menu-list button svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.8;vertical-align:-2px;margin-right:4px}

/* ── мера полей: input на всю карточку в 1720px — строка на 90+ знаков ── */
.measure{max-width:560px}

/* .wrap — длинная пачка меты переносится, а не
   уходит за край карточки на 375 px (план 6, Э6, № 24) */
.rowcard .rc-meta>.wrap{white-space:normal;max-width:100%}

/* текст только для чталки экрана: заголовок страницы-приложения, которой
   видимый h1 не нужен (SQL-редактор) */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}

/* ═══ SQL-редактор («Данные → SQL», Э3 plan-sql-editor) ═══════════════════
   Страница-приложение: во всю ширину и ровно в высоту окна под шапкой —
   прокручиваются дерево, редактор и результат, а не страница. Раскладка
   образца (редактор стенда собеседований) — дерево слева, справа вкладки,
   редактор, граница, панель запуска и результат; высоту при нехватке
   первым отдаёт редактор (сжатие 10000 против 1 у результата, до 120px),
   результату — не меньше 23vh: урок образца — «на Full HD под результат
   оставалась щель». Мерено на 2560×1300, 1920×950, 1366×768 и 1280×720
   (У5 sql-layout). Ни одной темы CodeMirror в JS: редактор красится здесь,
   через его классы, подсветка — классами tk-*. */
main.sqlpage{max-width:none;padding:0;display:flex;flex-direction:column;height:calc(100vh - var(--bar-h) - 1px);height:calc(100dvh - var(--bar-h) - 1px)}
.sqled{position:relative;flex:1 1 auto;min-height:0;display:grid;grid-template-columns:280px minmax(0,1fr)}
/* кнопки редактора без заливки: вкладки, строки дерева, столбцы, «×» и «+» —
   общий button кабинета залил бы их акцентом */
/* та же специфичность, что у общего button:hover:not(.ghost), и правило ниже
   по файлу — побеждает и в наведении; в :hover сброс не дублировать: иначе
   он перебивает паддинги .sqled-col и строка дёргается под мышью */
.sqled button.sqled-b{background:none;box-shadow:none;border:none;color:inherit;font-weight:inherit;transform:none;padding:0;border-radius:var(--r-sm);text-align:left}
.sqled button.sqled-b:focus-visible{box-shadow:var(--ring)}

/* дерево: таблицы источников, сырые данные и объекты клиента со столбцами */
.sqled-tree{display:flex;flex-direction:column;min-height:0;background:var(--surface);border-right:1px solid var(--border)}
.sqled-tree-head{display:flex;align-items:center;gap:8px;padding:10px 10px 8px}
.sqled-tree-head .seg{flex:1}
.sqled-tree-head .seg a{flex:1;justify-content:center}
.sqled-tree-head .iconbtn{width:var(--ctl-h);height:var(--ctl-h)}
/* подсказки кнопок у правого края (обновить дерево, новый черновик) — к краю:
   по центру они уходили за экран и на телефоне давали прокрутку вбок */
.sqled-tree-head .iconbtn[data-tip]::after,.sqled-tabbar .iconbtn[data-tip]::after{left:auto;right:0;transform:translateY(4px)}
.sqled-tree-head .iconbtn[data-tip]:hover::after,.sqled-tabbar .iconbtn[data-tip]:hover::after{transform:translateY(0)}
.sqled-tree-head .iconbtn[data-tip]::before,.sqled-tabbar .iconbtn[data-tip]::before{left:auto;right:12px;transform:none}
input.sqled-find{flex:none;width:auto;margin:0 10px 6px;padding:6px 10px;font-size:.84rem}
.sqled-tree-body{flex:1 1 auto;min-height:0;overflow:auto;padding:0 6px 14px}
.sqled-group{margin:12px 6px 4px;font-size:.7rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
.sqled-item{display:flex;align-items:flex-start;border-radius:var(--r-sm)}
.sqled-item:hover,.sqled-item:focus-within{background:var(--surface-2)}
.sqled button.sqled-toggle{flex:1;min-width:0;display:grid;grid-template-columns:14px minmax(0,1fr) auto;gap:0 6px;align-items:baseline;padding:4px 4px 4px 6px;line-height:1.35}
.sqled-caret{color:var(--muted);font-size:.7rem}
.sqled-label{font-size:.86rem;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sqled-count{font-size:.72rem;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}
.sqled-tech{grid-column:2/-1;font-family:var(--mono);font-size:.72rem;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* «+» видна при наведении и фокусе: двадцать плюсов подряд — шум */
.sqled button.sqled-ins{flex:none;width:26px;height:26px;margin:3px 3px 0 0;justify-content:center;text-align:center;color:var(--muted);font-size:1rem;opacity:0}
.sqled-item:hover button.sqled-ins,.sqled button.sqled-ins:focus-visible{opacity:1}
.sqled button.sqled-ins:hover:not(.ghost){color:var(--accent);background:var(--accent-soft)}
.sqled button.sqled-col{display:flex;width:100%;gap:10px;padding:2px 8px 2px 26px;font:.76rem/1.65 var(--mono);color:var(--text-2)}
.sqled button.sqled-col:hover:not(.ghost){background:var(--surface-2);color:var(--text)}
.sqled-col-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sqled-col-type{margin-left:auto;color:var(--muted);white-space:nowrap}
.sqled-note{margin:0;padding:6px 8px;font-size:.84rem;color:var(--muted)}
.sqled-cols-none{padding-left:26px;font-size:.78rem}

/* рабочая колонка: вкладки, редактор, граница, запуск, результат */
.sqled-work{position:relative;display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--bg)}
.sqled-work>.msg{margin:8px 12px;flex:none}
.sqled-tabbar{flex:none;display:flex;align-items:flex-end;gap:6px;padding:8px 12px 0;background:var(--surface-2);border-bottom:1px solid var(--border)}
/* вкладки прокручиваются вбок; нижний край ряда заходит на рамку панели на
   1px — так активная вкладка своим фоном «открывается» в редактор */
.sqled-tabs{display:flex;align-items:flex-end;gap:2px;min-width:0;overflow-x:auto;overflow-y:hidden;margin-bottom:-1px;scrollbar-width:thin}
.sqled-tab{flex:none;display:inline-flex;align-items:center;border:1px solid transparent;border-bottom:none;border-radius:var(--r-sm) var(--r-sm) 0 0;color:var(--text-2)}
.sqled-tab:hover{background:color-mix(in srgb,var(--surface) 55%,var(--surface-2));color:var(--text)}
.sqled-tab.on{background:var(--surface);border-color:var(--border);color:var(--text);padding-bottom:1px}
.sqled button.sqled-tab-name{padding:6px 4px 7px 12px;font-size:.86rem;font-weight:500;max-width:22ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sqled-tab.on button.sqled-tab-name{font-weight:600}
.sqled button.sqled-tab-x{padding:1px 7px;margin-right:4px;color:var(--muted);font-size:1rem;line-height:1}
.sqled button.sqled-tab-x:hover:not(.ghost){color:var(--bad);background:var(--bad-soft)}
input.sqled-tab-input{width:16ch;margin:3px 4px 4px 6px;padding:3px 6px;font-size:.86rem}
.sqled-tabbar .iconbtn.sqled-new{width:28px;height:28px;margin-bottom:4px;font-size:1.1rem;line-height:1}
.sqled-save{margin-left:auto;align-self:center;padding-bottom:4px;font-size:.78rem;color:var(--muted);white-space:nowrap}
.sqled-save.bad{color:var(--bad)}
.sqled-editor{flex:0 10000 34vh;min-height:120px;overflow:hidden;background:var(--surface)}
.sqled-split{flex:none;height:9px;display:flex;align-items:center;justify-content:center;cursor:row-resize;touch-action:none;background:var(--surface-2);border-block:1px solid var(--border)}
.sqled-split::before{content:"";width:44px;height:3px;border-radius:var(--r-pill);background:var(--border-2)}
.sqled-split:hover::before,.sqled-split:focus-visible::before,body.sqled-drag .sqled-split::before{background:var(--accent)}
.sqled-split:focus-visible{outline:none}
body.sqled-drag{cursor:row-resize;user-select:none}
.sqled-run{flex:none;display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 12px;background:var(--surface);border-bottom:1px solid var(--border)}
.sqled-run>button{height:var(--ctl-h);padding:0 13px;font-size:.86rem}
.sqled-run kbd{font:.72rem var(--mono);padding:1px 5px;border-radius:calc(var(--r-sm) - 2px);border:1px solid color-mix(in srgb,var(--accent-ink) 35%,transparent);background:color-mix(in srgb,var(--accent-ink) 12%,transparent)}
label.sqled-rows{display:inline-flex;align-items:center;gap:6px;margin:0;font-size:.82rem;font-weight:400;color:var(--text-2)}
/* «строк» — той же высоты, что «▶ Выполнить» рядом (было 29.5px против 34) */
label.sqled-rows input{width:84px;height:var(--ctl-h);padding:0 8px;text-align:right;font:.84rem var(--mono)}
.sqled-info{font-size:.84rem;color:var(--text-2);font-variant-numeric:tabular-nums}
.sqled-info .ok{color:var(--good);font-weight:600}
.sqled-info .bad{color:var(--bad);font-weight:600}
.sqled-info .stopped{color:var(--text);font-weight:600}
.sqled-info .more{color:var(--accent);font-weight:600;cursor:help;border-bottom:1px dotted currentColor}
/* напоминание справа в панели запуска: редактор меняет данные (Э5.5 плана пересмотра) */
.sqled-run .sqled-rule{margin-left:auto;font-size:.8rem;color:var(--text-2)}
.sqled-result{flex:1 1 0;min-height:max(80px,23vh);overflow:auto;background:var(--surface)}
/* пока идёт новый запрос, прошлый результат приглушён — его не спутать с новым */
.sqled-result.stale>*{opacity:.4;transition:opacity .15s}
.sqled-empty{margin:0;padding:14px 16px;color:var(--muted)}
/* что запуск сделал с таблицами источников: «в корзину», «правка необратима» */
.sqled-result .sqled-touched{margin:12px 16px 0}
.sqled-error{margin:12px;padding:12px 14px;border:1px solid color-mix(in srgb,var(--bad) 30%,transparent);border-radius:var(--r-md);background:var(--bad-soft)}
.sqled-error pre{margin:0;font:.82rem/1.55 var(--mono);color:var(--text);white-space:pre-wrap;overflow-wrap:anywhere}
.sqled-where{margin:10px 0 0;font-size:.84rem;color:var(--text-2);display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.sqled-where button{padding:4px 10px;font-size:.82rem}
/* оверлей «открыто в другой вкладке» / «вход кончился» — поверх редактора */
.sqled-overlay{position:absolute;inset:0;z-index:15;display:grid;place-items:center;background:var(--scrim)}
.sqled-overlay-box{max-width:420px;text-align:center}
.sqled-overlay-box .hint{margin:8px 0 16px}

/* таблица результата: тип под именем столбца, номер строки, числа вправо,
   NULL — словом другого вида (пустая строка остаётся пустой), длинное — в
   подсказке, многострочное — переносом */
/* ширина — по содержимому: растянутая на всё окно таблица раздавала остаток
   столбце номера строки */
table.sqlgrid{width:auto;font:.8rem/1.45 var(--mono)}
.sqlgrid thead th{padding:6px 12px;color:var(--text);font-size:.8rem;letter-spacing:0;border-bottom:1px solid var(--border-2)}
.sqlgrid .sqlgrid-name{display:block}
.sqlgrid .sqlgrid-type{display:block;font-weight:400;font-size:.7rem;color:var(--muted)}
.sqlgrid td{padding:4px 12px;white-space:pre;max-width:520px;overflow:hidden;text-overflow:ellipsis}
.sqlgrid td.multi{white-space:pre-wrap;max-width:none;min-width:24ch}
/* width:auto — общее td.num{width:1%} растягивало таблицу по содержимому на всё окно */
.sqlgrid td.num,.sqlgrid th.num{text-align:right;width:auto}
.sqlgrid .rownum{position:sticky;left:0;z-index:1;text-align:right;color:var(--muted);background-color:var(--surface-2);background-image:linear-gradient(to left,var(--border) 1px,transparent 1px)}
.sqlgrid thead th.rownum{z-index:3}
.sqlgrid tbody tr:nth-child(even) td.rownum,.sqlgrid tbody tr:hover td.rownum{background-color:var(--surface-2)}
.sqlgrid .null{color:var(--muted);font-style:italic}

/* CodeMirror в цветах кабинета. Базовая тема редактора висит на классе с
   областью (.ͼ2 …), поэтому селекторы здесь на ступень длиннее её */
.sqled-editor .cm-editor{height:100%;background:var(--surface);color:var(--text);font-size:13.5px}
/* скелет редактора — повтор базовой темы CodeMirror (в кабинете её вешает
   сам редактор, значения те же): снимку SqlCode дизайн-системы без JS нужен
   тот же вид */
.sqled-editor .cm-scroller{display:flex;align-items:flex-start;height:100%;overflow:auto}
.sqled-editor .cm-gutters{display:flex;flex:none;min-height:100%}
.sqled-editor .cm-gutter{display:flex;flex-direction:column;min-height:100%}
.sqled-editor .cm-lineNumbers .cm-gutterElement{padding:0 3px 0 5px;min-width:20px;text-align:right}
.sqled-editor .cm-content{flex:1 0 auto;margin:0;white-space:pre}
.sqled-editor .cm-line{display:block;padding:0 2px 0 6px}
.sqled-editor .cm-editor.cm-focused{outline:none}
.sqled-editor .cm-editor .cm-scroller{font-family:var(--mono);line-height:1.55}
.sqled-editor .cm-editor .cm-content{caret-color:var(--accent);padding:10px 0}
.sqled-editor .cm-editor .cm-cursor,.sqled-editor .cm-editor .cm-dropCursor{border-left:2px solid var(--accent)}
.sqled-editor .cm-editor .cm-gutters{background:var(--surface-2);color:var(--muted);border-right:1px solid var(--border)}
.sqled-editor .cm-editor .cm-activeLine{background:color-mix(in srgb,var(--accent) 6%,transparent)}
.sqled-editor .cm-editor .cm-activeLineGutter{background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--text-2)}
.sqled-editor .cm-editor .cm-selectionBackground{background:color-mix(in srgb,var(--accent) 20%,transparent)}
.sqled-editor .cm-editor.cm-focused>.cm-scroller>.cm-selectionLayer .cm-selectionBackground{background:color-mix(in srgb,var(--accent) 30%,transparent)}
.sqled-editor .cm-editor.cm-focused .cm-matchingBracket{background:var(--accent-soft-2);outline:none}
.sqled-editor .cm-editor.cm-focused .cm-nonmatchingBracket{background:var(--bad-soft)}
.sqled-editor .cm-editor .cm-placeholder{color:var(--muted)}
.sqled-editor .cm-editor .cm-selectionMatch{background:var(--accent-soft)}
.sqled-editor .cm-editor .cm-searchMatch{background:var(--warn-soft);outline:1px solid color-mix(in srgb,var(--warn) 45%,transparent)}
.sqled-editor .cm-editor .cm-searchMatch.cm-searchMatch-selected{background:color-mix(in srgb,var(--warn) 35%,transparent)}
.sqled-editor .cm-editor .cm-tooltip{background:var(--surface);color:var(--text);border:1px solid var(--border-2);border-radius:var(--r-sm);box-shadow:var(--elev-2)}
.sqled-editor .cm-editor .cm-tooltip-autocomplete>ul{font:.8rem/1.5 var(--mono);max-height:16em}
.sqled-editor .cm-editor .cm-tooltip-autocomplete>ul>li{padding:2px 8px}
.sqled-editor .cm-editor .cm-tooltip-autocomplete>ul>li[aria-selected]{background:var(--accent-soft-2);color:var(--text)}
.sqled-editor .cm-editor .cm-completionDetail{margin-left:.9em;font-style:normal;color:var(--muted)}
.sqled-editor .cm-editor .cm-completionMatchedText{text-decoration:none;color:var(--accent);font-weight:600}
/* панель поиска (Ctrl+F): общие input/button/label кабинета растянули бы её
   на всю ширину и залили кнопки акцентом */
.sqled-editor .cm-editor .cm-panels{background:var(--surface-2);color:var(--text);border-color:var(--border)}
.sqled-editor .cm-editor .cm-panel.cm-search{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:6px 30px 6px 8px;font-size:.82rem}
.sqled-editor .cm-editor .cm-panel.cm-search input.cm-textfield{width:auto;min-width:14ch;margin:0;padding:3px 8px;font-size:.82rem}
.sqled-editor .cm-editor .cm-panel.cm-search label{display:inline-flex;align-items:center;gap:4px;margin:0;font-size:.8rem;font-weight:400}
.sqled-editor .cm-editor .cm-panel.cm-search input[type=checkbox]{width:auto;margin:0}
.sqled-editor .cm-editor .cm-panel.cm-search button.cm-button{padding:3px 10px;font-size:.8rem;font-weight:500;background:transparent;background-image:none;color:var(--text-2);border:1px solid var(--border);box-shadow:none}
.sqled-editor .cm-editor .cm-panel.cm-search button.cm-button:hover{color:var(--text);background:var(--surface)}
.sqled-editor .cm-editor .cm-panel.cm-search button[name=close]{position:absolute;top:4px;right:6px;padding:0 6px;background:none;color:var(--muted);box-shadow:none}
/* подсветка SQL: цвета — токены кабинета, обе темы сами */
.sqled-editor .tk-kw{color:var(--accent);font-weight:600}
.sqled-editor .tk-str{color:var(--good)}
.sqled-editor .tk-qid{color:var(--text)}
.sqled-editor .tk-num{color:var(--warn)}
.sqled-editor .tk-com{color:var(--muted);font-style:italic}
.sqled-editor .tk-type{color:var(--accent-2)}
.sqled-editor .tk-fn{color:var(--text);font-weight:500}
.sqled-editor .tk-op{color:var(--text-2)}

/* ═══ Узкий экран ═════════════════════════════════════════════════════════
   Все правила про телефон живут здесь, одним местом: до 05.08.2026 медиа-
   запрос в кабинете был ровно один, спрятанный посреди таблиц, а остальное
   держалось на flex-wrap и clamp() — и на 375px шапка расползалась молча.
   Порогов два, потому что вопроса два: 720px — «влезают ли три зоны шапки
   в одну строку», 640px — «влезает ли моноширинное значение в ячейку». */

@media (max-width:720px){
  /* Контролы под палец: одна высота --ctl-h на телефоне — 40px, а не 34.
     Растут вместе все: поля, кнопки, сегменты, чипы, иконные кнопки, ряд
     выборки и «▶ Выполнить» — формулы выше выводят их из токена */
  :root{--ctl-h:40px}
  /* Шапка в две строки: лого и правый кластер сверху, вкладки — снизу.
     Одной строкой они не живут: лого 97 + .bar-end 233 + гэпы 40 не влезают
     в 339 доступных на 375px, и средняя колонка minmax(0,1fr) честно
     ужималась в НОЛЬ — навигации на телефоне не было вообще, а .bar-end
     вылезал за правый край вместе с «Выйти». */
  .bar{grid-template-columns:auto minmax(0,1fr);grid-template-rows:var(--bar-h) auto;height:auto;gap:0 12px}
  .logo{grid-area:1/1}
  /* правый кластер — в гибкой колонке: длинное имя кабинета не распирает
     шапку */
  .bar-end{grid-area:1/2;justify-self:end;min-width:0}
  /* вкладки во всю ширину нижней строки; подчёркивание активной по-прежнему
     упирается в границу бара, потому что nav и есть низ бара */
  /* Одна строка вкладок (план 2, 5.3; находка № 22): шапка на телефоне —
     56 + 40 = 96px, а не 139 с переносом на вторую строку. Шесть вкладок
     на 375px влезают только во всю ширину экрана: nav выходит за отступы
     страницы (margin-inline на -page-pad), кегль .76rem, шаг 4px — по
     замеру 355px из 375 (У5 mobile-layout: без прокрутки). На более узком
     экране nav прокручивается (общее правило выше). */
  /* С 20.10.2026 разделов четыре, а не шесть: им хватает места и в кегле
     .86rem. Каждая вкладка — равная доля строки, подчёркивание — во всю
     долю: вкладки стоят на своих местах, а не там, куда их сдвинул текст
     соседей. Строку отделяет от лого волосок; высота 41px = 40 вкладки + 1
     волоска, иначе вкладка выступает на 1px и у строки появляется полоса прокрутки */
  header nav{grid-area:2/1/2/3;height:41px;flex-wrap:nowrap;justify-content:space-between;margin-inline:calc(-1 * var(--page-pad));padding-inline:0;border-top:1px solid var(--border);overflow-y:hidden}
  header nav a{flex:1 0 auto;justify-content:center;padding:0 8px;height:40px;font-size:.86rem}
  header nav a.on::after{left:0;right:0}
  /* правый кластер: лого + тема 36 + имя ≤64 + «Выйти» ~38 + шаги по 6 */
  .bar-end{gap:6px}
  /* лого на телефоне — только акцентный квадрат: слово «GoodWink» (97px)
     и так резалось до «Good…», а место нужно имени кабинета */
  .logo{font-size:0;gap:0}
  .bar-end>a.who{max-width:64px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* обрезалось — одна шестерёнка, имя в тултипе (план 3, Э4, № 27; класс ставит cabinet.js) */
  .bar-end>a.who.clip span{display:none}
  .bar-end>a.who.clip{max-width:none}
  /* имя длиннее 64px — многоточие на самом тексте: flex-ребёнок с min-width:auto
     не ужимался и резался краем без многоточия (план 5, 5.4; № 16 пятого прохода) */
  .bar-end>a.who span{min-width:0;overflow:hidden;text-overflow:ellipsis}
  /* действия экрана — слева, под заголовком: у правого края в переносе они
     висели бы отдельно от него */
  .pagehead>h1+*{margin-left:0}
  /* якорь карточки не прячется под шапкой: на телефоне она в две строки */
  .card[id]{scroll-margin-top:calc(var(--bar-h) + 52px)}
  /* строка ресурса на телефоне: числа под названием, действия ниже (№ 18) */
  .rowcard.rrow{grid-template-columns:minmax(0,1fr)}
  .rc-stats{justify-content:flex-start}
  .rc-stats>span{align-items:flex-start;min-width:0}
  /* строки «Источников», вебхуки, ключи API: кнопки действий под
     текстом (одна колонка сетки), а не поверх него в узкой второй */
  .rowcard{grid-template-columns:minmax(0,1fr)}
  .rowcard .rc-actions{justify-content:flex-start;flex-wrap:wrap}
  /* меню «…» строки: действия здесь слева, а список привязан к правому краю
     «…» — у источника без таблицы «…» стоит второй кнопкой, и список уходил
     за левый край экрана (Э9: на 111px). На телефоне список — под рядом
     действий во всю его ширину: на экране, где бы ни стояла «…» */
  .rowcard .rc-actions{position:relative}
  .rowcard .rc-actions>.menu{position:static}
  .rowcard .rc-actions .menu-list{left:0;right:0;min-width:0}

  /* kv-таблица (параметры API, журналы опроса и доставок) — парами в столбик:
     первый столбец nowrap+width:1%, и на узком она забирала себе строку, а
     текст ответа сжимался в столбик шириной в слово. Обёртка .overflow не
     спасала — таблица предпочитала сжаться, а не прокрутиться. */
  .kv,.kv tbody,.kv tr,.kv td{display:block;width:auto}
  .kv td{border-bottom:none;padding:2px 0}
  .kv td:first-child{white-space:normal;width:auto}
  .kv tr{border-bottom:1px solid var(--border);padding:7px 0}
  .kv tr:last-child{border-bottom:none}

  /* SQL-редактор — столбиком: дерево сверху со своей прокруткой, редактор и
     результат по высоте экрана, прокручивается страница. Тянуть границу
     пальцем по редактору — не жест телефона, её нет */
  main.sqlpage{height:auto}
  .sqled{grid-template-columns:minmax(0,1fr)}
  .sqled-tree{max-height:34vh;border-right:none;border-bottom:1px solid var(--border)}
  .sqled-editor{flex:none;height:40vh}
  .sqled-split{display:none}
  .sqled-result{flex:none;min-height:40vh}
}

/* длинное моноширинное значение в ячейке — многоточием, иначе один столбец
   растягивает таблицу на телефоне */
/* уже 400px — имени в шапке нет вовсе, только шестерёнка; полное имя в тултипе и
   aria-label ставит cabinet.js (план 5, 5.4): тема и «Выйти» занимают
   правый кластер */
@media (max-width:399px){
  .bar-end>a.who span{display:none}
  .bar-end>a.who{max-width:none}
}
@media (max-width:640px){
  /* селект с длинной подписью (настройки CSV) — во всю ширину, не за край (план 8, 1.5) */
  .inline>label{width:100%}
  .inline select{width:100%;min-width:0}
  td .mono{max-width:150px;display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}

/* ── Экран таблицы и каталог (Э5.4 плана пересмотра):
   data/templates/{table,catalog,row,row_part}.html, клей — data/static/table.js.
   Таблица — на стилях table.records (липкая шапка, строки по три, первая
   столбец закреплён); выборка — панели над ней, на телефоне — в поток. */
.msg.warn{background:var(--warn-soft);color:var(--text);border-color:color-mix(in srgb,var(--warn) 35%,transparent)}
.selform .toolbar{align-items:flex-start}
.sel-q{width:min(320px,100%)}
.selform .toolbar>input,.selform .toolbar>select{height:var(--ctl-h);box-sizing:border-box;padding-top:0;padding-bottom:0}
/* Панель выборки открывается под рядом от его левого края, а не под своей
   кнопкой: на узком десктопе панель уходила за правый край и давала
   странице прокрутку вбок («Фильтры» на 721px — +146px). Ряд — точка
   отсчёта, ширина панели — не больше ряда */
.selform .toolbar{position:relative}
.sel-panel{position:static}
.sel-panel>summary{list-style:none;height:var(--ctl-h);box-sizing:border-box;padding:0 13px;font-size:.86rem}
.sel-panel>summary::-webkit-details-marker{display:none}
.sel-panel[open]>summary{border-color:var(--accent);color:var(--text)}
.sel-box{position:absolute;z-index:25;top:calc(100% + 6px);left:0;width:max-content;min-width:min(420px,100%);max-width:min(640px,100%);background:var(--surface);border:1px solid var(--border-2);border-radius:var(--r-md);box-shadow:var(--elev-2);padding:12px;display:flex;flex-direction:column;gap:8px}
.sel-box .checklist{max-height:260px}
.filter-row{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.filter-row select{width:auto;max-width:220px}
.filter-row input[type=text]{width:auto;flex:1 1 140px;min-width:0}
/* компактные — на 6px ниже ряда, от того же токена: на телефоне растут вместе с ним */
.iconbtn.sm{width:calc(var(--ctl-h) - 6px);height:calc(var(--ctl-h) - 6px)}
button.sm,.btn.sm{padding:calc((var(--ctl-h) - 28px) / 2) 10px;font-size:.82rem}
.sel-size{width:auto}
.sel-said{margin:-6px 0 12px}
.seltools{margin:0 0 10px}
.seltools [data-role=selcount]{font-size:.88rem}
button.linklike{background:none;border:none;box-shadow:none;padding:0;color:var(--accent);font:inherit;font-weight:500;text-decoration:underline;text-underline-offset:3px}
button.linklike:hover:not(.ghost){background:none}
button.ghost.danger{color:var(--bad);border-color:color-mix(in srgb,var(--bad) 40%,var(--border))}
button.ghost.danger:hover{background:var(--bad-soft);color:var(--bad);border-color:var(--bad)}
.tablewrap.grid-wrap{max-height:calc(100vh - 230px)}
/* Заголовок столбца — имя в базе, поэтому моноширинным, как в окне строки и
   в результате SQL-редактора; кегль .8rem и --text-2 вместо .76rem и --muted:
   это главный ориентир таблицы на десятки столбцов */
table.records.grid thead th{font-size:.8rem;letter-spacing:0;color:var(--text-2)}
table.records.grid th .th-sub{display:block;max-width:220px;overflow:hidden;text-overflow:ellipsis;font-weight:400;font-size:.72rem;letter-spacing:0;color:var(--muted)}
table.records.grid th a.sorter{color:inherit;text-decoration:none;font-family:var(--mono);font-weight:500}
table.records.grid th a.sorter:hover{color:var(--text)}
table.records.grid th .rs{position:absolute;top:0;right:-3px;width:7px;height:100%;cursor:col-resize;z-index:4}
/* у последнего столбца ручка не выступает за таблицу: 3px за краем давали
   коробке таблицы постоянную полосу прокрутки вбок */
table.records.grid th:last-child .rs{right:0}
/* Отмеченная строка видна и без взгляда на флажок — подложка акцента на всю
   строку; у закреплённой первой ячейки та же подложка, но непрозрачная:
   под ней прокручиваются остальные столбцы */
table.records.grid tbody tr:has(input.sel:checked) td{background-color:var(--accent-soft)}
.tablewrap table.records.grid tbody tr:has(input.sel:checked) td:first-child{background-color:color-mix(in srgb,var(--accent) 13%,var(--surface))}
table.records.grid th .rs:hover{background:var(--accent-soft)}
table.records.grid td[tabindex]:focus{outline:2px solid var(--accent);outline-offset:-2px}
table.records.grid td.selcell,table.records.grid th.selcell{width:1%;padding-right:4px}
table.records.grid button.cell.struct{height:auto;box-shadow:none;font-weight:400;cursor:pointer}
table.records.grid button.cell.struct:hover:not(.ghost){background:var(--surface-2);color:var(--text);border-color:var(--accent)}
table.records.grid .cell.long{cursor:pointer}
table.records.grid a.rowlink{font-variant-numeric:tabular-nums}
.pager{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:12px 0 16px}
/* Каталог — список внутри карточки: строки разделены волоском, как строки
   «Источников», а не рамкой у каждой (рамка в рамке читалась как отдельные
   карточки). Имя и пилюля — одной строкой, мета и «N столбцов» — под ними */
.catalog{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column}
.catalog>li{display:flex;flex-wrap:wrap;align-items:center;gap:3px 10px;padding:11px 0;border-top:1px solid var(--border);min-width:0}
.catalog>li:last-child{padding-bottom:0}
.catalog>li>.muted,.catalog>li>details{flex-basis:100%;min-width:0}
.catalog>li>.muted{overflow-wrap:anywhere}
.catalog-name{font-weight:600}
.cols-info>summary{cursor:pointer;color:var(--text-2);font-size:.86rem}
.cols-info[open]>summary{margin-bottom:6px}
.cols-info.about{margin:4px 0 14px}
.danger-zone>summary{color:var(--bad)}
dialog.rowdlg{max-width:min(860px,94vw)}
dialog.rowdlg .dlg-scroll{padding:14px 18px 18px}
dialog.rowdlg .dlg-h .inline,dialog.structdlg .dlg-h .inline{margin:0 0 0 auto}
table.rowvals{width:100%}
table.rowvals th{width:30%;text-align:left;vertical-align:top;font-weight:400}
table.rowvals th .th-sub{display:block;font-size:.78rem;color:var(--muted)}
table.fields.rowvals td+td,table.fields.rowvals td,table.fields.reqmeta td{text-align:left;width:auto;white-space:normal}
.rowval{white-space:pre-wrap;overflow-wrap:anywhere}
.row-h{margin:18px 0 6px;font-size:1rem}
pre.reqbody{max-height:320px;white-space:pre-wrap;overflow-wrap:anywhere}
.row-actions{margin-top:14px}
@media (max-width:720px){
  /* выборка — в поток страницы: всплывающая панель шире экрана телефона */
  .sel-box{position:static;width:auto;min-width:0;max-width:100%;box-shadow:none;margin-top:6px}
  .sel-panel[open]{flex-basis:100%}
  .sel-q{width:100%}
  .tablewrap.grid-wrap{max-height:70vh}
  table.rowvals th{width:40%}
  /* шапка окна строки: заголовок и «×» — первой строкой, «Скопировать
     строку» — второй. Одной строкой они не помещаются, и ряд кнопок
     переносил «×» под «Скопировать» (Э9). Обёртка кнопок раскрыта в шапку,
     перенос строки после «×» — псевдоэлементом во всю ширину */
  dialog.rowdlg .dlg-h{flex-wrap:wrap;align-items:center;row-gap:0}
  dialog.rowdlg .dlg-h>b{flex:1 1 0;min-width:0}
  dialog.rowdlg .dlg-h .inline{display:contents}
  dialog.rowdlg .dlg-h::after{content:"";flex-basis:100%;order:1}
  dialog.rowdlg .dlg-h .inline>:not(.iconbtn){order:2;margin-top:10px}
}
