@charset "UTF-8";
/* SP-1-D-8 §6.1: иконки-эмодзи в content (📁 у папок, ⛓ у отражений) читаются как UTF-8 при любой
   кодировке. Двухслойная защита: charset-заголовок статики (Program.cs) + это правило как страховка.
   Эмодзи намеренно литералами, а не \u-escape — ради наглядности. #SP-1-D-8 */
.tags-tree {
    position: relative;
    display: flex;
    flex-direction: row;
    align-items: stretch;
    gap: var(--gap-tree-columns);
    overflow-x: auto;
    /*
    border: var(--border-width) solid var(--border-tree);
    border-radius: var(--border-radius-container);
    padding: var(--padding-tree);
    */
    
    /* Сверху резервируем поле под плавающую mode-полосу — иначе она перекрыла бы верх колонок. */
    padding-top: var(--padding-tree-top);
    min-height: var(--min-height-tree);
}

/* Нижняя граница области article (с деревом) «упирается» в низ окна и следует за ним при
   ресайзе. Реализовано flex-цепочкой от body до .tags-tree на ФИКСИРОВАННУЮ высоту вьюпорта
   (height:100dvh, а не min-height — иначе контент распирал бы страницу выше окна). Промежуточные
   звенья — flex:1 1 auto; min-height:0, чтобы дерево получило конечную высоту, а колонки внутри
   скроллились самостоятельно при нехватке высоты. Без JS, ресайз обрабатывает браузер нативно.
   Правила действуют только на странице дерева: tree.css подключается лишь в Tree/Index. */
body {
    display: flex;
    flex-direction: column;
    height: 100dvh;
}

body > .container {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    /* Адаптивная ширина области дерева (#SP-2-D-1 «Ширина области дерева»): снимаем фиксированный
       потолок bootstrap-контейнера и растим область ПО СОДЕРЖИМОМУ — мало колонок → область держит
       БАЗОВУЮ ширину (--min-width-tree-area, ширина не дёргается при переходах), глубже → растёт
       вплоть до всей ширины окна, дальше колонки скроллятся внутри .tags-tree (overflow-x:auto).
       fit-content = clamp(базовая, сумма ширин колонок, окно). min-width клампится до 100% — иначе
       на узких экранах база распёрла бы страницу. Спейсер .tags-tree::after (flex 0 0 100%) на
       intrinsic-размер не влияет (процентный базис → 0). */
    width: fit-content;
    /* Флор по вьюпорту (100vw, не 100%): процент у флекс-итема резолвится ненадёжно (может дать 0),
       тогда флор не срабатывает и при малом числе колонок область прижимается к содержимому, а
       строка поиска (width: 100% контейнера) скачет/сужается. 100vw всегда определён → область
       гарантированно держит базовую ширину, пока окно её вмещает. */
    min-width: min(var(--min-width-tree-area), 100vw);
    max-width: 100%;
    margin-inline: auto;
    /* Убираем горизонтальный gutter-padding bootstrap-контейнера: при max-ширине JS даёт дереву
       min-width = вся ширина окна, и padding контейнера добавлялся бы сверху → дерево вылезало за
       правый край окна, а слева оставался «лишний» отступ (горизонтальный скролл всей страницы).
       Дерево само имеет внутренний padding (--padding-tree) и должно доходить до краёв окна. */
    padding-inline: 0;
}

.container > main {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    /* Без нижнего отступа: нижняя граница article упирается ровно в низ окна. */
    padding-bottom: 0;
}

main > article {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Все элементы над деревом (плашки-баннеры, edit/admin-bar, панель операций драфта, поиск)
   держат естественную высоту и НЕ сжимаются: иначе при высоком дереве flexbox отнимал высоту
   у них. Особенно у .tree-ops-panel — это scroll-контейнер (overflow-y:auto), в flex-колонке
   его min-height резолвится в 0, и он схлопывался в ноль. Сжиматься должно только дерево. */
main > article > * {
    flex: 0 0 auto;
}

main > article > .tags-tree {
    flex: 1 1 auto;
    /* Конечная высота от flex-цепочки; min-height:0 разрешает дереву сжаться под окно,
       чтобы при нехватке высоты скроллились колонки, а не вся страница. */
    min-height: 0;
}

/* SP-2-D-6: строка поиска над деревом — на всю ширину контейнера дерева, с увеличенным шрифтом. */
.tree-search {
    display: block;
    /* Ширина строки поиска не зависит от глубины навигации (#SP-2-D-1): считаем от ВЬЮПОРТА
       (100vw), а не от контейнера (100%) — иначе ширина строки тянулась за растущей/сжимающейся
       областью. 100vw → строка всегда базовой ширины (клампится до окна), сколько бы колонок ни
       раскрыли. margin-inline:auto центрирует её внутри контейнера; контейнер центрирован
       относительно центра окна → строка стоит на центре окна и НЕ смещается и НЕ меняет ширину. */
    width: min(var(--min-width-tree-area), 100vw);
    margin-inline: auto;
    box-sizing: border-box;
    padding: var(--padding-tree-search-y) var(--padding-tree-search-x);
    margin-bottom: var(--margin-tree-search-bottom);
    font-size: var(--font-size-tree-search);
    border: var(--border-width) solid var(--border-tree);
    border-radius: var(--border-radius);
    background: var(--background-page);
}

/* Узлы, не входящие в результат поиска (current'а subtree, в котором нет совпадений), приглушаются. */
.tags-tree__node.is-search-dimmed {
    opacity: var(--opacity-search-dimmed);
}

/* Спейсер шириной с viewport справа от последней колонки: при переходе вверх по дереву
   (особенно через несколько уровней) клик удаляет правые колонки, контент сжимается,
   браузер клампит scrollLeft, и колонка с кликнутым узлом «уезжает» из viewport'а.
   Спейсер удерживает scrollWidth, scrollLeft сохраняется, кликнутая колонка остаётся
   на своём месте, а справа появляется пустое пространство. */
.tags-tree::after {
    content: '';
    flex: 0 0 100%;
    pointer-events: none;
}

.tags-tree__column {
    /* Ширина по контенту: потолок --width-tree-column, пол --min-width-tree-column.
       На узких экранах колонки с коротким текстом сужаются (#SP-2-D-1 § «Ширина колонок»). */
    flex: 0 0 auto;
    width: max-content;
    max-width: var(--width-tree-column);
    min-width: var(--min-width-tree-column);
    display: flex;
    flex-direction: column;
    gap: var(--gap-tree-nodes);
    background: var(--background-tree);
    /* Рамка через inset box-shadow, а НЕ border — намеренно. При глобальном box-sizing:border-box
       (из Bootstrap) border входит в 240px потолка колонки → content-box колонки = 240 − 2×рамка = 236px.
       Растянутый узел обычной колонки (дефолтный align-items:stretch) получал эти 236px и терял ~4px под
       текст, тогда как в колонке с историей (align-items:flex-start, max-width:none) узел брал свою полную
       max-width 240px. Из-за этих 4px один и тот же тег то влезал в строку, то переносился — в зависимости
       от наличия истории. box-shadow не входит в поток → content-box колонки = ровно 240px, растянутый узел
       получает те же 240px, что и узел в истории → перенос одинаков в обоих режимах, а привычный вид обычного
       дерева (узлы-блоки на всю ширину колонки) сохраняется. #SP-2-D-8-history-lines, #SP-2-D-5 */
    box-shadow: inset 0 0 0 var(--border-width) var(--border-column);
    border-radius: var(--border-radius);
    overflow-y: auto;
    /* Колонки растягиваются на всю высоту дерева (align-items: stretch), а внутренний
       контент скроллится вертикально. Раньше был потолок 70vh — теперь колонка следует
       за высотой дерева, прижатого к низу окна. */
    max-height: 100%;

    
}

/* SP-2-D-8: колонка детей текущего узла с линиями истории — не ограничиваем ширину
   (длинная линия скроллится по горизонтали вместе с деревом) и не растягиваем узлы
   на всю ширину (иначе короткий узел занял бы ширину самой длинной линии).
   #SP-2-D-8-history-lines § «Рендер», #SP-8-US-11-1/AC7 */
.tags-tree__column--history {
    max-width: none;
    align-items: flex-start;
}

/* Строка-контейнер: узел + его линия истории в один горизонтальный ряд,
   линия выровнена по центру по высоте относительно узла. */
.tags-tree__row {
    display: flex;
    align-items: center;
    gap: var(--gap-history-line);
}

.tags-tree__row .tags-tree__node {
    flex: 0 0 auto;
}

/* Сама линия — чипы-узлы, разделённые ›; не переносится (горизонтальный скролл дерева).
   user-select: none — линия навигационная, а не контентная: при выделении колонки
   потомков (чтобы скопировать имена) чипы истории в выделение/копирование не попадают.
   Узел и линия остаются в одном ряду → высота линии всегда равна высоте узла.
   #SP-2-D-8-history-lines § «Рендер», #SP-8-US-11-1 (замечание: выделение потомков) */
.tags-tree__history-line {
    display: flex;
    align-items: center;
    gap: var(--gap-history-node);
    flex-wrap: nowrap;
    white-space: nowrap;
    font-size: var(--font-size-history-node);
    user-select: none;
}

.tags-tree__history-sep {
    color: var(--color-history-sep);
}

/* Первый разделитель (перед первым чипом, сразу после имени узла) не нужен. */
.tags-tree__history-line .tags-tree__history-sep:first-child {
    display: none;
}

.tags-tree__history-node {
    padding: var(--padding-history-node-y) var(--padding-history-node-x);
    border-radius: var(--border-radius);
    color: var(--color-history-node);
    font-size: var(--font-size-history-node);
    text-decoration: none;
    white-space: nowrap;
    -webkit-user-drag: none;
}

.tags-tree__history-node:hover,
.tags-tree__history-node:focus {
    background: var(--background-history-node-hover);
    color: var(--color-history-node);
    text-decoration: none;
}

.tags-tree__node {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    /* Перенос имени узла НЕ должен зависеть от того, показаны ли у колонки линии истории.
       Колонка с историей (--history) теряет потолок 15rem и не растягивает узлы (align:flex-start),
       из-за чего длинный узел переставал переноситься (был в 2 строки → стал в 1) и высота строки
       менялась → при «Влево/Вправо» контент колонки прыгал по вертикали. Собственный max-width у
       узла фиксирует точку переноса (15rem) в любом режиме колонки → высоты строк стабильны, скролл
       не убегает. Линия истории при этом «торчит» правее узла (колонка --history это позволяет).
       #SP-2-D-8-history-lines, #SP-2-D-5 */
    max-width: var(--width-tree-column);
    padding: var(--padding-node-y) var(--padding-node-x);
    background: transparent;
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    cursor: pointer;
    text-align: left;
    font-size: var(--font-size-node);
    color: inherit;
    text-decoration: none;
    /* SP-2-D-8: ссылка-узел не перетаскивается — иначе drag по тексту запускал бы
       перетаскивание ссылки вместо выделения текста (отмена dragstart постфактум
       выделению не помогает). #SP-8-US-11-1 (замечание: drag-n-drop) */
    -webkit-user-drag: none;
}

/* SP-2-D-5: цель перехода «Вправо» — последний посещённый ребёнок в колонке детей текущего узла.
   Еле заметный фон-подсказка. Размещено ДО :hover/is-expanded/is-current (равная специфичность) —
   чтобы hover и выделение пути перебивали эту подсветку (она самая слабая в иерархии фонов). */
.tags-tree__node.is-last-visited {
    background: var(--background-tree-node-last-visited);
}

.tags-tree__node:hover,
.tags-tree__node:focus {
    text-decoration: none;
    color: inherit;
}

/* Если узел уже визуально отмечен (is-current / is-expanded), подавляем браузерный
   focus-outline — иначе при keyboard-навигации (arrow → $node.focus()) поверх
   рамки is-current рисуется ещё одна. Для «голого» фокуса (без is-current/is-expanded)
   default outline остаётся — требование a11y из SP-2-D-0 / SP-2-D-2. */
.tags-tree__node.is-current:focus,
.tags-tree__node.is-expanded:focus {
    outline: none;
}

.tags-tree__node:hover {
    background: var(--background-hovered-no-active);
}

.tags-tree__node.is-expanded {
    background: var(--background-active);
    border-color: var(--border-active);
}

.tags-tree__node.is-draft-added.is-expanded {
    border-color: var(--border-active);
}

.tags-tree__node.is-current  {
    background: var(--background-active-special);
    border-color: var(--border-active-special);
}

.tags-tree__node.is-expanded:hover,
.tags-tree__node.is-current:hover {
    background: var(--background-active-hovered);
}

.tags-tree__node.is-current {
    font-weight: var(--font-weight-current);
}

/* Стрелка-индикатор «есть дети» — через ::after по data-has-children, без span в DOM (легче дерево
   на горячем пути чтения). Декоративная (не копируется, не в a11y-дереве). #SP-2-D-1 § «Отображение» */
.tags-tree__node[data-has-children="true"]::after {
    content: '›';
    color: var(--color-text-muted);
    margin-left: var(--margin-arrow-left);
    user-select: none;
}

/* SP-1-D-6: бейдж типа тега — приглушённая метка после текста узла (различает тёзок). */
.tags-tree__node-type {
    margin-left: var(--margin-node-type-left);
    padding: var(--padding-node-type-y) var(--padding-node-type-x);
    background: var(--background-node-type);
    color: var(--color-node-type);
    font-size: var(--font-size-node-type);
    border-radius: var(--border-radius);
    user-select: none;
}

.tags-tree__empty {
    padding: var(--padding-empty-y) var(--padding-empty-x);
    color: var(--color-text-muted);
    font-style: italic;
    font-size: var(--font-size-empty);
}

/* Визуальная пометка отражения: ⛓ вместо стрелки ">" справа от текста. Тот же ::after, что и стрелка;
   правило идёт ПОЗЖЕ при равной специфичности → у отражения с детьми перебивает '›'. У отражения без
   детей data-has-children=false, но это правило всё равно ставит ⛓. #SP-1-D-8 §6.1 (charset) */
.tags-tree__node.is-mirror::after {
    content: '⛓'; /* эмодзи-литерал; кодировка гарантируется charset — см. SP-1-D-8 §6.1 */
    margin-left: var(--margin-arrow-left);
    color: var(--color-mirror-marker);
    font-size: var(--font-size-mirror-marker);
    user-select: none;
}

/* SP-1-D-8: узел-Папка — более скруглённые углы (контейнер) + иконка 📁 перед текстом.
   Иконка через ::before текст-спана (декоративная, не копируется). #SP-1-D-8-node-type */
.tags-tree__node.is-folder {
    border-radius: var(--border-radius-folder);
}

.tags-tree__node.is-folder .tags-tree__node-text::before {
    content: '📁'; /* эмодзи-литерал; кодировка гарантируется charset — см. SP-1-D-8 §6.1 */
    margin-right: var(--margin-folder-marker-right);
    font-size: var(--font-size-folder-marker);
    user-select: none;
}

.tags-tree__node.is-taken {
    opacity: var(--opacity-taken);
    border-style: var(--border-style-taken);
}

/* Узел в буфере, но временно деактивирован — пунктир без снижения прозрачности,
   чтобы пользователь видел, что узел в буфере, но не уйдёт по Place. */
.tags-tree__node.is-taken-inactive {
    border-style: var(--border-style-buffer-chip-inactive);
}

.tags-tree__node.is-deleted-draft .tags-tree__node-text {
    text-decoration: line-through;
    color: var(--color-deleted-draft);
}

.tags-tree__node.is-draft-added {
    background: var(--background-tag-draft-added);
    border-color: var(--border-tag-draft-added);
}

.tags-tree__node.is-draft-added:hover {
    background: var(--background-tag-draft-added-hovered);
}

.tags-tree__node.is-draft-added.is-current {
    border-color: var(--border-active);
}

/* --- Inline-редактор имени тега (<input> внутри text-span, TODO-11) --- */

.tags-tree__node.is-tag-editing {
    cursor: text;
}

.tags-tree__node-edit {
    font: inherit;
    color: inherit;
    width: var(--width-tag-edit-input);
    outline: none;
    cursor: text;
    background: var(--background-tag-draft-added);
    padding: 0 var(--padding-tag-edit-x);
    border: none;
    border-radius: var(--border-radius);
}

/* Тег переименован в драфте (op EditTag) — курсив (TODO-11, SP-2-D-4-1) */
.tags-tree__node.is-tag-edited .tags-tree__node-text {
    font-style: italic;
}

/* --- Плавающая кнопка «Редактировать» в углу --- */

.tree-edit-toggle {
    position: fixed;
    top: var(--position-edit-toggle-top);
    right: var(--position-edit-toggle-right);
    z-index: var(--z-index-edit-toggle);
    padding: var(--padding-button-y) var(--padding-button-x);
    background: var(--background-button-primary);
    color: var(--color-button-primary);
    border: var(--border-width) solid var(--background-button-primary);
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-button);
}

.tree-edit-toggle:hover {
    background: var(--background-button-primary-hover);
    border-color: var(--background-button-primary-hover);
}

body.is-edit-mode .tree-edit-toggle {
    display: none;
}

/* --- Edit-bar (полоса режима редактирования) --- */

.tree-edit-bar {
    display: none;
    position: sticky;
    top: 0;
    z-index: var(--z-index-edit-bar);
    align-items: center;
    gap: var(--gap-edit-bar);
    padding: var(--padding-edit-bar-y) var(--padding-edit-bar-x);
    background: var(--background-edit-bar);
    border-bottom: var(--border-width) solid var(--border-edit-bar);
    font-size: var(--font-size-button);
}

body.is-edit-mode .tree-edit-bar {
    display: flex;
    flex-wrap: wrap;
}

.tree-edit-bar__spacer {
    flex: 1 1 auto;
}

.tree-edit-bar__btn {
    padding: var(--padding-button-y) var(--padding-button-x);
    background: var(--background-button);
    border: var(--border-width) solid var(--border-button);
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-button);
}

.tree-edit-bar__btn:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--background-button-hover);
}

/* :disabled — транзиентный AJAX-дизейбл; [aria-disabled] — state-дизейбл (правило 7). */
.tree-edit-bar__btn:disabled,
.tree-edit-bar__btn[aria-disabled="true"] {
    opacity: var(--opacity-button-disabled);
    cursor: var(--cursor-button-disabled);
}

.tree-edit-bar__btn.is-primary {
    background: var(--background-button-primary);
    color: var(--color-button-primary);
    border-color: var(--background-button-primary);
}

.tree-edit-bar__btn.is-primary:hover {
    background: var(--background-button-primary-hover);
    border-color: var(--background-button-primary-hover);
}

.tree-edit-bar__btn.is-danger {
    background: var(--background-button-danger);
    color: var(--color-button-danger);
    border-color: var(--background-button-danger);
}

.tree-edit-bar__btn.is-danger:hover {
    background: var(--background-button-danger-hover);
    border-color: var(--background-button-danger-hover);
}

.tree-edit-bar__btn.is-hidden,
.tree-edit-bar__readonly-notice.is-hidden {
    display: none;
}

.tree-edit-bar__changes {
    cursor: pointer;
    user-select: none;
    text-decoration: underline dashed;
    text-underline-offset: 0.2rem;
}

.tree-edit-bar__changes:hover {
    text-decoration: underline;
}

.tree-edit-bar__readonly-notice {
    color: var(--color-edit-bar-readonly-notice);
    font-size: var(--font-size-edit-bar-readonly-notice);
    font-style: italic;
}

/* --- Ops-panel (панель списка операций драфта) --- */

.tree-ops-panel {
    display: none;
    flex-direction: column;
    max-height: var(--max-height-ops-panel);
    overflow-y: auto;
    padding: var(--padding-ops-panel-y) var(--padding-ops-panel-x);
    background: var(--background-ops-panel);
    border-bottom: var(--border-width) solid var(--border-ops-panel);
    font-size: var(--font-size-ops-panel);
}

.tree-ops-panel.is-open {
    display: flex;
}

/* SP-2-D-10: инспектор узла («?» в тулбаре) — КОЛОНКА справа в потоке дерева (как колонка
   детей / панель «Связи»). Ширину/рамку/скролл даёт .tags-tree__column; здесь — внутреннее
   оформление. Не модалка (правило 1 SP-2-D-5). #SP-2-D-10-node-inspector */
.tree-node-info-panel {
    /* Потолок ширины вычисляется в JS (nodeInspector.applyPanelMaxWidth): ширина области дерева
       минус ширина тулбара — чтобы и легенда, и тулбар всегда влезали на экран. Здесь не задаём
       max-width — до JS работает потолок обычной колонки (--width-tree-column) как фолбэк, инлайн
       из JS его перекрывает. Длинный путь переносится на несколько строк. #SP-2-D-10-node-inspector */
    gap: var(--gap-node-info-panel);
    padding: var(--padding-node-info-panel-y) var(--padding-node-info-panel-x);
    background: var(--background-node-info-panel);
    font-size: var(--font-size-node-info-panel);
}

.tree-node-info-panel__title {
    display: flex;
    align-items: baseline;
}

.tree-node-info-panel__name {
    font-size: var(--font-size-node-info-name);
    font-weight: var(--font-weight-current);
}

.tree-node-info-panel__type {
    margin-left: var(--margin-node-info-type-left);
    color: var(--color-node-info-type);
}

.tree-node-info-panel__close {
    margin-left: auto;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--color-node-info-close);
    font-size: var(--font-size-node-info-close);
    line-height: 1;
}

.tree-node-info-panel__close:hover {
    color: var(--color-node-info-close-hover);
}

.tree-node-info-panel__section {
    display: flex;
    flex-direction: column;
    gap: var(--gap-node-info-section);
}

.tree-node-info-panel__section-label {
    color: var(--color-node-info-label);
}

.tree-node-info-panel__path {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--gap-node-info-path);
}

.tree-node-info-panel__path-item {
    white-space: nowrap;
    color: var(--color-node-info-link);
    text-decoration: underline;
}

.tree-node-info-panel__path-item:hover {
    color: var(--color-node-info-link-hover);
}

.tree-node-info-panel__path-sep {
    color: var(--color-node-info-path-sep);
    user-select: none;
}

.tree-node-info-panel__states {
    display: flex;
    flex-direction: column;
    gap: var(--gap-node-info-states);
}

.tree-node-info-panel__state-link {
    margin-left: var(--gap-node-info-path);
    color: var(--color-node-info-link);
    text-decoration: underline;
}

.tree-node-info-panel__state-link:hover {
    color: var(--color-node-info-link-hover);
}

.tree-ops-panel__item {
    display: flex;
    align-items: center;
    gap: var(--gap-ops-panel-item);
    padding: var(--padding-ops-panel-y) 0;
}

.tree-ops-panel__item-text {
    flex: 1 1 auto;
}

.tree-ops-panel__item-link {
    color: var(--color-ops-panel-link);
    text-decoration: underline;
}

.tree-ops-panel__item-link:hover {
    color: var(--color-ops-panel-link-hover);
}

.tree-ops-panel__item-remove {
    flex: 0 0 auto;
    background: none;
    border: none;
    color: var(--color-ops-panel-remove);
    cursor: pointer;
    font-size: var(--font-size-ops-panel);
    padding: 0 0.25rem;
    line-height: 1;
}

.tree-ops-panel__item-remove:hover {
    color: var(--color-ops-panel-remove-hover);
}

.tree-ops-panel__item-restore {
    flex: 0 0 auto;
    background: none;
    border: none;
    color: var(--color-ops-panel-restore);
    cursor: pointer;
    font-size: var(--font-size-ops-panel);
    padding: 0 0.25rem;
    line-height: 1;
}

.tree-ops-panel__item-restore:hover {
    color: var(--color-ops-panel-restore-hover);
}

.tree-ops-panel__item.is-removed-op .tree-ops-panel__item-text {
    text-decoration: line-through;
    color: var(--color-ops-panel-removed);
    opacity: var(--opacity-ops-panel-removed);
}

.tree-ops-panel__item.is-cascade-op .tree-ops-panel__item-text {
    font-style: italic;
}

.tree-ops-panel__item.is-conflict-op {
    background: var(--background-ops-panel-conflict);
    margin: 0 calc(-1 * var(--padding-ops-panel-x));
    padding-left: var(--padding-ops-panel-x);
    padding-right: var(--padding-ops-panel-x);
}

.tree-ops-panel__item-conflict {
    display: block;
    font-size: 0.8em;
    color: var(--color-ops-panel-conflict);
    margin-top: 0.125rem;
}

/* SP-11-D-4: «погашенный» конфликт — фон тише, текст «⚠ конфликт» остаётся для контекста. */
.tree-ops-panel__item.is-ignored-conflict-op {
    background: var(--background-ops-panel-ignored-conflict);
    margin: 0 calc(-1 * var(--padding-ops-panel-x));
    padding-left: var(--padding-ops-panel-x);
    padding-right: var(--padding-ops-panel-x);
}

.tree-ops-panel__item-toggle-ignore {
    flex: 0 0 auto;
    background: none;
    border: 1px solid var(--color-ops-panel-toggle-ignore);
    color: var(--color-ops-panel-toggle-ignore);
    cursor: pointer;
    font-size: var(--font-size-ops-panel-toggle-ignore);
    padding: var(--padding-ops-panel-toggle-ignore-y) var(--padding-ops-panel-toggle-ignore-x);
    line-height: 1;
    border-radius: var(--border-radius-button);
}

.tree-ops-panel__item-toggle-ignore:hover {
    color: var(--color-ops-panel-toggle-ignore-hover);
    border-color: var(--color-ops-panel-toggle-ignore-hover);
}

.tree-ops-panel__item.is-cancelled-op {
    background: var(--background-ops-panel-cancelled);
    margin: 0 calc(-1 * var(--padding-ops-panel-x));
    padding-left: var(--padding-ops-panel-x);
    padding-right: var(--padding-ops-panel-x);
}

.tree-ops-panel__item.is-cancelled-op .tree-ops-panel__item-text {
    text-decoration: line-through;
    color: var(--color-ops-panel-cancelled-text);
}

.tree-ops-panel__item-toggle-cancel {
    background: none;
    border: 1px solid var(--color-ops-panel-toggle-cancel);
    color: var(--color-ops-panel-toggle-cancel);
    cursor: pointer;
    font-size: var(--font-size-ops-panel-toggle-cancel);
    padding: var(--padding-ops-panel-toggle-cancel-y) var(--padding-ops-panel-toggle-cancel-x);
    border-radius: var(--border-radius-button);
}

.tree-ops-panel__item-toggle-cancel:hover {
    color: var(--color-ops-panel-toggle-cancel-hover);
    border-color: var(--color-ops-panel-toggle-cancel-hover);
}

.tree-ops-panel__empty {
    color: var(--color-secondary);
    padding: var(--padding-ops-panel-y) 0;
}

/* --- Mode-полоса: плавающая горизонтальная полоса (Дерево/Связи/Группы) над текущей колонкой --- */
/* Живёт в .tags-tree (position: relative), а не в колонке: overflow колонки обрезал бы её сверху.
   left выставляется в JS по offsetLeft текущей колонки (toolbar.ts → positionModeBar). */

.tree-mode-bar {
    position: absolute;
    top: var(--padding-tree);
    z-index: var(--z-index-mode-bar);
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--gap-toolbar);
    padding: var(--padding-toolbar-y) var(--padding-toolbar-x);
    background: var(--background-toolbar);
    border: var(--border-width) solid var(--border-toolbar);
    border-radius: var(--border-radius);
}

/* --- Edit-бар: вертикальный разделитель между колонками (только edit-действия) --- */

.tree-toolbar {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    align-items: stretch;
    align-self: flex-start;
    gap: var(--gap-toolbar);
    padding: var(--padding-toolbar-y) var(--padding-toolbar-x);
    background: var(--background-toolbar);
    border: var(--border-width) solid var(--border-toolbar);
    border-radius: var(--border-radius);
}

/* В режиме чтения тулбар содержит только «?» (инспектор узла) — edit-кнопки скрыты
   (.is-edit-only). Бар не прячем целиком: «?» нужен и без драфта (отражение/папка).
   #SP-2-D-4-1-edit-ui § «Тулбар активного узла», #SP-2-D-10-node-inspector */

.tree-toolbar__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--size-toolbar-btn);
    height: var(--size-toolbar-btn);
    padding: 0;
    background: var(--background-button);
    border: var(--border-width) solid var(--border-button);
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-toolbar-icon);
    line-height: 1;
}

.tree-toolbar__btn:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--background-button-hover);
}

/* State-дизейбл — aria-disabled (правило 7 SP-2-D-5): кнопка остаётся кликабельной,
   но показывается приглушённой. Нативный :disabled оставлен для совместимости. */
.tree-toolbar__btn:disabled,
.tree-toolbar__btn[aria-disabled="true"] {
    opacity: var(--opacity-button-disabled);
    cursor: var(--cursor-button-disabled);
}

.tree-toolbar__btn.is-danger {
    color: var(--background-button-danger);
}

/* mode-переключатели (Дерево/Связи/Группы) — залипающие */
.tree-toolbar__btn.is-mode.is-active {
    background: var(--background-active);
    border-color: var(--border-active);
}

.tree-toolbar__btn.is-mode.is-active:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--background-active-hovered);
}

/* SP-15-D-2: тоггл «Ссылки» — НЕ radio-режим (работает ПОВЕРХ «Дерева»), но подсветка активности
   такая же, как у mode-переключателей. */
.tree-toolbar__btn.is-urls-toggle.is-active {
    background: var(--background-active);
    border-color: var(--border-active);
}

.tree-toolbar__btn.is-urls-toggle.is-active:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--background-active-hovered);
}

/* В режиме чтения edit-only кнопки скрыты */
.tree-toolbar__btn.is-edit-only {
    display: none;
}

body.is-edit-mode .tree-toolbar__btn.is-edit-only {
    display: flex;
}

/* SP-2-D-10: «?» (инспектор) переехал в mode-полосу. В режиме чтения боковой тулбар содержит
   только edit-only кнопки (скрыты) → сам бар пуст, скрываем его целиком. В редактировании виден. */
body:not(.is-edit-mode) .tree-toolbar {
    display: none;
}

/* --- SP-2-D-9: режим «Связи» — панель связей в слоте колонки-потомка --- */

/* В режиме «Связи» вертикальный edit-тулбар скрыт (его действия — над деревом, к панели
   связок неприменимы; §2). Mode-бар (.tree-mode-bar) остаётся видимым. */
.tags-tree.is-links-mode .tree-toolbar {
    display: none;
}

/* SP-2-D-11: режим «Группы» — edit-тулбар неприменим к колонкам-пикерам (как в «Связях»). */
.tags-tree.is-groups-mode .tree-toolbar {
    display: none;
}

/* Колонки режима «Группы» (Группы/Значения/Результат) наследуют .tags-tree__column. */
.tree-groups {
    padding: var(--padding-groups-column);
    gap: var(--gap-groups-list);
}

.tree-groups__title {
    padding: var(--padding-groups-title-y) var(--padding-groups-title-x);
    font-weight: var(--font-weight-groups-title);
    font-size: var(--font-size-groups-title);
    color: var(--color-groups-title);
}

.tree-groups__loading {
    padding: var(--padding-groups-empty);
    color: var(--color-groups-loading);
}

.tree-groups__empty {
    padding: var(--padding-groups-empty);
    color: var(--color-groups-empty);
}

.tree-groups__list {
    display: flex;
    flex-direction: column;
    gap: var(--gap-groups-list);
}

/* Пункт группы/значения — кнопка-строка с подписью и счётчиком. */
.tree-groups__item {
    display: flex;
    align-items: baseline;
    gap: var(--gap-groups-item);
    width: 100%;
    text-align: left;
    background: transparent;
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius-groups-item);
    padding: var(--padding-groups-item-y) var(--padding-groups-item-x);
    cursor: pointer;
    color: inherit;
    font: inherit;
}

.tree-groups__item:hover {
    background: var(--background-groups-item-hover);
}

.tree-groups__item.is-group-selected {
    background: var(--background-groups-item-selected);
    color: var(--color-groups-item-selected);
    border-color: var(--border-groups-item-selected);
}

.tree-groups__item-count {
    margin-left: auto;
    color: var(--color-groups-item-count);
    font-size: var(--font-size-groups-item-count);
}

.tree-groups__item-role {
    color: var(--color-groups-item-role);
    font-size: var(--font-size-groups-item-role);
}

/* Колонка «Результат»: чипы-теги. Кликабельны (есть data-node-id) — курсор-указатель. */
.tree-groups__result .tree-groups__list {
    gap: var(--gap-groups-result);
}

.tree-groups__result-chip {
    display: inline-block;
    padding: var(--padding-groups-chip-y) var(--padding-groups-chip-x);
    background: var(--background-groups-chip);
    border: var(--border-width) solid var(--border-groups-chip);
    border-radius: var(--border-radius-groups-chip);
    color: inherit;
}

.tree-groups__result-chip[data-node-id] {
    cursor: pointer;
}

.tree-groups__result-chip[data-node-id]:hover {
    background: var(--background-groups-item-hover);
}

.tree-groups__regroup {
    align-self: flex-start;
    background: transparent;
    border: none;
    padding: 0;
    margin-bottom: var(--margin-groups-regroup-bottom);
    cursor: pointer;
    color: var(--color-groups-regroup);
    font: inherit;
    font-size: var(--font-size-groups-regroup);
}

.tree-groups__regroup:hover {
    text-decoration: underline;
}

/* Отдельная колонка-кнопка «Группировать ещё» справа от «Результат» — узкая, по контенту. */
.tree-groups__regroup-column {
    min-width: var(--min-width-groups-regroup-column);
}

/* Панель связей — широкая колонка (наследует .tags-tree__column): шире обычной, по контенту.
   Правый край широкой таблицы достаётся горизонтальным скроллом контейнера дерева (§2). */
.tree-links-panel {
    max-width: var(--max-width-links-panel);
    gap: var(--gap-links-panel);
    padding: var(--padding-links-panel);
    font-size: var(--font-size-links);
}

.tree-links-panel__empty {
    padding: var(--padding-links-empty-y) var(--padding-links-empty-x);
    color: var(--color-links-empty);
}

.tree-links-panel__loading {
    padding: var(--padding-links-empty-y) var(--padding-links-empty-x);
    color: var(--color-links-loading);
}

/* Блок «Свойства» (2т-связки): строки «Роль: chip, chip» (§3). */
.tree-links-panel__properties {
    display: flex;
    flex-direction: column;
    gap: var(--gap-links-properties);
}

.tree-links-panel__property {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--gap-links-property);
}

.tree-links-panel__property-role {
    color: var(--color-links-property-role);
    font-weight: var(--font-weight-links-property-role);
}

/* Приглушённая роль колонки в скобках после имени шаблона (§3, «шаблон (колонка)»). */
.tree-links-panel__property-paren {
    color: var(--color-links-property-paren);
    font-weight: var(--font-weight-links-property-paren);
    opacity: var(--opacity-links-property-paren);
    font-size: var(--font-size-links-property-paren);
}

.tree-links-panel__chips {
    display: inline;
}

/* «Чип + запятая» как неразрывная единица: запятая не отрывается от тега при переносе (§3).
   Перенос — только по пробелу МЕЖДУ единицами. */
.tree-links-panel__chip-unit {
    white-space: nowrap;
}

/* Чип тега. §9: НЕ кликается — без cursor:pointer, без hover-перехода. */
.tree-links-panel__chip {
    display: inline-block;
    padding: var(--padding-links-chip-y) var(--padding-links-chip-x);
    background: var(--background-links-chip);
    border: var(--border-width) solid var(--border-links-chip);
    border-radius: var(--border-radius-links-chip);
    color: var(--color-links-chip);
}

/* Таблица (шаблон ≥3 колонок, §4). */
.tree-links-panel__table {
    display: flex;
    flex-direction: column;
    gap: var(--gap-links-table);
}

.tree-links-panel__table + .tree-links-panel__table,
.tree-links-panel__properties + .tree-links-panel__table {
    margin-top: var(--margin-links-table-top);
}

.tree-links-panel__table-title {
    font-size: var(--font-size-links-table-title);
    font-weight: var(--font-weight-links-table-title);
}

.tree-links-panel__grid {
    border-collapse: collapse;
    width: max-content;
}

.tree-links-panel__grid th,
.tree-links-panel__grid td {
    border: var(--border-width) solid var(--border-links-table);
    padding: var(--padding-links-cell-y) var(--padding-links-cell-x);
    text-align: left;
    vertical-align: top;
}

.tree-links-panel__grid th {
    background: var(--background-links-th);
    color: var(--color-links-th);
    font-weight: var(--font-weight-links-th);
}

/* «Лишняя» колонка (атрибут без колонки-зеркала в шаблоне, §4–5) — приглушена. */
.tree-links-panel__grid th.is-extra,
.tree-links-panel__grid td.is-extra {
    color: var(--color-links-col-extra);
}

/* Пустая ячейка — заметный маркер «пусто» (§4). */
.tree-links-panel__cell--empty {
    color: var(--color-links-cell-empty);
    font-style: italic;
}

/* Чипы в ячейке/строке — перенос по словам, небольшой зазор. */
.tree-links-panel__chip + .tree-links-panel__chip {
    margin-left: 0;
}

/* SP-2-D-9 §11.4 (этап 3b-1): edit-аффордансы ячеек таблиц связей. Только в edit-режиме
   (body.is-edit-mode) ячейка — flex-поток чип-токенов и кнопки «+». В чтении панель тоже
   живёт под .is-links-mode, поэтому скоупим именно по edit-режиму, а не по links-режиму. */
/* Flex-раскладка чипов+«+» в edit-режиме — на ВНУТРЕННЕМ обёрточном элементе, не на самом <td>:
   display:flex на table-cell ломает табличную раскладку (колонки строки схлопываются). */
.tree-links-panel__cell-edit {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--gap-links-cell-edit);
}

/* Чип-токен с кнопкой «×» (убрать член). */
.tree-links-panel__chip-wrap {
    display: inline-flex;
    align-items: center;
    gap: var(--gap-links-chip-wrap);
}

.tree-links-panel__chip-remove {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    line-height: 1;
    color: var(--color-links-chip-remove);
    font-size: var(--font-size-links-chip-remove);
}

.tree-links-panel__chip-remove:hover {
    color: var(--color-links-chip-remove-hover);
}

/* Кнопка «+» в ячейке (раскрывает инлайн-пикер значения). */
.tree-links-panel__cell-add {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    line-height: 1;
    color: var(--color-links-cell-add);
    font-size: var(--font-size-links-cell-add);
}

/* SP-2-D-9 §11.6: блок «Свойства» в edit-режиме — чипы-токены + «+» с тем же gap, что в ячейке.
   inline-flex (а не flex), чтобы контейнер чипов остался на одной строке с подписью «Роль:». */
body.is-edit-mode .tree-links-panel__chips {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--gap-links-cell-edit);
    vertical-align: top;
}

/* SP-2-D-9 §11.5: действия над строкой (🗑/↩) + помеченная удалённой строка. */
.tree-links-panel__row-actions {
    white-space: nowrap;
    text-align: center;
}

.tree-links-panel__row-delete,
.tree-links-panel__row-restore {
    border: none;
    background: none;
    padding: var(--padding-links-row-action);
    cursor: pointer;
    line-height: 1;
    color: var(--color-links-row-action);
    font-size: var(--font-size-links-row-action);
}

.tree-links-panel__row-delete:hover { color: var(--color-links-row-delete-hover); }
.tree-links-panel__row-restore:hover { color: var(--color-links-row-restore-hover); }

/* Помеченная удалённой строка: приглушена; кнопка ↩ остаётся читаемой. */
.tree-links-panel__grid tr.is-deleted td {
    opacity: var(--opacity-links-row-deleted);
}
.tree-links-panel__grid tr.is-deleted .tree-links-panel__row-restore {
    opacity: 1;
}

/* SP-2-D-9 §11.5: «+ связка» под таблицей. */
.tree-links-panel__add-pack-row {
    margin-top: var(--margin-links-add-pack-top);
}
.tree-links-panel__add-pack {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    color: var(--color-links-add-pack);
    font-size: var(--font-size-links-add-pack);
}

/* SP-2-D-9 §11.6: «+ новая связка» (внизу панели / в пустом состоянии). */
.tree-links-panel__new-pack {
    display: inline-block;
    margin-top: var(--margin-links-new-pack-top);
    border: none;
    background: none;
    padding: var(--padding-links-new-pack-y) 0;
    cursor: pointer;
    color: var(--color-links-new-pack);
    font-weight: var(--font-weight-links-new-pack);
    font-size: var(--font-size-links-new-pack);
}

/* Дизейбл-аффорданс (заблокированный драфт, §5): aria-disabled — единый стиль (правило 7). */
.tree-links-panel__chip-remove.is-disabled,
.tree-links-panel__cell-add.is-disabled,
.tree-links-panel__row-delete.is-disabled,
.tree-links-panel__row-restore.is-disabled,
.tree-links-panel__add-pack.is-disabled,
.tree-links-panel__new-pack.is-disabled {
    opacity: var(--opacity-button-disabled);
    cursor: var(--cursor-button-disabled);
}

/* Адаптив §8: на узком экране таблица → карточки (строка = карточка, «роль: значения»),
   без горизонтального скролла внутри таблицы. Подпись роли берётся из data-label (td::before).
   Брейкпоинт 36rem — литералом: var() в условии @media недопустим (как и @media в site.css). */
@media (max-width: 36rem) {
    .tree-links-panel__grid,
    .tree-links-panel__grid thead,
    .tree-links-panel__grid tbody,
    .tree-links-panel__grid tr,
    .tree-links-panel__grid td {
        display: block;
        width: auto;
    }

    /* Заголовок-строка скрыт визуально — подпись роли уходит в каждую ячейку через ::before. */
    .tree-links-panel__grid thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }

    .tree-links-panel__grid tr {
        margin-bottom: var(--gap-links-card);
        border: var(--border-width) solid var(--border-links-card);
        border-radius: var(--border-radius);
        padding: var(--padding-links-card);
    }

    .tree-links-panel__grid td {
        border: none;
        padding: var(--padding-links-cell-y) 0;
        display: flex;
        gap: var(--gap-links-property);
    }

    .tree-links-panel__grid td::before {
        content: attr(data-label);
        flex: 0 0 var(--width-links-card-label);
        color: var(--color-links-property-role);
        font-weight: var(--font-weight-links-property-role);
    }
}

/* --- Форма поиска/создания тега --- */

.tree-search-form {
    display: flex;
    flex-direction: column;
    gap: var(--gap-search-form);
    padding: var(--padding-search-form);
    background: var(--background-search-form);
    border: var(--border-width) solid var(--border-search-form);
    border-radius: var(--border-radius);
}

.tree-search-form__row {
    display: flex;
    gap: var(--gap-search-form);
}

.tree-search-form__input {
    flex: 1 1 auto;
    min-width: 0;
    padding: var(--padding-search-input-y) var(--padding-search-input-x);
    background: var(--background-search-input);
    border: var(--border-width) solid var(--border-column);
    border-radius: var(--border-radius);
    font-size: var(--font-size-search-input);
    color: inherit;
}

.tree-search-form__create {
    flex: 0 0 auto;
    padding: var(--padding-button-y) var(--padding-button-x);
    background: var(--background-button-primary);
    color: var(--color-button-primary);
    border: var(--border-width) solid var(--background-button-primary);
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-button);
}

.tree-search-form__create:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--background-button-primary-hover);
    border-color: var(--background-button-primary-hover);
}

.tree-search-form__create:disabled,
.tree-search-form__create[aria-disabled="true"] {
    opacity: var(--opacity-button-disabled);
    cursor: var(--cursor-button-disabled);
}

.tree-search-form__dropdown {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.tree-search-form__option {
    padding: var(--padding-search-option-y) var(--padding-search-option-x);
    background: var(--background-search-input);
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-node);
}

.tree-search-form__option:hover {
    background: var(--background-search-option-hover);
}

.tree-search-form__option.is-highlighted {
    background: var(--background-search-option-highlighted);
    border-color: var(--border-search-option-highlighted);
}

.tree-search-form__empty {
    padding: var(--padding-search-empty-y) var(--padding-search-empty-x);
    color: var(--color-search-empty);
    font-style: italic;
    font-size: var(--font-size-search-empty);
}

/* --- SP-1-D-6: инлайн-пикер типа тега (раскрывается под текущим узлом) --- */

.tree-type-picker {
    display: flex;
    flex-direction: column;
    gap: var(--gap-type-picker);
    padding: var(--padding-type-picker);
    background: var(--background-type-picker);
    border: var(--border-width) solid var(--border-type-picker);
    border-radius: var(--border-radius);
}

.tree-type-picker__current {
    color: var(--color-type-picker-current);
    font-size: var(--font-size-type-picker-current);
}

.tree-type-picker__row {
    display: flex;
    gap: var(--gap-type-picker);
}

.tree-type-picker__input {
    flex: 1 1 auto;
    min-width: 0;
    padding: var(--padding-search-input-y) var(--padding-search-input-x);
    background: var(--background-search-input);
    border: var(--border-width) solid var(--border-column);
    border-radius: var(--border-radius);
    font-size: var(--font-size-search-input);
    color: inherit;
}

.tree-type-picker__clear {
    flex: 0 0 auto;
    padding: var(--padding-button-y) var(--padding-button-x);
    background: var(--background-search-input);
    border: var(--border-width) solid var(--border-column);
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-button);
}

.tree-type-picker__clear:disabled {
    opacity: var(--opacity-button-disabled);
    cursor: var(--cursor-button-disabled);
}

.tree-type-picker__dropdown {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.tree-type-picker__option {
    padding: var(--padding-search-option-y) var(--padding-search-option-x);
    background: var(--background-search-input);
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-node);
}

.tree-type-picker__option:hover {
    background: var(--background-search-option-hover);
}

.tree-type-picker__option.is-highlighted {
    background: var(--background-search-option-highlighted);
    border-color: var(--border-search-option-highlighted);
}

.tree-type-picker__empty {
    padding: var(--padding-search-empty-y) var(--padding-search-empty-x);
    color: var(--color-search-empty);
    font-style: italic;
    font-size: var(--font-size-search-empty);
}

/* --- SP-2-D-9 §11.4 (этап 3b-1): инлайн-пикер значения ячейки таблицы связей --- */

.tree-link-cell-picker {
    display: flex;
    flex-direction: column;
    gap: var(--gap-link-cell-picker);
    margin-top: var(--margin-link-cell-picker-top);
    padding: var(--padding-link-cell-picker);
    min-width: var(--min-width-link-cell-picker);
    background: var(--background-link-cell-picker);
    border: var(--border-width) solid var(--border-link-cell-picker);
    border-radius: var(--border-radius);
}

.tree-link-cell-picker__row {
    display: flex;
    gap: var(--gap-link-cell-picker);
}

.tree-link-cell-picker__input {
    flex: 1 1 auto;
    min-width: 0;
    padding: var(--padding-search-input-y) var(--padding-search-input-x);
    background: var(--background-search-input);
    border: var(--border-width) solid var(--border-column);
    border-radius: var(--border-radius);
    font-size: var(--font-size-search-input);
    color: inherit;
}

.tree-link-cell-picker__dropdown {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.tree-link-cell-picker__option {
    padding: var(--padding-search-option-y) var(--padding-search-option-x);
    background: var(--background-search-input);
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-node);
}

.tree-link-cell-picker__option:hover {
    background: var(--background-search-option-hover);
}

.tree-link-cell-picker__option.is-highlighted {
    background: var(--background-search-option-highlighted);
    border-color: var(--border-search-option-highlighted);
}

.tree-link-cell-picker__empty {
    padding: var(--padding-search-empty-y) var(--padding-search-empty-x);
    color: var(--color-search-empty);
    font-style: italic;
    font-size: var(--font-size-search-empty);
}

/* SP-2-D-9 §11.6: инлайн-пикер узла-шаблона «+ новая связка» — те же токены, что у пикера ячейки. */
.tree-link-template-picker {
    display: flex;
    flex-direction: column;
    gap: var(--gap-link-cell-picker);
    margin-top: var(--margin-link-cell-picker-top);
    padding: var(--padding-link-cell-picker);
    min-width: var(--min-width-link-cell-picker);
    background: var(--background-link-cell-picker);
    border: var(--border-width) solid var(--border-link-cell-picker);
    border-radius: var(--border-radius);
}

.tree-link-template-picker__row {
    display: flex;
    gap: var(--gap-link-cell-picker);
}

.tree-link-template-picker__input {
    flex: 1 1 auto;
    min-width: 0;
    padding: var(--padding-search-input-y) var(--padding-search-input-x);
    background: var(--background-search-input);
    border: var(--border-width) solid var(--border-column);
    border-radius: var(--border-radius);
    font-size: var(--font-size-search-input);
    color: inherit;
}

.tree-link-template-picker__dropdown {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.tree-link-template-picker__option {
    padding: var(--padding-search-option-y) var(--padding-search-option-x);
    background: var(--background-search-input);
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-node);
}

.tree-link-template-picker__option:hover {
    background: var(--background-search-option-hover);
}

.tree-link-template-picker__option.is-highlighted {
    background: var(--background-search-option-highlighted);
    border-color: var(--border-search-option-highlighted);
}

.tree-link-template-picker__empty {
    padding: var(--padding-search-empty-y) var(--padding-search-empty-x);
    color: var(--color-search-empty);
    font-style: italic;
    font-size: var(--font-size-search-empty);
}

/* SP-2-D-9 §11.7: шаг выбора колонки контекста при «+ новая связка» */
.tree-link-template-picker__title {
    font-weight: var(--font-weight-template-picker-title);
    font-size: var(--font-size-template-picker-title);
}

.tree-link-template-picker__hint {
    color: var(--color-template-picker-hint);
    font-size: var(--font-size-template-picker-hint);
}

.tree-link-template-picker__columns {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.tree-link-template-picker__column {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-template-picker-column-mark);
    padding: var(--padding-search-option-y) var(--padding-search-option-x);
    background: var(--background-search-input);
    border: var(--border-width) solid transparent;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-node);
}

.tree-link-template-picker__column:hover {
    background: var(--background-search-option-hover);
}

.tree-link-template-picker__column.is-highlighted {
    background: var(--background-search-option-highlighted);
    border-color: var(--border-search-option-highlighted);
}

.tree-link-template-picker__column-mark {
    color: var(--color-template-picker-column-valid);
}

.tree-link-template-picker__column--invalid .tree-link-template-picker__column-mark {
    color: var(--color-template-picker-column-invalid);
}

.tree-link-template-picker__warning {
    color: var(--color-template-picker-warning);
    font-size: var(--font-size-template-picker-warning);
}

.tree-link-template-picker__actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--gap-template-picker-actions);
    margin-top: var(--margin-template-picker-actions-top);
}

.tree-link-template-picker__cancel {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--color-template-picker-cancel);
    font-size: var(--font-size-node);
}

.tree-link-template-picker__confirm {
    padding: var(--padding-template-picker-confirm-y) var(--padding-template-picker-confirm-x);
    background: var(--background-template-picker-confirm);
    color: var(--color-template-picker-confirm);
    border: none;
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-node);
}

.tree-link-template-picker__confirm:hover {
    background: var(--background-template-picker-confirm-hover);
}

/* --- Нижняя панель сообщений (единый канал уведомлений, #SP-2-D-7-message-panel) --- */

.tree-message-panel {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: var(--z-index-message-panel);
    display: flex;
    flex-direction: column;
    height: var(--height-message-line);
    max-height: var(--max-vh-message-panel);
    overflow: hidden;
    background: var(--background-message-panel);
    border-top: var(--border-width) solid var(--border-message-panel);
    font-size: var(--font-size-message);
}

/* В режиме просмотра дерева панель не нужна — показываем только в edit-режиме
   (как и панель буфера). #SP-2-D-7-message-panel */
body:not(.is-edit-mode) .tree-message-panel {
    display: none;
}

/* Грип-таскалка: видна только в развёрнутом виде; перетаскивание = ресайз, клик = свернуть. */
.tree-message-panel__grip {
    display: none;
    flex: 0 0 auto;
    align-items: center;
    justify-content: flex-end;
    height: var(--height-message-grip);
    padding: 0 var(--padding-message-x);
    background: var(--background-message-grip);
    color: var(--color-message-grip);
    border-bottom: var(--border-width) solid var(--border-message-panel);
    cursor: ns-resize;
    user-select: none;
    touch-action: none;
}

.tree-message-panel.is-expanded .tree-message-panel__grip {
    display: flex;
}

/* История: видна в развёрнутом виде, самостоятельный вертикальный скролл.
   Содержимое прижато к низу (новейшее внизу): при вытягивании панель «приоткрывается»
   сверху, а записи не уезжают вместе с грипом. margin-top:auto на первой записи
   отдаёт свободное место сверху; при переполнении схлопывается и работает скролл. */
.tree-message-panel__history {
    display: none;
    flex: 1 1 auto;
    flex-direction: column;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.tree-message-panel.is-expanded .tree-message-panel__history {
    display: flex;
}

.tree-message-panel__history > .tree-message-panel__row:first-child {
    margin-top: auto;
}

/* Свёрнутая строка: последнее сообщение; скрыта в развёрнутом виде. */
.tree-message-panel__line {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: var(--gap-message-row);
    height: var(--height-message-line);
    padding: 0 var(--padding-message-x);
    border-left: var(--width-message-sev-bar) solid transparent;
    overflow-x: auto;
    white-space: nowrap;
    touch-action: pan-x;
}

.tree-message-panel.is-expanded .tree-message-panel__line {
    display: none;
}

.tree-message-panel__line-text {
    flex: 0 0 auto;
}

/* Анимация появления нового сообщения: въезд снизу вверх. */
.tree-message-panel__line.is-entering .tree-message-panel__line-text {
    animation: message-slide-up var(--duration-message-anim) ease-out;
}

@keyframes message-slide-up {
    from { transform: translateY(100%); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

/* Счётчик дедупа ×N. */
.tree-message-panel__count {
    flex: 0 0 auto;
    color: var(--color-message-count);
}

.tree-message-panel__count.is-bumped {
    animation: message-count-bump var(--duration-message-anim) ease-out;
}

@keyframes message-count-bump {
    0% { transform: scale(1); }
    50% { transform: scale(1.4); }
    100% { transform: scale(1); }
}

/* Строка истории: время + текст + счётчик; severity-полоса слева. */
.tree-message-panel__row {
    display: flex;
    gap: var(--gap-message-row);
    padding: var(--padding-message-row-y) var(--padding-message-x);
    border-left: var(--width-message-sev-bar) solid transparent;
}

.tree-message-panel__row-time {
    flex: 0 0 auto;
    color: var(--color-message-row-time);
}

.tree-message-panel__row-text {
    flex: 1 1 auto;
}

/* Кликабельная ссылка в сообщении (источник отражения и т.п.) — в свёрнутой строке и в истории. */
.tree-message-panel__link {
    flex: 0 0 auto;
    color: var(--color-message-link);
    text-decoration: underline;
    cursor: pointer;
}

/* Severity-акцент (полоса слева) — и для строки, и для записей истории. */
.is-sev-info { border-left-color: var(--color-message-sev-info); }
.is-sev-success { border-left-color: var(--color-message-sev-success); }
.is-sev-error { border-left-color: var(--color-message-sev-error); }

@media (prefers-reduced-motion: reduce) {
    .tree-message-panel__line.is-entering .tree-message-panel__line-text,
    .tree-message-panel__count.is-bumped {
        animation: none;
    }
}

/* Зеркало строки в visual viewport (зум/клавиатура): копия свёрнутой строки, которую JS
   позиционирует и масштабирует у нижней кромки видимой области. transform-origin: top left —
   JS задаёт top/width/transform так, что зеркало нормального физ. размера во всю видимую
   ширину. #SP-2-D-7-message-panel */
.tree-message-mirror {
    position: fixed;
    z-index: var(--z-index-message-mirror);
    transform-origin: top left;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: var(--gap-message-row);
    height: var(--height-message-line);
    padding: 0 var(--padding-message-x);
    background: var(--background-message-panel);
    border-top: var(--border-width) solid var(--border-message-panel);
    border-left: var(--width-message-sev-bar) solid transparent;
    box-shadow: var(--shadow-message-mirror);
    font-size: var(--font-size-message);
    white-space: nowrap;
    overflow: hidden;
    cursor: pointer;
}

.tree-message-mirror__text {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tree-message-mirror__count {
    flex: 0 0 auto;
    color: var(--color-message-count);
}

/* --- Буфер «Взять/Перенести сюда»: статичная панель снизу (SP-2-D-4) --- */

.tree-buffer-panel {
    display: none;
    position: fixed;
    /* Над панелью сообщений (она прилеплена к самому низу). */
    bottom: var(--height-message-line);
    left: 0;
    right: 0;
    z-index: var(--z-index-buffer-panel);
    align-items: center;
    gap: var(--gap-buffer-panel);
    padding: var(--padding-buffer-panel-y) var(--padding-buffer-panel-x);
    background: var(--background-buffer-panel);
    border-top: var(--border-width) solid var(--border-buffer-panel);
    font-size: var(--font-size-buffer-panel);
}

body.is-edit-mode .tree-buffer-panel.is-active {
    display: flex;
    flex-wrap: wrap;
}

body.is-edit-mode .tags-tree {
    padding-bottom: var(--height-buffer-panel-approx);
}

/* SP-15-D-2 §3: режим «Ссылки» — панель буфера показана ВСЕГДА (фантом + закреплённые ноги),
   вне edit и при пустом буфере. Резерв под неё снизу дерева. */
body.is-urls-mode .tree-buffer-panel {
    display: flex;
    flex-wrap: wrap;
}

body.is-urls-mode .tags-tree {
    padding-bottom: var(--height-buffer-panel-approx);
}

/* §3.4: в режиме «Ссылки» edit-кнопки Перенести/Очистить не показываем — буфер контекстен по
   режиму (ноги фильтра регулируют фантом / «встать» / ×, а не Place). */
body.is-urls-mode .tree-buffer-panel__buttons {
    display: none;
}

/* §3.1: фантом-chip — текущий узел, приглушён, пунктирная рамка (клик = материализовать). */
.tree-buffer-panel__chip.is-phantom {
    opacity: var(--opacity-buffer-chip-phantom);
    border-style: var(--border-style-buffer-chip-phantom);
}

/* §3.4 дизейбл-с-причиной: фантом сверх капа 6 ног не закрепляется (клик показывает причину). */
.tree-buffer-panel__chip.is-phantom.is-disabled {
    cursor: var(--cursor-button-disabled);
}

/* §3.2: закреплённая нога = текущий узел → подсветка «ты здесь». */
.tree-buffer-panel__chip.is-here {
    background: var(--background-buffer-chip-here);
    border-color: var(--border-buffer-chip-here);
}

.tree-buffer-panel__chip-here {
    color: var(--color-buffer-chip-here);
    font-size: var(--font-size-buffer-chip-here);
    user-select: none;
}

/* SP-15-D-2 §3: видимый хинт рядом с фантомом («← нажми, чтобы…»). Приглушён, некликабелен. */
.tree-buffer-panel__phantom-hint {
    color: var(--color-buffer-phantom-hint);
    font-size: var(--font-size-buffer-phantom-hint);
    align-self: var(--align-self-buffer-phantom-hint);
    user-select: none;
}

.tree-buffer-panel__header {
    font-weight: var(--font-weight-current);
    color: var(--color-text-muted);
}

.tree-buffer-panel__count {
    margin-inline-start: var(--gap-buffer-panel-count);
}

.tree-buffer-panel__list {
    display: flex;
    flex: 1 1 auto;
    flex-wrap: wrap;
    gap: var(--gap-buffer-panel-list);
}

.tree-buffer-panel__chip {
    display: inline-flex;
    align-items: center;
    gap: var(--gap-buffer-chip);
    padding: var(--padding-buffer-chip-y) var(--padding-buffer-chip-x);
    background: var(--background-buffer-chip);
    border: var(--border-width) solid var(--border-buffer-chip);
    border-radius: var(--border-radius);
    cursor: pointer;
}

.tree-buffer-panel__chip:hover {
    background: var(--background-buffer-chip-hover);
}

.tree-buffer-panel__chip.is-taken-inactive {
    opacity: var(--opacity-buffer-chip-inactive);
    border-style: var(--border-style-buffer-chip-inactive);
}

.tree-buffer-panel__chip-text {
    user-select: none;
}

.tree-buffer-panel__chip-remove {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    color: var(--color-buffer-chip-remove);
    font-size: var(--font-size-buffer-chip-remove);
    line-height: 1;
}

.tree-buffer-panel__buttons {
    display: flex;
    gap: var(--gap-buffer-panel-list);
}

.tree-buffer-panel__btn {
    padding: var(--padding-button-y) var(--padding-button-x);
    background: var(--background-button);
    border: var(--border-width) solid var(--border-button);
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-button);
}

.tree-buffer-panel__btn:hover:not([aria-disabled="true"]) {
    background: var(--background-button-hover);
}

/* State-дизейбл Place при превышении batch-лимита (правило 7 SP-2-D-5). */
.tree-buffer-panel__btn[aria-disabled="true"] {
    opacity: var(--opacity-button-disabled);
    cursor: var(--cursor-button-disabled);
}

.tree-buffer-panel__btn.is-primary {
    background: var(--background-button-primary);
    color: var(--color-button-primary);
    border-color: var(--background-button-primary);
}

.tree-buffer-panel__btn.is-primary:hover:not([aria-disabled="true"]) {
    background: var(--background-button-primary-hover);
    border-color: var(--background-button-primary-hover);
}

/* SP-11-D-1: баннеры о состоянии драфта (только в режиме автора). */
.tree-draft-banner {
    padding: var(--padding-banner-y) var(--padding-banner-x);
    margin-bottom: var(--margin-banner-bottom);
    border: var(--border-width) solid;
    border-radius: var(--border-radius);
}

.tree-draft-banner.is-rejection {
    background: var(--background-banner-rejection);
    color: var(--color-banner-rejection);
    border-color: var(--border-banner-rejection);
}

.tree-draft-banner.is-submitted {
    display: none;
    background: var(--background-banner-submitted);
    color: var(--color-banner-submitted);
    border-color: var(--border-banner-submitted);
}

body.is-edit-mode .tree-draft-banner.is-submitted {
    display: block;
}

/* SP-11-D-1: бар админских действий поверх дерева. Выглядит как edit-bar, но
   жёлто-тёплый и без счётчиков; всегда виден (не зависит от is-edit-mode). */
.tree-admin-bar {
    background: var(--background-admin-bar);
    border-color: var(--border-admin-bar);
    display: flex !important;
}

.tree-admin-bar.is-committed {
    background: var(--background-admin-bar-committed);
    border-color: var(--border-admin-bar-committed);
}

.tree-admin-bar__committed-badge {
    color: var(--color-admin-bar-committed-badge);
    font-weight: var(--font-weight-admin-bar-committed-badge);
}

/* Предпросмотр чужого драфта (read-only): бейдж «только чтение» + плашка статуса. #SP-2-D-4-5 */
.tree-admin-bar__readonly-badge {
    color: var(--color-preview-readonly-badge);
    font-weight: var(--font-weight-preview-readonly-badge);
}

.tree-admin-bar__status-badge {
    color: var(--color-preview-status-badge);
    font-weight: var(--font-weight-preview-status-badge);
}

/* SP-11-D-2: переключатель draft'ов в edit-bar (чип-кнопка + dropdown) */
.tree-edit-bar__draft {
    cursor: pointer;
    background: none;
    border: 1px solid transparent;
    font: inherit;
    color: inherit;
    padding: 0.125rem 0.5rem;
    border-radius: 0.25rem;
}
.tree-edit-bar__draft:hover {
    border-color: var(--color-ops-panel-link, #2265a8);
}
.tree-draft-switcher {
    background: #fff;
    border: 1px solid var(--color-ops-panel-link, #2265a8);
    border-radius: 0.25rem;
    box-shadow: 0 0.25rem 0.75rem rgba(0,0,0,0.15);
    min-width: 16rem;
    max-width: 32rem;
    padding: 0.25rem 0;
}
.tree-draft-switcher__item {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    padding: 0.375rem 0.75rem;
    cursor: pointer;
    font: inherit;
    color: inherit;
}
.tree-draft-switcher__item:hover {
    background: #f0f0f0;
}
.tree-draft-switcher__item.is-active {
    background: #e8f0fa;
    font-weight: bold;
}
.tree-draft-switcher__item.is-rejected {
    color: #c33;
}
.tree-draft-switcher__item.is-submitted {
    color: #888;
    font-style: italic;
}
.tree-draft-switcher__item--empty {
    padding: 0.375rem 0.75rem;
    color: #888;
    font-style: italic;
}
.tree-draft-switcher__new {
    border-top: 1px solid #eee;
    color: var(--color-ops-panel-link, #2265a8);
}

/* SP-8-US-5-1: полоса загрузки вверху страницы */
.loading-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--height-loading-bar);
    background: var(--color-loading-bar);
    z-index: var(--z-index-loading-bar);
    opacity: 0;
    transition: opacity 0.15s ease;
    pointer-events: none;
}

.loading-bar--visible {
    opacity: 1;
}

/* SP-8-US-6 + SP-8-US-5-2: модальные окна (overlay + dialog) */
.modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: var(--z-index-modal);
    background: var(--background-modal-overlay);
    align-items: center;
    justify-content: center;
}

.modal-overlay.is-visible {
    display: flex;
}

.modal-dialog {
    /* pointer-events: auto — перебиваем Bootstrap .modal-dialog (pointer-events:none),
       иначе клики проваливаются через dialog на overlay, и `e.target === this`
       закрывает модалку без вызова confirm-callback. */
    pointer-events: auto;
    background: var(--background-modal);
    border-radius: var(--border-radius-modal);
    padding: var(--padding-modal-y) var(--padding-modal-x);
    max-width: 28rem;
    width: calc(100% - 2rem);
    box-shadow: 0 0.5rem 2rem rgba(0, 0, 0, 0.2);
}

.modal-dialog__title {
    margin: 0 0 var(--margin-modal-title-bottom);
    font-size: var(--font-size-modal-title);
    font-weight: var(--font-weight-modal-title);
}

.modal-dialog__body {
    margin: 0 0 var(--margin-modal-body-bottom);
    line-height: 1.5;
}

.modal-dialog__footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--gap-modal-footer);
}

.modal-dialog__btn {
    padding: var(--padding-button-y) var(--padding-button-x);
    border: var(--border-width) solid var(--border-button);
    border-radius: var(--border-radius);
    cursor: pointer;
    font-size: var(--font-size-button);
    background: var(--background-button);
}

.modal-dialog__btn:hover:not(:disabled) {
    background: var(--background-button-hover);
}

.modal-dialog__btn:disabled {
    opacity: var(--opacity-button-disabled);
    cursor: var(--cursor-button-disabled);
}

.modal-dialog__btn--primary {
    background: var(--background-button-primary);
    color: var(--color-button-primary);
    border-color: var(--background-button-primary);
}

.modal-dialog__btn--primary:hover:not(:disabled) {
    background: var(--background-button-primary-hover);
    border-color: var(--background-button-primary-hover);
}

/* --- SP-15-D-2: режим «Ссылки» — колонка урлов (наследует .tags-tree__column) ---
   Самая правая колонка в потоке, БЕЗ приклеивания (§2.1): скроллится по горизонтали вместе с
   деревом. Ширина по контенту с потолком; вертикальный скролл — свой (как у обычной колонки). */
.tree-urls-panel {
    max-width: var(--max-width-urls-panel);
    gap: var(--gap-urls-panel);
    padding: var(--padding-urls-panel);
    font-size: var(--font-size-urls);
    align-items: stretch;
}

.tree-urls-panel__header {
    color: var(--color-urls-header);
    font-weight: var(--font-weight-urls-header);
}

.tree-urls-panel__loading {
    padding: var(--padding-urls-empty-y) var(--padding-urls-empty-x);
    color: var(--color-urls-loading);
}

/* Пустой результат — явной строкой (§4, НЕ модалка/НЕ фейдаут — SP-2-D-5). */
.tree-urls-panel__empty {
    padding: var(--padding-urls-empty-y) var(--padding-urls-empty-x);
    color: var(--color-urls-empty);
}

.tree-urls-panel__list {
    display: flex;
    flex-direction: column;
    gap: var(--gap-urls-list);
}

.tree-urls-panel__row {
    display: flex;
    flex-direction: column;
    gap: var(--gap-urls-row);
    padding: var(--padding-urls-row);
    background: var(--background-urls-row);
    border: var(--border-width) solid var(--border-urls-row);
    border-radius: var(--border-radius-urls-row);
}

/* Заголовок — внешняя ссылка (открывает пост в новой вкладке). */
.tree-urls-panel__title {
    color: var(--color-urls-title);
    font-weight: var(--font-weight-urls-title);
    text-decoration: none;
    overflow-wrap: anywhere;
}

.tree-urls-panel__title:hover {
    text-decoration: underline;
}

/* Бейдж сайта — маленький, приглушённый (§4). */
.tree-urls-panel__site {
    align-self: flex-start;
    padding: var(--padding-urls-site-y) var(--padding-urls-site-x);
    background: var(--background-urls-site);
    color: var(--color-urls-site);
    font-size: var(--font-size-urls-site);
    border-radius: var(--border-radius-urls-site);
}

/* «Чем зацепилось» — чипы совпавших тегов (не кликаются). */
.tree-urls-panel__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap-urls-chips);
}

.tree-urls-panel__chip {
    display: inline-block;
    padding: var(--padding-urls-chip-y) var(--padding-urls-chip-x);
    background: var(--background-urls-chip);
    border: var(--border-width) solid var(--border-urls-chip);
    border-radius: var(--border-radius-urls-chip);
    color: var(--color-urls-chip);
    font-size: var(--font-size-urls-chip);
}

/* SP-15-D-2 §6: мультиузел — блок «чем зацепилось» на каждую ногу: подпись-имя узла + её чипы. */
.tree-urls-panel__leg {
    display: flex;
    flex-direction: column;
    gap: var(--gap-urls-leg);
    margin-top: var(--margin-urls-leg-top);
}

.tree-urls-panel__leg-label {
    color: var(--color-urls-leg-label);
    font-size: var(--font-size-urls-leg-label);
    font-weight: var(--font-weight-urls-leg-label);
}

/* SP-15-D-2 §4: раскрывашка «Показать ещё N» — остальные теги урла (tags \ matched). Кнопка-ссылка
   (без модалок/фейдаутов); клик переключает .is-expanded на контейнере чипов. */
.tree-urls-panel__more-toggle {
    align-self: flex-start;
    margin-top: var(--margin-urls-more-toggle-top);
    padding: 0;
    background: none;
    border: none;
    color: var(--color-urls-more-toggle);
    font-size: var(--font-size-urls-more-toggle);
    cursor: pointer;
    text-align: left;
}

.tree-urls-panel__more-toggle:hover {
    text-decoration: underline;
}

/* Остальные теги по умолчанию свёрнуты; .is-expanded — раскрывает (наследует раскладку чипов). */
.tree-urls-panel__more-tags {
    display: none;
    margin-top: var(--margin-urls-more-tags-top);
}

.tree-urls-panel__more-tags.is-expanded {
    display: flex;
}

/* «Показано N из M» — первая страница (пагинация «ещё» — TODO этап 2 §4). */
.tree-urls-panel__more {
    padding-top: var(--padding-urls-more-top);
    color: var(--color-urls-more);
    font-size: var(--font-size-urls-more);
}

