/* ============================================================
   ОФОРМЛЕНИЕ КОДА АВТОРИНГА
   Стили того, что добавляют задачи 001–008. Отдельный файл, чтобы
   правки нового кода не перемешивались с оформлением просмотрщика.
   Переменные темы берутся из studio-base.css — своих цветов здесь нет,
   иначе тёмная тема разъезжается.
   ============================================================ */

/* ---------- модальный диалог ---------- */
.dlg{
  width:min(380px,92vw);padding:0;border:0;border-radius:20px;
  background:var(--m-s-low);color:var(--text);box-shadow:var(--m-e3);
  font:inherit;
}
.dlg::backdrop{background:rgba(0,0,0,.4)}

.dlg-form{display:flex;flex-direction:column;gap:12px;padding:16px 18px}

.dlg-title{
  margin:0;
  font-family:"PT Sans Narrow","PT Sans",system-ui,sans-serif;
  font-size:16px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
}

.dlg-field{display:flex;flex-direction:column;gap:4px;font-size:12px}
.dlg-field > span{color:var(--m-on-variant)}
.dlg-field input{
  height:32px;padding:0 10px;border-radius:8px;
  border:1px solid var(--m-outline-var);
  background:var(--m-surface);color:var(--text);font:inherit;font-size:13px;
}
.dlg-field input:focus{outline:2px solid var(--m-primary);outline-offset:-1px}
/* Поле с недопустимым значением: подсвечивается, пока «ОК» недоступна */
.dlg-field input.bad{border-color:#c5442f}

/* Место под подсказку занято всегда: иначе диалог прыгает по высоте,
   когда подсказка появляется и исчезает при вводе */
.dlg-hint{margin:0;min-height:16px;font-size:11.5px;color:#c5442f}

/* Текст вопроса и перечень в диалогах проекта (024) */
.dlg-text{margin:0;font-size:12.5px;line-height:1.4}
.dlg-list{
  margin:0;padding:0 0 0 18px;max-height:160px;overflow:auto;
  font-size:12px;color:var(--m-on-variant);
}

.dlg-foot{display:flex;justify-content:flex-end;gap:8px;padding-top:4px}
.dlg-btn{
  height:34px;padding:0 18px;border:0;border-radius:17px;cursor:pointer;
  background:var(--m-s-cont);color:var(--text);font:inherit;font-size:13px;
}
/* Ссылкой бывает выбор, ведущий на другую страницу, — категория новой формы (O-001) */
a.dlg-btn{display:inline-flex;align-items:center;text-decoration:none}
.dlg-btn:hover{background:var(--m-s-high)}
.dlg-btn.primary{background:var(--m-primary);color:var(--m-on-primary)}
.dlg-btn.primary:hover{filter:brightness(1.08)}
.dlg-btn:disabled{opacity:.45;cursor:default}
.dlg-btn.primary:disabled:hover{filter:none}

/* Список в диалоге типа (073-b): шаблон, тип замены, вид свойства */
.dlg-select{
  min-height:32px;padding:4px 8px;border-radius:8px;
  border:1px solid var(--m-outline-var);
  background:var(--m-surface);color:var(--text);font:inherit;font-size:13px;
}
.dlg-select:focus{outline:2px solid var(--m-primary);outline-offset:-1px}

/* Импорт типа из IFC (073-e): типы файла по группам с флажками. Кнопок
   конфликта четыре — на узком диалоге они переносятся, а не вылезают */
.dlg-checks{display:flex;flex-direction:column;gap:8px;max-height:280px;overflow:auto}
.dlg-checks fieldset{margin:0;padding:0;border:0;display:flex;flex-direction:column;gap:2px}
.dlg-checks legend{padding:0 0 2px;font-size:12px;color:var(--m-on-variant)}
.dlg-check{display:flex;align-items:center;gap:8px;font-size:12.5px;cursor:pointer}
.dlg-check.off{opacity:.5;cursor:default}
.dlg-check em{font-style:normal;font-size:11.5px;color:var(--m-on-variant)}
.dlg-foot.wrap{flex-wrap:wrap}

/* Вкладки диалога (168): «Снаружи» и «Внутри» окна «Образмерить» */
.dlg-tabs{display:flex;gap:2px;border-bottom:1px solid var(--m-outline-var)}
.dlg-tab{
  padding:6px 12px;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;
  background:none;color:var(--m-on-variant);font:inherit;font-size:13px;cursor:pointer;
}
.dlg-tab:hover{background:var(--m-hover)}
.dlg-tab[aria-selected="true"]{color:var(--text);border-bottom-color:var(--m-primary)}
.dlg-tabpanel{display:flex;flex-direction:column;gap:12px}
.dlg-tabpanel[hidden]{display:none}
.dlg-tabs[hidden]{display:none}

/* ---------- контекстное меню диспетчера (073-b) ---------- */
.ctx-menu{
  position:fixed;z-index:1000;min-width:160px;padding:4px 0;margin:0;list-style:none;
  border-radius:8px;background:var(--m-s-low);color:var(--text);box-shadow:var(--m-e3);
  font-size:12.5px;
}
.ctx-menu[hidden]{display:none}
.ctx-menu button{
  display:block;width:100%;padding:6px 14px;border:0;background:none;color:inherit;
  font:inherit;text-align:left;cursor:pointer;
}
.ctx-menu button:hover:not(:disabled){background:var(--m-s-high)}
.ctx-menu button:disabled{opacity:.45;cursor:default}

/* ---------- панель типа (073-b) ---------- */
/* Кнопки «Новый тип», «Копировать», «Удалить» над полями */
.type-actions{display:flex;flex-wrap:wrap;gap:4px;padding:4px 0 6px}
/* Удалить свойство пользователя — маленький крестик у значения */
.prop-remove{
  width:20px;height:20px;margin-left:4px;padding:0;border:0;border-radius:4px;cursor:pointer;
  background:none;color:var(--m-on-variant);font:inherit;font-size:13px;line-height:20px;
}
.prop-remove:hover{background:var(--m-s-high);color:var(--text)}

/* ---------- кнопки ленты ---------- */
/* Недоступная кнопка вкладки: у просмотрщика таких не было, поэтому
   правило живёт здесь. Подсказка при наведении остаётся — она объясняет,
   чего кнопке не хватает, и pointer-events поэтому не снимаем. */
.btn:disabled{opacity:.4;cursor:default}
.btn:disabled:hover .pad{background:transparent}
.btn:disabled:hover{color:var(--m-on-variant)}

/* ---------- список уровней ---------- */
/* Пометка происхождения строки. Не должна отнимать место у имени:
   имя ужимается многоточием, а пометка короткая и не сжимается. */
.tree .leaf .tag{
  flex:none;font-size:11px;letter-spacing:.02em;
  color:var(--m-on-variant);opacity:.75;
}
.tree .leaf.cur .tag{color:inherit;opacity:.85}

/* ---------- ярус типа в дереве (задача 052-a) ---------- */
/* Строка типа — та же стрелка и скрытый флажок, что у раздела, но имя,
   а не заголовок: обычный шрифт, без капители. Счётчик и пометка «из
   файла» — как у листа. Выбранный тип подсвечивается как лист. */
.tree .node{
  display:flex;align-items:center;gap:8px;
  height:32px;padding:0 12px 0 14px;border-radius:16px;cursor:pointer;
  font-size:13px;font-weight:500;color:var(--text);
}
.tree .node:hover{background:var(--m-hover)}
.tree .node .name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tree .node .name.muted{color:var(--m-on-variant);font-weight:400}
.tree .node .num{margin-left:auto;font-size:11.5px;opacity:.75}
.tree .node .tag{flex:none;font-size:11px;color:var(--m-on-variant);opacity:.75}
.tree li > input:checked + .node .arrow{transform:rotate(-90deg)}
.tree .node.cur{background:var(--m-secondary-c);color:var(--m-on-secondary-c)}
.tree .node.cur .arrow,.tree .node.cur .num,.tree .node.cur .tag{color:inherit;opacity:.85}
/* Перенумерация листов перетаскиванием (102): черта — куда встанет лист */
.tree .leaf.drop-before{box-shadow:inset 0 2px 0 var(--m-primary)}
.tree .leaf.drop-after{box-shadow:inset 0 -2px 0 var(--m-primary)}
.tree .node.drop-into{outline:2px solid var(--m-primary);outline-offset:-2px}

/* ---------- панель типа ---------- */
/* Поле и пометка «толщина оценена» в одной ячейке; ссылка «Тип…» рядом
   с выбором типа в панели стены — тем же контейнером */
.type-field{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}
.type-field .tag{font-size:11px;color:var(--m-on-variant);opacity:.85}
.type-field .tag[hidden]{display:none}
/* Состав типа (139): свёрнутая строка раскрывается щелчком, поля
   раскрытого — с отступом под ней, галочка «наследовать» — справа от поля */
.component-row{cursor:pointer}
.component-row[aria-expanded="true"] .k{color:var(--m-primary)}
.component-fields{margin-left:6px;padding-left:4px;border-left:2px solid var(--m-outline-var)}
.component-inherit{display:inline-flex;align-items:center;gap:3px;font-size:11px;color:var(--m-on-variant);white-space:nowrap}
.prop-group .tag{font-size:11px;font-weight:400;letter-spacing:0;text-transform:none;opacity:.75}

/* ---------- марки осей ---------- */
/* Слой марок лежит поверх холста и мышь не ловит: клик по холсту
   принадлежит выбору тел и режиму построения, и перехватывать его
   кружком нельзя. Устройство то же, что у флажков уровней в
   studio-workspace.css: текст элементом страницы, а не в сцене, — он
   остаётся чётким при любом зуме (задача 002). */
.grid-layer{position:absolute;inset:0;pointer-events:none;z-index:2;overflow:hidden}

/* Кружок с именем. Начало координат — центр марки: рендерер выносит его
   за конец оси вдоль линии (057), и марка сдвигается на половину своего
   размера, чтобы стоять центром в этой точке. Отдалили план — марка
   уменьшается до своего размера на бумаге: `--label-shrink` ставит слою
   рендерер (labelShrink.ts), масштаб — вокруг центра. */
.grid-bubble{
  position:absolute;left:0;top:0;transform:translate(-50%,-50%) scale(var(--label-shrink,1));
  /* Свёрстана под кружок Ø8 и имя 3,5 мм бумаги; размер вида (163) —
     доли `--bubble-size` и `--bubble-text`, их ставит рендерер слою */
  min-width:calc(22px * var(--bubble-size,1));height:calc(22px * var(--bubble-size,1));
  padding:0 calc(4px * var(--bubble-size,1));box-sizing:border-box;
  display:flex;align-items:center;justify-content:center;
  border:1.2px solid #3f51b5;border-radius:50%;
  background:var(--m-s-low);color:#3f51b5;
  /* Марка оси — знак чертежа: чертёжным шрифтом (116), наклонным (160) */
  font-family:"osifont",sans-serif;font-style:italic;
  font-size:calc(11px * var(--bubble-text,1));font-variant-numeric:tabular-nums;white-space:nowrap;
  /* Марка ловит клик, как имя разреза: клик по ней выбирает ось (021) */
  pointer-events:auto;cursor:pointer;user-select:none;
}
/* display:flex выше перебивает встроенное правило для [hidden]: без этой
   строки марка с концом за кадром оставалась у края, где её поставили
   последний раз (117) */
.grid-bubble[hidden]{display:none}
/* Конец оси заслонён моделью в 3D (117): марку не видно и мышь она не ловит */
.grid-bubble.occluded{display:none}
#theme:checked ~ .app .grid-bubble{border-color:#8c9eff;color:#8c9eff}
/* Чертёжный стиль вида (163): марка тушью, как на листе; на тёмной теме — светлой */
.grid-layer.drafting .grid-bubble{border-color:#000;color:#000;border-width:1px}
#theme:checked ~ .app .grid-layer.drafting .grid-bubble{border-color:#e6e6e6;color:#e6e6e6}
/* Под курсором и у выбранной оси — бирюзовая, как выбранные стена и разрез */
.grid-bubble:hover,
.grid-bubble.selected{border-color:#1a9c90;color:#1a9c90}
#theme:checked ~ .app .grid-bubble:hover,
#theme:checked ~ .app .grid-bubble.selected{border-color:#4fd8cb;color:#4fd8cb}

/* Марка будущей оси: бледнее построенных — ось ещё не часть проекта. Мышь
   не ловит: иначе резинка спотыкалась бы о собственную марку */
.grid-bubble.preview{opacity:.55;border-style:dashed;pointer-events:none}

/* В режиме построения марки мышь не ловят: конец оси — первое, к чему
   притягивается курсор (046-a), и клик по нему принадлежит режиму */
.app.build-mode .grid-bubble{pointer-events:none}

/* ---------- обозначение разреза ---------- */
/* Слой имён разрезов — как слой марок осей, но имя ловит мышь: клик по
   нему выбирает разрез, двойной открывает вид. Это наш собственный
   элемент, и двойной клик по холсту у просмотрщика мы не трогаем
   (задача 035). */
.section-layer{position:absolute;inset:0;pointer-events:none;z-index:2;overflow:hidden}

/* Знак разреза по ГОСТ (091) рисуется на холсте панели, как отметки
   уровня; над каждым обозначением у стрелки лежит прозрачная мишень того
   же размера. Начало координат мишени — центр строки. */
.section-mark-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
.section-label{
  position:absolute;left:0;top:0;transform:translate(-50%,-50%);
  box-sizing:border-box;overflow:hidden;
  color:transparent;font-size:0;white-space:nowrap;
  pointer-events:auto;cursor:pointer;user-select:none;
}

/* Обозначение будущего разреза мышь не ловит — иначе резинка
   спотыкалась бы о собственную подпись */
.section-label.preview{pointer-events:none}

/* Маркер фрагмента (095) — штриховая рамка и выноска на холсте панели;
   над именем на полке — прозрачная мишень, как у разреза: двойной клик
   открывает фрагмент. Ручки рамки — у слоя подрезки. */
.callout-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
.callout-targets{position:absolute;inset:0;pointer-events:none;z-index:2;overflow:hidden}

/* Помещения (008) — заливка контура и марки на холсте панели, под
   аннотациями. Выбор по марке ищет сцена (`roomAt`), мишеней нет. */
.room-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:1}
/* Чертёжный стиль (156) — элементы модели кодом листа, под помещениями */
.drafting-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:1}
.callout-label{
  position:absolute;left:0;top:0;transform:translate(-50%,-50%);
  box-sizing:border-box;overflow:hidden;
  color:transparent;font-size:0;white-space:nowrap;
  pointer-events:auto;cursor:pointer;user-select:none;
}

/* Кнопка в панели свойств: «Перевернуть». Оформлена как поле ввода,
   чтобы стоять в строке наравне с ними. */
.prop-button{
  height:24px;padding:0 10px;border-radius:6px;cursor:pointer;
  border:1px solid var(--m-outline-var);
  background:var(--m-s-cont);color:var(--text);font:inherit;font-size:12px;
}
.prop-button:hover{background:var(--m-s-high)}

/* Сторона фасада (048): четыре кнопки С/Ю/З/В в ряд, нажатая — подсвечена */
.prop-segmented{display:inline-flex;gap:3px}
.prop-segmented .prop-button{padding:0 8px}
.prop-segmented .prop-button.on{background:var(--m-s-high);border-color:var(--accent, #1a9c90)}

/* Маркер фасада на плане (048): мишень над кружком — клик выбирает,
   двойной клик открывает вид */
.elevation-marker{
  position:absolute;left:0;top:0;transform:translate(-50%,-50%);
  box-sizing:border-box;border-radius:50%;
  pointer-events:auto;cursor:pointer;user-select:none;
}
.elevation-marker.preview{pointer-events:none}

/* Пункт блока «Примечания» (096): поле на всю строку и три кнопки за ним */
.note-item{display:flex;align-items:center;gap:3px}
.note-item .prop-input{flex:1;min-width:0}
.note-item-btn{padding:0 6px}
.note-item-btn:disabled{opacity:.45;cursor:default}

/* Поле с переводом (106-a): значок языка за полем, строки UZ и EN под ним */
.prop-translated{display:flex;align-items:center;gap:3px}
.prop-translated .prop-input{flex:1;min-width:0}
.prop-lang{padding:0 4px;display:inline-flex;align-items:center}
.prop-lang .ico{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.6}
.prop-lang[aria-pressed="true"]{background:var(--m-s-high)}
.prop-translations[hidden]{display:none}
.prop-translation .k{padding-left:12px;font-size:11px}

/* Комплект (102): фамилия и дата подписанта в одной строке; ревизии —
   шесть узких колонок штампа и кнопка удаления */
.prop-row .v.signatory-fields{display:flex;gap:4px;min-width:0}
.signatory-fields .prop-input{flex:1;min-width:0;width:auto}
.signatory-fields .prop-input-date{flex:0 0 82px}
.revision-list{display:flex;flex-direction:column;gap:3px;margin:4px 16px}
/* Дата — самая длинная графа: ей вдвое больше места */
.revision-row{
  display:grid;gap:3px;align-items:center;
  grid-template-columns:repeat(3,minmax(0,.8fr)) repeat(2,minmax(0,1.1fr)) minmax(0,2fr) 22px;
}
.revision-row .prop-input{width:auto;min-width:0}
.revision-head{font-size:11px;color:var(--m-on-variant);text-align:center}
.revision-row .prop-button{padding:0}

/* ---------- линии детализации ---------- */
/* Список стилей в группе ленты (047-0): та же строка «подпись — список»,
   что в строке параметров, только стоит среди кнопок */
.ribbon-field{align-self:center;padding:0 3px;font-size:12px}
/* Подпись списка и числа — над полем, как у кнопок: сбоку она
   удваивала ширину поля. Флажок остаётся в строке. Поле ниже, чем в
   палитре: столбик из двух полей с подписями укладывается в высоту
   ленты. */
.ribbon-field:not(:has(input[type="checkbox"])){
  flex-direction:column;align-items:flex-start;gap:1px;font-size:11px;line-height:1.15;
}
.ribbon-field .prop-input{height:22px;padding-top:2px;padding-bottom:2px}
.ribbon-field select{max-width:150px}
/* Числа в ленте короткие (2,5 или 90): узкое поле экономит ширину ленты */
.ribbon-field input.prop-input[type="number"]{width:52px}

/* Плоский холст поверх кадра панели (задача 047-0): толщина и штрих
   линии — в пикселях по миллиметрам бумаги, чего линии сцены не умеют.
   Мышь холст не ловит: клик по линии находит рендерер по расстоянию на
   экране, как у осей. Ниже ручек — их тянут поверх линии. */
.detail-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Опорные плоскости формы объекта (O-002) — такой же холст: след на всю
   рамку панели, клик находит рендерер по расстоянию */
.plane-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Рамка подрезки вида (030-a): служебная, мышь не ловит */
.crop-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Размеры (047-a) — на таком же холсте, поверх линий: число должно
   читаться и там, где линии пересекаются */
.dimension-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Текст (047-b) — на таком же холсте; клик по строке находит рендерер
   по её рамке на экране */
.text-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Выноски и марки (047-c) — на таком же холсте; клик по строке, рамке
   или линии находит рендерер */
.tag-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Отметки и марки осей на разрезе (090) — на таком же холсте */
.level-mark-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Выноски состава (176) — на таком же холсте */
.layer-callout-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Знаки уклона (177) — на таком же холсте */
.slope-mark-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Линии уровней со знаками на разрезе и фасаде (126) — тоже */
.level-line-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}
/* Флажки зон отделки на фасаде (048-b) — тоже */
.facade-zone-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2}

/* ---------- ручки элемента ---------- */
/* Слой ручек — единственный из наложенных слоёв, который ловит мышь:
   ручку тянут. Событие при этом не доходит до холста, и камера не едет —
   ради этого ручки и сделаны элементами страницы (задача 033). */
.handle-layer{position:absolute;inset:0;pointer-events:none;z-index:3;overflow:hidden}

.scene-handle{
  position:absolute;left:0;top:0;transform:translate(-50%,-50%);
  width:9px;height:9px;box-sizing:border-box;
  border:1.4px solid #1a9c90;background:var(--m-s-low);
  pointer-events:auto;cursor:grab;
}
/* Квадрат — конец, круг — середина: разные ручки делают разное, и
   различать их надо не наведением, а взглядом */
.scene-handle.move{border-radius:50%}
/* Ромб — поворот (005-b): тянут по кругу, а не в точку */
.scene-handle.rotate{transform:translate(-50%,-50%) rotate(45deg);cursor:alias}
.scene-handle:hover{background:#1a9c90}
.scene-handle.dragging{cursor:grabbing;background:#1a9c90}
/* Ручка, выбранная щелчком (076): на ней манипулятор, стрелки двигают
   только её. Крупнее и залита — видно издалека, какой конец выбран */
.scene-handle.active{width:11px;height:11px;background:#1a9c90;box-shadow:0 0 0 2px var(--m-s-low)}
#theme:checked ~ .app .scene-handle.active{background:#4fd8cb}
#theme:checked ~ .app .scene-handle{border-color:#4fd8cb}
#theme:checked ~ .app .scene-handle:hover,
#theme:checked ~ .app .scene-handle.dragging{background:#4fd8cb}

/* В режиме построения ручек нет: клик по холсту принадлежит режиму, и
   ручка, попавшая под курсор, отбирала бы у него точку. Признак общий —
   тот же класс, которым все режимы метят оболочку. */
.app.build-mode .handle-layer{display:none}

/* ---------- манипулятор перемещения (076) ---------- */
/* Свой слой под слоем ручек: круг ручки середины ложится поверх начала
   стрелок. Режим построения слой не прячет — во время перемещения по
   нему рисуется линия оси; прячутся только стрелки. Цвета осей — как
   принято в 3D-редакторах: X красный, Y зелёный, Z синий. */
.move-gizmo-layer{position:absolute;inset:0;pointer-events:none;z-index:3;overflow:hidden}
.move-gizmo{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
.move-gizmo .axis-x{--gizmo:#e5484d}
.move-gizmo .axis-y{--gizmo:#46a758}
.move-gizmo .axis-z{--gizmo:#3e8ef7}
.move-gizmo .gizmo-arrow{pointer-events:auto;cursor:grab}
.move-gizmo .gizmo-hit{stroke:transparent;stroke-width:14px}
.move-gizmo .gizmo-shaft{stroke:var(--gizmo);stroke-width:2px}
.move-gizmo .gizmo-head{fill:var(--gizmo)}
.move-gizmo .gizmo-arrow:hover .gizmo-shaft{stroke-width:3px}
.move-gizmo .gizmo-guide{stroke:var(--gizmo);stroke-width:1px;stroke-dasharray:6 4;opacity:.85}
.move-gizmo .gizmo-label{fill:#3e8ef7;font:600 12px/1 system-ui,sans-serif;paint-order:stroke;stroke:var(--m-s-low);stroke-width:3px}
.app.build-mode .move-gizmo .gizmo-arrow{display:none}
/* Стрелку, которую тянут, не видно, но она остаётся в странице: на ней
   захват указателя до отпускания */
.move-gizmo .gizmo-arrow.held{opacity:0}
/* Режим перемещения (020): ввод занят, как у построения, но ручки и
   стрелки видны — их тянут. Пока ручка в руке, класса на слое нет */
.app.build-mode .handle-layer.move-mode{display:block}
.app.build-mode .move-gizmo-layer.move-mode .move-gizmo .gizmo-arrow{display:inline}
/* Вектор от базовой точки к курсору (020). Не цвет оси — сдвиг
   свободный, ни к одной оси не прижат */
.move-gizmo .gizmo-vector-line{stroke:var(--m-primary);stroke-width:1.5px;stroke-dasharray:6 4}
.move-gizmo .gizmo-vector-head{fill:var(--m-primary)}

/* ---------- маркер привязки ---------- */
/* Поверх ручек и в режиме построения тоже: маркер показывает, куда пойдёт
   построение. Мышь слой не ловит вовсе (задача 046-a). Форма — знаком
   вида, как в Revit: квадрат у конца, треугольник у середины, крест у
   пересечения; размер в пикселях, от зума не зависит. */
.snap-layer{position:absolute;inset:0;pointer-events:none;z-index:4;overflow:hidden}

/* Тот же знак — значком в кнопке и строке меню (046-c): .snap-icon стоит
   в потоке, а не у точки холста; форма по виду общая с маркером */
.snap-marker{
  position:absolute;left:0;top:0;transform:translate(-50%,-50%);
  width:13px;height:13px;box-sizing:border-box;
  color:#1a9c90;pointer-events:none;
}
.snap-icon{
  position:relative;display:inline-block;flex:none;
  width:13px;height:13px;box-sizing:border-box;color:#1a9c90;pointer-events:none;
}
:is(.snap-marker,.snap-icon).end{border:1.6px solid currentColor}
:is(.snap-marker,.snap-icon).mid{
  width:0;height:0;border-left:7px solid transparent;border-right:7px solid transparent;
  border-bottom:13px solid currentColor;
}
.snap-marker.mid{transform:translate(-50%,-55%)}
:is(.snap-marker,.snap-icon).intersection::before,
:is(.snap-marker,.snap-icon).intersection::after{
  content:"";position:absolute;left:50%;top:50%;width:17px;height:1.6px;
  background:currentColor;transform:translate(-50%,-50%) rotate(45deg);
}
:is(.snap-marker,.snap-icon).intersection::after{transform:translate(-50%,-50%) rotate(-45deg)}
/* Перпендикуляр — знак ⊥: стойка и основание */
:is(.snap-marker,.snap-icon).perpendicular::before{
  content:"";position:absolute;left:50%;top:0;width:1.6px;height:13px;
  background:currentColor;transform:translateX(-50%);
}
:is(.snap-marker,.snap-icon).perpendicular::after{
  content:"";position:absolute;left:0;bottom:0;width:13px;height:1.6px;background:currentColor;
}
/* Ближайшая точка — ромб */
:is(.snap-marker,.snap-icon).nearest{border:1.6px solid currentColor}
.snap-marker.nearest{transform:translate(-50%,-50%) rotate(45deg)}
.snap-icon.nearest{transform:rotate(45deg)}
/* Узел фоновой сетки — кружок: меньше и тише знаков геометрии */
:is(.snap-marker,.snap-icon).grid{width:9px;height:9px;border:1.6px solid currentColor;border-radius:50%}
/* Продолжение (060) — три точки вдоль направления; пунктирная нить — отдельный элемент */
:is(.snap-marker,.snap-icon).extension{
  background:radial-gradient(circle,currentColor 1.6px,transparent 1.8px) 0 50%/5px 5px repeat-x;
  height:5px;width:15px;
}
/* Параллель — две косые черты */
:is(.snap-marker,.snap-icon).parallel::before,
:is(.snap-marker,.snap-icon).parallel::after{
  content:"";position:absolute;top:0;width:1.6px;height:13px;background:currentColor;transform:rotate(30deg);
}
:is(.snap-marker,.snap-icon).parallel::before{left:3px}
:is(.snap-marker,.snap-icon).parallel::after{left:9px}
/* Точка вставки — два квадрата со сдвигом, как метка вставки блока */
:is(.snap-marker,.snap-icon).insertion::before,
:is(.snap-marker,.snap-icon).insertion::after{
  content:"";position:absolute;width:8px;height:8px;border:1.6px solid currentColor;box-sizing:border-box;
}
:is(.snap-marker,.snap-icon).insertion::before{left:0;top:0}
:is(.snap-marker,.snap-icon).insertion::after{right:0;bottom:0}
/* Ждущие виды — значки только в окне: центр — кружок, узел — кружок с
   крестом, квадрант — ромб, касательная — кружок с чертой сверху, мнимое
   пересечение — крест в квадрате */
:is(.snap-marker,.snap-icon).center,:is(.snap-marker,.snap-icon).node,:is(.snap-marker,.snap-icon).tangent{
  border:1.6px solid currentColor;border-radius:50%;
}
:is(.snap-marker,.snap-icon).node::before,:is(.snap-marker,.snap-icon).node::after{
  content:"";position:absolute;left:50%;top:50%;width:13px;height:1.6px;background:currentColor;
  transform:translate(-50%,-50%) rotate(45deg);
}
:is(.snap-marker,.snap-icon).node::after{transform:translate(-50%,-50%) rotate(-45deg)}
:is(.snap-marker,.snap-icon).tangent::before{
  content:"";position:absolute;left:-2px;top:-3px;width:15px;height:1.6px;background:currentColor;
}
:is(.snap-marker,.snap-icon).quadrant{border:1.6px solid currentColor}
.snap-marker.quadrant{transform:translate(-50%,-50%) rotate(45deg)}
.snap-icon.quadrant{transform:rotate(45deg)}
:is(.snap-marker,.snap-icon).apparent{border:1.6px solid currentColor}
:is(.snap-marker,.snap-icon).apparent::before,:is(.snap-marker,.snap-icon).apparent::after{
  content:"";position:absolute;left:50%;top:50%;width:12px;height:1.6px;background:currentColor;
  transform:translate(-50%,-50%) rotate(45deg);
}
:is(.snap-marker,.snap-icon).apparent::after{transform:translate(-50%,-50%) rotate(-45deg)}
#theme:checked ~ .app :is(.snap-marker,.snap-icon){color:#4fd8cb}

/* Знаки захвата (060): метка у захваченного конца, значок параллели на
   образце, пунктирная нить продолжения — от конца к точке под курсором */
.snap-capture{
  position:absolute;left:0;top:0;width:17px;height:17px;box-sizing:border-box;
  transform:translate(-50%,-50%);border:1.6px dashed #1a9c90;pointer-events:none;
}
.snap-capture[hidden],.snap-sample[hidden],.snap-thread[hidden]{display:none}
.snap-sample{position:absolute;left:0;top:0;transform:translate(-50%,-50%);pointer-events:none}
.snap-thread{
  position:absolute;left:0;top:0;height:0;border-top:1.2px dashed #1a9c90;
  transform-origin:0 0;pointer-events:none;opacity:.8;
}
#theme:checked ~ .app .snap-capture,#theme:checked ~ .app .snap-thread{border-color:#4fd8cb}

/* ---------- сетка разового переопределения вида (046-c) ---------- */
/* Открыта по Shift с правой кнопкой; пока открыта, мышь ловит только
   слой — клик мимо значков закрывает сетку без замены */
.snap-override-layer{position:absolute;inset:0;z-index:7;overflow:hidden;pointer-events:auto}
.snap-override-layer[hidden]{display:none}
.snap-override{
  position:absolute;left:0;top:0;display:grid;grid-template-columns:repeat(3,28px);gap:2px;
  padding:4px;border-radius:6px;background:var(--m-surface);color:var(--m-on-surface);
  border:1px solid var(--m-outline-var);box-shadow:0 4px 14px rgba(0,0,0,.18);
}
.snap-override-item{
  width:28px;height:28px;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer;padding:0;
}
.snap-override-item:hover{background:var(--m-hover)}
.snap-override-item .snap-icon{pointer-events:none}

/* ---------- кнопка «Привязки» в строке состояния и окно (046-c, 060) ---------- */
.sb-snap-wrap{position:relative;display:inline-flex}
/* Кнопка с рамкой и запасом ширины: прозрачная надпись в строке
   состояния терялась среди текста, и её не находили (замечание владельца) */
.sb-snap{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-width:120px;height:22px;padding:0 14px;box-sizing:border-box;
  border:1px solid var(--m-outline-var);border-radius:4px;background:transparent;
  color:inherit;font:inherit;cursor:pointer;
}
.sb-snap:hover{background:var(--m-hover);border-color:var(--m-outline)}
/* Хоть один вид снят или выключатель снят — значок кнопки гаснет наполовину */
.sb-snap.partial .snap-icon{opacity:.45}
.sb-snap .snap-icon{width:12px;height:12px}
/* Окно «Привязки» — разметка и стили окна видимости (vs-*), свои только
   строки: значок вида перед подписью, подсказка у ждущего вида */
.ss-row .snap-icon{margin-right:8px;vertical-align:middle}
.ss-row.pending td{color:var(--m-on-variant);opacity:.6}
.ss-hint{display:block;font-size:11.5px;opacity:.8}
.ss-master{display:flex;align-items:center;gap:8px;padding:10px 18px 4px;font-size:13px}

/* ---------- поле длины и угла у курсора ---------- */
/* Открывается первой набранной цифрой и стоит там, где был курсор.
   Слой мышь не ловит, само поле — ловит: в него печатают (046-b). */
.dim-layer{position:absolute;inset:0;pointer-events:none;z-index:6;overflow:hidden}

/* display:flex перебил бы атрибут hidden — у него стиль браузера с
   меньшим приоритетом; закрытое поле прячется отдельным правилом */
.dim-field[hidden]{display:none}
.dim-field{
  position:absolute;left:0;top:0;pointer-events:auto;
  display:flex;gap:10px;align-items:center;
  padding:5px 10px;border-radius:10px;
  background:var(--m-s-low);color:var(--text);box-shadow:var(--m-e2);
  font-size:12px;white-space:nowrap;
}
.dim-item{display:flex;gap:5px;align-items:center}
.dim-caption{opacity:.75}
.dim-unit{opacity:.75}
.dim-input{
  width:64px;padding:2px 5px;box-sizing:border-box;
  border:1px solid var(--m-outline,#8a8a8a);border-radius:5px;
  background:var(--m-s-cont);color:var(--text);font:inherit;text-align:right;
}
.dim-input:focus{outline:1.5px solid #1a9c90;outline-offset:0}
/* Текст, который не разбирается: та же подсветка, что у полей свойств */
.dim-input.bad{outline:1px solid #c5442f;outline-offset:0}
#theme:checked ~ .app .dim-input:focus{outline-color:#4fd8cb}

/* Поле текста у точки вставки (047-b): левый нижний угол поля — точка
   вставки, как у самой строки, поэтому поле поднято на свою высоту.
   Кегль задаёт скрипт — тот, которым строка нарисована на холсте. */
.text-note-field{
  position:absolute;left:0;top:0;transform:translateY(-100%);pointer-events:auto;
  min-width:120px;padding:1px 4px;box-sizing:content-box;
  border:1px solid #1a9c90;border-radius:3px;outline:none;
  background:var(--m-s-low);color:var(--text);box-shadow:var(--m-e2);
  font-family:inherit;line-height:1.15;
}
.text-note-field[hidden]{display:none}
#theme:checked ~ .app .text-note-field{border-color:#4fd8cb}

/* Поле многострочного текста в рамке (047-h): левый верхний угол поля —
   угол рамки. Кегль, шаг строк и ширину задаёт скрипт по блоку на
   холсте; высота растёт вместе с текстом. */
.text-block-field{
  position:absolute;left:0;top:0;pointer-events:auto;
  padding:1px 4px;box-sizing:content-box;resize:none;overflow:hidden;
  border:1px solid #1a9c90;border-radius:3px;outline:none;
  background:var(--m-s-low);color:var(--text);box-shadow:var(--m-e2);
  font-family:inherit;
}
.text-block-field[hidden]{display:none}
#theme:checked ~ .app .text-block-field{border-color:#4fd8cb}

/* Текст блока в палитре свойств: многострочное поле во всю колонку */
.prop-textarea{width:100%;box-sizing:border-box;resize:vertical;line-height:1.3;font-family:inherit}

/* ---------- строка параметров построения ---------- */
/* Появляется вместе с режимом и ложится поверх вкладок видов: она про то,
   чем строят сейчас, и уходить за ней в палитру незачем. */
.options-bar{
  position:absolute;left:50%;top:6px;transform:translateX(-50%);z-index:5;
  display:flex;gap:16px;align-items:center;
  padding:6px 14px;border-radius:18px;
  background:var(--m-s-low);color:var(--text);box-shadow:var(--m-e2);
  font-size:12.5px;
}
.options-field{display:flex;gap:8px;align-items:center;white-space:nowrap}
.options-field select{max-width:190px}

/* ---------- режим построения ---------- */
/* Пока режим включён, курсор над холстом — перекрестье: пользователь
   должен видеть, что клик сейчас ставит точку, а не выбирает тело. */
.app.build-mode .scene3d{cursor:crosshair}

/* ---------- свойства уровня ---------- */
/* Поле, значение которого модель не приняла: подсветка снимается вводом.
   Обводкой, а не рамкой: .prop-input просмотрщика рисуется без неё, и
   рамка сдвинула бы соседние строки. */
.prop-input.bad{outline:1px solid #c5442f;outline-offset:0}
/* Подсказка по книге у лестницы (183) и порог уклона пандуса (184):
   предупреждение строкой, не запрет */
.stair-hint{display:block;margin:0;padding:3px 16px 5px;font-size:11px;color:#c5442f}

/* ---------- окна агентов (071-a) ----------
   Панель справа поверх рабочей области: выше палитр дока, ниже
   плавающих палитр и диалогов. Ширину ставит код, правый край прижат. */
.agent-window{
  position:absolute;top:8px;right:8px;bottom:8px;z-index:30;
  width:380px;display:flex;flex-direction:column;min-height:0;
  background:var(--m-s-lowest);color:var(--text);
  border:1px solid var(--m-outline-var);border-radius:12px;box-shadow:var(--m-e2);
  overflow:hidden;
}
.agent-window[hidden]{display:none}
.agent-resize{position:absolute;left:0;top:0;bottom:0;width:6px;cursor:col-resize;z-index:1;touch-action:none}
.agent-resize:hover{background:var(--accent);opacity:.35}
.agent-head{display:flex;align-items:center;gap:8px;padding:10px 10px 8px 14px;border-bottom:1px solid var(--m-outline-var)}
.agent-head .ico{width:20px;height:20px;flex:none;color:var(--m-on-variant)}
.agent-title{flex:1;margin:0;font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.agent-close{
  width:28px;height:28px;border:0;border-radius:8px;background:transparent;
  color:var(--m-on-variant);font-size:20px;line-height:1;cursor:pointer;
}
.agent-close:hover{background:var(--m-hover)}
/* Очистить историю (133): только в браузере, переписка на сервере остаётся */
.agent-clear{
  height:28px;padding:0 8px;border:0;border-radius:8px;background:transparent;
  color:var(--m-on-variant);font:inherit;font-size:12px;cursor:pointer;
}
.agent-clear:hover:not(:disabled){background:var(--m-hover)}
.agent-clear:disabled{opacity:.4;cursor:default}
.agent-clear[hidden]{display:none}
/* Настройки агентов (134): выбор модели строками с пометкой */
.agent-providers{border:0;margin:0 0 8px;padding:0;display:flex;flex-direction:column;gap:6px}
.agent-providers legend{padding:0;margin-bottom:6px;font-size:12px;color:var(--m-on-variant)}
.agent-provider{display:grid;grid-template-columns:auto 1fr;column-gap:8px;align-items:center;cursor:pointer;font-size:13px}
.agent-provider input{margin:0}
.agent-provider-name{font-weight:600}
.agent-provider-note{grid-column:2;font-size:11px;color:var(--m-on-variant)}
.agent-lane{padding:6px 14px;font-size:12px;font-weight:600;background:var(--m-secondary-c);color:var(--m-on-secondary-c)}
.agent-lane[hidden]{display:none}
.agent-lane[data-state="unavailable"]{background:var(--m-s-high);color:var(--m-on-variant)}
.agent-description{margin:0;padding:8px 14px;font-size:12px;color:var(--m-on-variant)}
.agent-chat{flex:1;display:flex;flex-direction:column;min-height:0}
.agent-messages{flex:1;min-height:0;overflow-y:auto;padding:6px 14px;display:flex;flex-direction:column;gap:8px}
.agent-msg{align-self:flex-end;max-width:88%}
/* Пример переписки в пустой истории: рамка пунктиром и подпись отделяют
   его от настоящих сообщений; ответ агента — слева, как в чате */
.agent-example{
  display:flex;flex-direction:column;gap:8px;padding:8px 10px;
  border:1px dashed var(--m-outline-var);border-radius:12px;
}
.agent-example-label{font-size:11px;color:var(--m-on-variant)}
.agent-msg.reply{align-self:flex-start}
.agent-msg.reply .agent-msg-text{
  border-radius:12px 12px 12px 4px;
  background:var(--m-s-cont);color:var(--text);
}
.agent-msg.example .agent-msg-text{opacity:.8}
.agent-msg-text{
  padding:7px 11px;border-radius:12px 12px 4px 12px;
  background:var(--m-primary-c);color:var(--m-on-primary-c);
  font-size:13px;line-height:1.4;white-space:pre-wrap;overflow-wrap:anywhere;
}
.agent-msg.outgoing .agent-msg-text{opacity:.7}
.agent-msg-note{margin-top:3px;font-size:11px;color:var(--m-on-variant);text-align:right}
.agent-msg-note.failed,.agent-msg-note.limit{color:#b3261e}
/* Согласие на хранение переписки (130) — над полем ввода */
.agent-consent{display:flex;gap:8px;align-items:flex-start;padding:6px 14px 0;font-size:12px;line-height:1.35;color:var(--m-on-variant);cursor:pointer}
.agent-consent[hidden]{display:none}
.agent-consent input{margin:2px 0 0;flex:none}
.agent-waiting{padding:4px 14px;font-size:12px;color:var(--m-on-variant)}
.agent-waiting[hidden]{display:none}
.agent-form{display:flex;gap:6px;align-items:flex-end;padding:8px 10px 4px}
.agent-input{
  flex:1;min-height:40px;max-height:160px;resize:vertical;padding:7px 9px;
  border:1px solid var(--m-outline-var);border-radius:8px;
  background:var(--m-s-lowest);color:var(--text);font:inherit;font-size:13px;
}
.agent-input:focus{outline:2px solid var(--m-primary);outline-offset:-1px}
.agent-send{
  padding:8px 12px;border:0;border-radius:8px;cursor:pointer;
  background:var(--m-primary);color:var(--m-on-primary);font:inherit;font-size:13px;font-weight:600;
}
.agent-privacy{padding:2px 12px 10px;font-size:10.5px;color:var(--m-on-variant)}

/* ---------- вкладка-сетка ведомости (097) ----------
   Цвет ячейки — куда пойдёт правка (анализ эталонов, 6.5): белая —
   свойство типа, голубая — экземпляра, серая — вычисляется */
.schedule-grid{max-width:none}
.schedule-table td.sched-type{background:var(--m-s-lowest);cursor:text}
.schedule-table td.sched-instance{background:color-mix(in srgb, #3d8bd4 16%, var(--m-s-lowest));cursor:text}
.schedule-table td.sched-computed{background:var(--m-s-cont);color:var(--m-on-variant)}
.schedule-table td.bad{outline:2px solid #b3261e;outline-offset:-2px}
.schedule-table tr.sched-group td{font-weight:600;background:var(--m-s-high)}
.schedule-table tr.sched-underline td{text-decoration:underline}
.schedule-table tr.sched-subtotal td{font-weight:600}
.schedule-table input.sched-edit{
  font:inherit;width:100%;min-width:6em;box-sizing:border-box;padding:2px 4px;
  border:1px solid var(--m-primary);border-radius:4px;background:var(--m-s-lowest);color:var(--text);
}
/* Строки легенды флажками в панели таблицы (098) */
.prop-checks{display:flex;flex-direction:column;gap:2px}
.prop-check{display:flex;align-items:center;gap:4px;cursor:pointer}

/* Диалог «Структура типа» (041-a): таблица слоёв шире обычного диалога */
.dlg-wide{width:min(720px,94vw)}
.dlg-text.muted{color:var(--m-on-variant);font-size:11.5px}
.structure-table-wrap{max-height:320px;overflow:auto;border:1px solid var(--m-outline-var);border-radius:8px}
.structure-table{width:100%;border-collapse:collapse;font-size:12px}
.structure-table th{position:sticky;top:0;background:var(--m-s-cont);text-align:left;font-weight:600;padding:6px 8px}
.structure-table td{padding:3px 6px;border-top:1px solid var(--m-outline-var)}
.structure-table tr.cur td{background:var(--m-s-high)}
.structure-table select,.structure-table input{
  width:100%;height:28px;padding:0 6px;border-radius:6px;box-sizing:border-box;
  border:1px solid var(--m-outline-var);background:var(--m-surface);color:var(--text);font:inherit;font-size:12px;
}
.structure-table input.bad{border-color:#c5442f}
.structure-table td.num{width:28px;text-align:right;color:var(--m-on-variant);cursor:pointer}
.structure-table .structure-new{margin-top:3px}
.structure-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.structure-total{margin-left:auto;font-size:12.5px;font-weight:600}

/* Диалог «Сетка и заполнения» витража (100): оси в строку, ячейки — как фасад, верхний ряд сверху */
.curtain-axes{display:flex;gap:12px;flex-wrap:wrap}
.curtain-axes .dlg-field{flex:1 1 220px}
.curtain-axes select{height:28px;border-radius:6px;border:1px solid var(--m-outline-var);background:var(--m-surface);color:var(--text);font:inherit;font-size:12px}
.curtain-cells{border-collapse:collapse;font-size:12px;margin:6px}
.curtain-cells th{font-weight:600;color:var(--m-on-variant);padding:2px 6px;text-align:center}
.curtain-cells td{border:1px solid var(--m-outline-var);padding:4px;vertical-align:top;min-width:120px}
.curtain-cells select{width:100%;height:26px;border-radius:6px;border:1px solid var(--m-outline-var);background:var(--m-surface);color:var(--text);font:inherit;font-size:12px}
.curtain-cells label{display:inline-flex;align-items:center;gap:3px;margin-top:3px;margin-right:6px;font-size:11px;color:var(--m-on-variant)}


/* «Линия обрыва» в панели вида (178): четыре флажка сторон в строку, переносятся по ширине панели */
.crop-edges{display:inline-flex;flex-wrap:wrap;align-items:center;gap:2px 8px}
.crop-edges label{display:inline-flex;align-items:center;gap:3px;white-space:nowrap;font-size:12px}
