:root{
  --bg:#05080c; --panel:#0a0f16; --panel2:#0d131c;
  --line:#1c2733; --line-soft:#141c26;
  --text:#dbe6ef; --dim:#5f7688; --dim2:#3d4d5c;
  /* Пунктирные рамки блоков. Отдельно от --dim намеренно: штрихи усредняются с
     фоном, и при равном цвете рамка выглядит светлее сплошной. Здесь на тон
     контрастнее, чтобы вес совпадал на глаз, а не в значениях. */
  --map-dash:#8aa3b6;
  --accent:#34d5ff; --accent-dim:#1a5f75;
  --green:#3ddc84; --green-dim:#155c37;
  --red:#ff5470; --red-dim:#5c1524; --danger:var(--red);
  --orange:#ffb648; --orange-dim:#5c3d10;
  --purple:#b48cff; --purple-dim:#3a2a5c;
  /* Розовый - только под "локация не указана". Не берём --red-dim: это не ошибка
     расчёта, а незаполненные данные, и путать их не нужно. */
  --pink:#ff7ab2; --pink-dim:#5c2038;
  /* «Подставлено само» (из фильтра, от проекта выше, по умолчанию, из «Времени»): жёлтая рамка и фон. */
  --auto:#ffd23f; --auto-bg:rgba(255,210,63,0.12);
  --mono:'JetBrains Mono',ui-monospace,Menlo,Consolas,monospace;
  /* Наименьшая ширина окон списков на карте - от неё же считается наименьшая
     ширина самой панели карты в разделённом экране. */
  --map-side-min:340px;
  /* Масштаб интерфейса. Вынесен в переменную, потому что от него зависит не только
     сам zoom: единицы vh зум не учитывают, и всякую высоту "в целый экран" внутри
     body приходится делить на этот множитель. Тот же множитель читает uiZoom(). */
  --ui-zoom:1.2;
  /* Карта мест (placemap.js): карта и подписи на ней всегда светлые, в любой теме. */
  --pm-bg:#f4f5f7; --pm-ink:#0b1620; --pm-halo:#ffffff;
  /* Просмотр мест (placeview.js): эскиз всегда светлый, как карта. */
  --pv-grey:#9aa6b2; --pv-grey-line:#8795a3; --pv-dark:#37475a; --pv-red:#ff1744;
  /* Вещи на карте (placething.js, placethingform.js): эскиз и карта всегда светлые. */
  --pt-fig:#00897b; --pt-check:#ff9800; --pt-w1:#ff6d00; --pt-w2:#3949ab; --pt-ink:#0b1620; --pt-halo:#ffffff;
  /* Размеры на карте (placedim.js): подписи лежат на светлой карте, цвета не зависят от темы. */
  --pd-ink:#4a148c; --pd-line:#7b1fa2; --pd-bad-ink:#b71c1c; --pd-bad-line:#d50000; --pd-bad-bg:#ffebee;
  --pd-ok-ink:#1b5e20; --pd-ok-line:#2e7d32; --pd-ok-bg:#e8f5e9; --pd-ruler-ink:#004d40; --pd-ruler-line:#00897b; --pd-angle-line:#455a64;
  /* Вид точек «Изменить контур» (placedim.js, PD_PT): свободная, держится одним размером, определена полностью - как на карте. */
  --pd-pt-free:#1565c0; --pd-pt-one:#1e88e5; --pd-pt-full:#111111; --pd-pt-ring:#ffffff; --pd-pt-edge:#9e9e9e;
}

/* Светлая тема. Переопределяем только переменные - вся остальная вёрстка
   опирается на них, поэтому отдельных правил под неё не требуется.
   Акценты взяты темнее исходных: на светлом фоне неоново-яркие цвета
   исходной палитры не читаются. */
body.light-theme{
  --bg:#f4f6f8; --panel:#ffffff; --panel2:#f0f3f6;
  --line:#c8d2dc; --line-soft:#dfe5eb;
  --text:#16202b; --dim:#5c7080; --dim2:#93a5b3;
  --map-dash:#3e5464;
  --accent:#0273a8; --accent-dim:#8fc9e4;
  --green:#137a45; --green-dim:#a5dcbe;
  --red:#c02040; --red-dim:#f2b8c3; --danger:var(--red);
  --orange:#a35c00; --orange-dim:#f0d2a0;
  --purple:#6a3fbf; --purple-dim:#d3c2f2;
  --pink:#c9337a; --pink-dim:#ffd4e6;
  --auto:#c79200; --auto-bg:rgba(199,146,0,0.12);
}

*{box-sizing:border-box; margin:0; padding:0;}
/* overscroll-behavior-y: contain - против «потянул вниз и страница перезагрузилась».
   На карте и в длинных списках жест вверх-вниз пальцем постоянно доходил до края
   прокрутки и запускал перезагрузку прямо посреди работы. */
html{ overscroll-behavior-y: contain; }
body{
  background:var(--bg); color:var(--text); font-family:var(--mono);
  min-height:calc(100vh / var(--ui-zoom)); font-size:13px; zoom:var(--ui-zoom); overscroll-behavior-y: contain;
  background-image:
    radial-gradient(circle at 15% 0%, rgba(52,213,255,0.06), transparent 40%),
    repeating-linear-gradient(0deg, rgba(255,255,255,0.012) 0px, rgba(255,255,255,0.012) 1px, transparent 1px, transparent 3px);
}
.hidden{display:none !important;}

/* ---------- ЛОГИН ---------- */
#login-screen{
  min-height:100vh; display:flex; align-items:center; justify-content:center; padding:20px;
}
.login-box{
  width:100%; max-width:360px; background:var(--panel); border:1px solid var(--line);
  padding:28px; position:relative;
  clip-path:polygon(18px 0,100% 0,100% calc(100% - 18px),calc(100% - 18px) 100%,0 100%,0 18px);
}
.login-box::before{
  content:''; position:absolute; inset:0; padding:1px;
  background:linear-gradient(135deg, rgba(52,213,255,0.5), rgba(52,213,255,0.05) 40%);
  clip-path:inherit; -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude; pointer-events:none;
}
.login-title{font-size:20px; font-weight:800; letter-spacing:1px; margin-bottom:24px;}
.field{margin-bottom:14px;}
.field label{display:block; font-size:10px; letter-spacing:1.5px; color:var(--dim); margin-bottom:6px; text-transform:uppercase;}
.field input{
  width:100%; background:var(--panel2); border:1px solid var(--line); color:var(--text);
  font-family:inherit; font-size:14px; padding:11px 12px; outline:none;
}
.field input:focus{border-color:var(--accent); box-shadow:0 0 0 1px var(--accent) inset;}
.login-error{color:var(--red); font-size:11px; min-height:16px; margin-bottom:8px;}
.btn-primary{
  width:100%; background:rgba(52,213,255,0.08); border:1px solid var(--accent); color:var(--accent);
  font-family:inherit; font-size:12px; font-weight:700; letter-spacing:1.5px; text-transform:uppercase;
  padding:12px; cursor:pointer; margin-top:6px;
}
.btn-primary:active{background:var(--accent); color:#04141c;}
.btn-primary:disabled{opacity:0.4; cursor:default;}
/* Пока идёт запрос - глухая заслонка поверх формы. Не просто disabled на кнопке:
   поля тоже должны быть недоступны, иначе человек правит логин, пока летит запрос
   со старым, и потом не понимает, почему ошибка не про то. */
.login-busy{
  position:absolute; inset:0; z-index:5; clip-path:inherit;
  display:flex; align-items:center; justify-content:center;
  cursor:progress;
}
/* Гасим саму форму прозрачностью, а не кладём сверху заливку: любой конкретный
   цвет верен только в одной теме, и на светлой он читался как грязно-серое пятно.
   Прозрачность работает одинаково в обеих - под ней просто фон окна. */
.login-box.busy > *:not(.login-busy){ opacity:0.25; transition:opacity 0.12s; }
.login-spinner{
  width:26px; height:26px; border-radius:50%;
  border:2px solid var(--line); border-top-color:var(--accent);
  animation:spin-loading-bar 0.7s linear infinite;
}

/* ---------- DASHBOARD ---------- */
#dashboard{min-height:calc(100vh / var(--ui-zoom)); display:flex; flex-direction:column;}

.topbar{
  display:flex; align-items:center; gap:16px; padding:12px 18px; border-bottom:1px solid var(--line);
  background:var(--panel); flex-wrap:nowrap;
  position:sticky; top:0; z-index:1000;
}
/* Единственное содержимое шапки - имя открытой вкладки. Вкладку тут не выбирают:
   выбор живёт в меню у нижнего края, до которого достаёт палец. */
.tb-tabname{
  flex-shrink:0; font-size:12px; letter-spacing:1.5px; text-transform:uppercase;
  color:var(--dim); white-space:nowrap;
}
/* При разделении экрана имена обеих вкладок стоят прямо над панелями и переключают
   их же - общая подпись в шапке только дублировала бы их. */
body.split-on .tb-tabname{ display:none; }
.status-dot{width:8px; height:8px; border-radius:50%; background:var(--dim2); flex-shrink:0;}
.status-dot.live{background:var(--green); box-shadow:0 0 8px var(--green); animation:pulse 1.6s ease-in-out infinite;}
.status-dot.err{background:var(--red); box-shadow:0 0 8px var(--red);}
@keyframes pulse{0%,100%{opacity:1;} 50%{opacity:0.35;}}
.status-text{font-size:11px; color:var(--dim);}
.tb-spacer{flex:1;}
.tb-controls{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
.tb-controls label{font-size:10px; color:var(--dim); letter-spacing:0.5px; display:flex; align-items:center; gap:6px;}
.tb-controls select, .tb-controls input[type=number]{
  background:var(--panel2); border:1px solid var(--line); color:var(--text); font-family:inherit;
  font-size:11px; padding:5px 8px;
}
.tb-btn{
  background:var(--panel2); border:1px solid var(--line); color:var(--dim); font-family:inherit;
  font-size:10px; letter-spacing:1px; text-transform:uppercase; padding:7px 12px; cursor:pointer;
}
.tb-btn:hover{border-color:var(--accent); color:var(--accent);}
.tb-btn.active{border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.08);}

#tab-feed > .tb-controls{padding:10px 18px; border-bottom:1px solid var(--line); background:var(--panel);}
.layout{flex:1; display:flex; min-height:0;}
.stock-panel{
  width:340px; flex-shrink:0; border-right:1px solid var(--line); background:var(--panel);
  display:flex; flex-direction:column; min-height:0;
}
.feed-panel{flex:1; display:flex; flex-direction:column; min-height:0;}

.panel-header{
  padding:12px 16px; border-bottom:1px solid var(--line); font-size:10px; letter-spacing:2px;
  color:var(--dim); text-transform:uppercase; display:flex; justify-content:space-between; align-items:center;
}
.panel-header .count{color:var(--accent); font-weight:700;}

.panel-search{padding:10px 12px; border-bottom:1px solid var(--line-soft);}
.panel-search input{
  width:100%; background:var(--panel2); border:1px solid var(--line); color:var(--text);
  font-family:inherit; font-size:12px; padding:8px 10px; outline:none;
}
.panel-search input:focus{border-color:var(--accent);}

.stock-list{flex:1; overflow-y:auto; padding:6px;}
.stock-row{
  padding:9px 10px; border-bottom:1px dashed var(--line-soft); font-size:12px;
  display:flex; flex-direction:column; gap:3px; position:relative;
}
.stock-row.flash{animation:flashRow 1.4s ease-out;}
@keyframes flashRow{0%{background:rgba(52,213,255,0.18);} 100%{background:transparent;}}
.stock-row.negative{border-left:2px solid var(--red);}
.stock-row-top{display:flex; justify-content:space-between; gap:8px; align-items:baseline;}
.stock-row-name{color:var(--text); font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.stock-row-qty{font-weight:800; font-size:13px; white-space:nowrap;}
.stock-row-qty.negative{color:var(--red);}
.stock-row-meta{font-size:10px; color:var(--dim);}
.stock-row-warn{font-size:10px; color:var(--red); font-weight:700;}

.feed-list{flex:1; overflow-y:auto; padding:6px 6px 40px;}
.feed-empty{color:var(--dim2); text-align:center; padding:60px 20px; font-size:12px; line-height:1.6;}

.event{
  border:1px solid var(--line); border-left-width:3px; background:var(--panel2);
  padding:10px 12px; margin-bottom:6px; cursor:pointer; animation:slideIn 0.25s ease-out;
}
@keyframes slideIn{from{opacity:0; transform:translateY(-6px);} to{opacity:1; transform:translateY(0);}}
.event.warn{background:rgba(255,84,112,0.06);}
.event-top{display:flex; justify-content:space-between; align-items:flex-start; gap:10px;}
.event-type{font-size:10px; font-weight:800; letter-spacing:1px; text-transform:uppercase; padding:2px 7px; border-radius:2px; white-space:nowrap;}
.event-time{font-size:10px; color:var(--dim); white-space:nowrap; flex-shrink:0;}
.event-body{margin-top:6px; font-size:12.5px; color:var(--text); line-height:1.5;}
.event-body b{color:#fff;}
.event-meta{margin-top:5px; font-size:10.5px; color:var(--dim); display:flex; gap:12px; flex-wrap:wrap;}
.event-warn-badge{color:var(--red); font-weight:800; margin-top:5px; font-size:11px;}
.event-raw{
  margin-top:8px; padding:8px 10px; background:var(--bg); border:1px solid var(--line-soft);
  font-size:10.5px; color:var(--dim); white-space:pre-wrap; word-break:break-all; display:none;
}
.event.open .event-raw{display:block;}

/* цвета по типам */
.event.type-delivery{border-left-color:var(--green);} .event.type-delivery .event-type{background:var(--green-dim); color:var(--green);}
.event.type-take{border-left-color:var(--orange);} .event.type-take .event-type{background:var(--orange-dim); color:var(--orange);}
.event.type-put{border-left-color:var(--accent);} .event.type-put .event-type{background:var(--accent-dim); color:var(--accent);}
.event.type-adjust{border-left-color:var(--purple);} .event.type-adjust .event-type{background:var(--purple-dim); color:var(--purple);}
.event.type-other{border-left-color:var(--dim2);} .event.type-other .event-type{background:var(--line); color:var(--dim);}
.event.type-error{border-left-color:var(--red); background:rgba(255,84,112,0.08);} .event.type-error .event-type{background:var(--red-dim); color:var(--red);}

.errbar{
  background:var(--red-dim); color:#ffd7de; font-size:11px; padding:8px 16px; display:none;
}
.errbar.show{display:block;}

::-webkit-scrollbar{width:8px;}
::-webkit-scrollbar-thumb{background:var(--line); border-radius:4px;}
::-webkit-scrollbar-track{background:transparent;}

@media (max-width:760px){
  .layout{flex-direction:column;}
  .stock-panel{width:100%; max-height:38vh; border-right:none; border-bottom:1px solid var(--line);}
  .tb-controls{width:100%; justify-content:space-between;}
}

/* ---------- ВКЛАДКИ ---------- */
/* Выпадающий список вкладок. Открывается от названия панели (.pane-title) при
   разделении экрана и меняет вкладку именно той панели, от которой открыт. Вне
   разделения вкладку выбирают в меню. */
.tab-menu{
  position:fixed; z-index:3000; min-width:210px; max-height:70vh; overflow:auto;
  background:var(--panel); border:1px solid var(--line); padding:4px 0;
  box-shadow:0 8px 26px rgba(0,0,0,0.45);
}
.tab-menu button{
  display:block; width:100%; text-align:left; background:none; border:none;
  border-left:2px solid transparent; color:var(--dim); font-family:inherit;
  font-size:12px; letter-spacing:0.5px; text-transform:uppercase;
  padding:11px 16px; cursor:pointer; white-space:nowrap;
}
.tab-menu button:hover{ background:var(--panel2); color:var(--text); }
/* Вкладка этой панели помечена ярко, вкладка соседней - бледно: так заранее видно,
   что выбор её сюда просто поменяет панели местами. */
.tab-menu button.cur{ color:var(--accent); border-left-color:var(--accent); }
.tab-menu button.cur-other{ color:var(--text); border-left-color:var(--dim); }

/* ---------- НИЖНЯЯ ПЛАШКА И МЕНЮ ----------
   Общая для всех вкладок полоса действий у нижнего края: слева то, что положила в
   неё текущая вкладка, справа вход в меню. Высоту плашки меряет bootstrap.js и
   кладёт в --appbar-h: под неё отступает содержимое вкладок и приподнимаются окна
   на карте, а зашивать цифру в стили нельзя - полоса чипов бывает выше одной строки. */
.appbar{
  display:flex; align-items:center; gap:8px;
  position:fixed; left:0; right:0; bottom:0; z-index:960;
  padding:8px 12px calc(8px + env(safe-area-inset-bottom));
  background:var(--panel); border-top:1px solid var(--line);
  box-shadow:0 -2px 14px rgba(0,0,0,0.28);
}
.appbar-actions{ flex:1; min-width:0; display:flex; align-items:center; gap:8px; }
/* Логотип - кнопка меню: обычная кнопка в рамке, как соседняя «◫», знак цвета текста
   (маска icons/logo-mask.png) - виден и в тёмной, и в светлой теме и читается как кнопка. */
.app-logo{ display:block; width:22px; height:22px; background:currentColor;
  -webkit-mask:url(icons/logo-mask.png) center/contain no-repeat; mask:url(icons/logo-mask.png) center/contain no-repeat; }
.appbar-menu{
  flex-shrink:0; display:flex; align-items:center; justify-content:center;
  width:34px; height:34px; padding:0; cursor:pointer;
  background:var(--panel2); border:1px solid var(--line); color:var(--text);
}
.appbar-menu:hover, .appbar-menu[aria-expanded="true"]{ border-color:var(--accent); color:var(--accent); }
/* Разделение экрана - соседка меню, но обычная кнопка: это действие, а не вход. */
.appbar-split{
  flex-shrink:0; width:34px; height:34px; padding:0;
  background:var(--panel2); border:1px solid var(--line); color:var(--dim);
  font-family:inherit; font-size:14px; line-height:1; cursor:pointer;
}
.appbar-split:hover{ color:var(--text); border-color:var(--accent); }
/* Действия вкладки внутри плашки: своих отступов и фона им здесь не нужно. */
.appbar .tasks-chips-bar{ flex:1; min-width:0; margin:0; }

/* Отступ снизу под плашку - сразу всем вкладкам: плашка общая и низ содержимого
   перекрывает одинаково везде. */
.panes{ padding-bottom:var(--appbar-h, 58px); }

.drawer{
  display:flex; position:fixed; top:0; right:0; bottom:0; z-index:1200;
  width:min(78vw, 300px); flex-direction:column; overflow-y:auto;
  background:var(--panel); border-left:1px solid var(--line);
  box-shadow:-2px 0 18px rgba(0,0,0,0.35);
  transform:translateX(100%); transition:transform 0.18s ease-out;
}
.drawer.open{ transform:none; }
.drawer-head{ display:flex; align-items:center; gap:10px; padding:16px 18px 10px; font-size:13px; font-weight:800; letter-spacing:1.5px; }
.drawer-head .app-logo{ width:24px; height:24px; color:var(--text); }
.drawer-head span{ color:var(--accent); }
.drawer-tabs, .drawer-service{ display:flex; flex-direction:column; }
/* Общие действия отбиты от вкладок одной полосой на всю группу, а не на каждой. */
.drawer-service{ margin-top:8px; border-top:1px solid var(--line-soft); }
.drawer-tabs button, .drawer-service button{
  text-align:left; background:none; border:none; border-left:2px solid transparent;
  color:var(--dim); font-family:inherit; font-size:12px; letter-spacing:0.5px;
  text-transform:uppercase; padding:13px 18px; cursor:pointer;
}
.drawer-tabs button:hover, .drawer-service button:hover{ color:var(--text); }
/* Значок вкладки. Ширина задана жёстко, поэтому названия выстраиваются в столбик по
   левому краю - эмодзи разной ширины иначе разъезжаются, и список выглядит рваным.
   Регистр сбрасываем: у text-transform:uppercase некоторые значки на Android
   подменяются другим начертанием. Приглушать не стали - цвет у эмодзи свой, а
   opacity гасит и его, делая рисунок грязным. */
.tab-icon{
  display:inline-block; width:1.5em; margin-right:2px;
  text-align:center; text-transform:none; font-size:13px; line-height:1;
  vertical-align:-1px;
}
.drawer-service .tb-service-label{ margin-left:8px; }
/* Отпечаток сборки - служебная строка, а не кнопка: читают её редко, поэтому она
   мелкая и приглушённая, но выделяется, когда часть файлов не загрузилась. */
.drawer-build{
  padding:10px 18px 14px; color:var(--dim); font-size:10px; letter-spacing:0.5px;
  opacity:0.65; user-select:text; word-break:break-all;
}
/* В вертикальном списке подчёркивание снизу не читается - метим полосой слева. */
.drawer-tabs button.active{ color:var(--accent); border-left-color:var(--accent); background:var(--panel2); }
/* Затемнение под выехавшим меню: и подсказка, что остальное сейчас неактивно, и
   удобная зона закрытия по касанию мимо. */
.drawer-overlay{ display:none; position:fixed; inset:0; z-index:1150; background:rgba(0,0,0,0.45); }
.drawer-overlay.open{ display:block; }

.panes{ display:flex; flex-direction:column; min-height:0; }
.tab-pane{display:none;}
.tab-pane.active{display:flex;}

/* ---------- РАЗДЕЛЁННЫЙ ЭКРАН ----------
   Обычный режим не меняется вовсе: пока класса split-on нет, .panes - обычная
   колонка с одной видимой вкладкой, и страница прокручивается как раньше.
   Включили разделение - оболочка становится ростом с экран, и каждая панель
   прокручивается сама (у вкладок для этого уже есть свои .metrics-wrap/.map-wrap
   с overflow:auto). Ограничивать высоту всегда было бы рискованно: на телефоне
   100vh врёт из-за адресной строки, а разделение там и не нужно. */
/* В разделённом экране страница не прокручивается вовсе - листают сами панели.
   Место под нижнюю плашку отнимаем у всей колонки приложения, а не отступом внутри
   .panes: так высота панелей известна точно, и ни одна из них не может вытолкнуть
   вторую за нижний край окна. overflow:hidden на body - страховка от того же:
   если что-то внутри окажется выше панели, оно обрежется, а не утащит всю страницу. */
body.split-on{ overflow:hidden; }
/* min-height из базового правила обязательно сбросить: он сильнее height, и без него
   колонка приложения оставалась ростом в целый экран. Деление на --ui-zoom тоже
   обязательно: vh отсчитывается от окна и про zoom на body не знает, поэтому 100vh
   внутри body - это на 20% больше экрана, и низ панелей уходил под нижний край. */
body.split-on #dashboard{ height:calc(100vh / var(--ui-zoom) - var(--appbar-h, 58px)); min-height:0; }
body.split-on .panes{
  flex:1; min-height:0; flex-direction:row; flex-wrap:nowrap;
  padding-bottom:0; overflow:hidden;
}
/* Колонкой - чтобы подпись панели встала НАД содержимым, а не рядом с ним: часть
   вкладок (задачи, очередь, метрики) в обычном режиме выложены строкой. */
body.split-on .tab-pane.active{ flex:1 1 0; min-width:0; order:3; flex-direction:column; }
/* Имя вкладки над панелью. Оно же переключатель вкладки этой панели, поэтому это
   кнопка. Стиль тот же, что у заголовка списка задач. */
.pane-title{
  display:block; width:100%; text-align:left; font-family:inherit;
  font-size:11px; letter-spacing:2px; color:var(--dim); text-transform:uppercase;
  padding:14px 24px 8px; background:none; border:none; cursor:pointer;
  border-bottom:1px solid var(--line); flex-shrink:0;
}
.pane-title::after{ content:' ▾'; }
.pane-title:hover{ color:var(--accent); }
body.split-on .tab-pane.pane-left{ flex:0 0 var(--split-ratio, 50%); order:1; }
body.split-on .pane-split{ display:block; order:2; }
/* Вкладки-таблицы своей прокрутки не имеют - в обычном режиме их листает
   страница. В панели листать нечему, поэтому даём прокрутку самой вкладке. */
body.split-on #tab-recipes.active,
body.split-on #tab-items.active{ overflow:auto; }
.pane-split{
  display:none; flex:0 0 7px; cursor:col-resize; position:relative;
  background:var(--line-soft);
}
.pane-split::before{
  content:''; position:absolute; top:50%; left:50%; transform:translate(-50%, -50%);
  width:1px; height:28px; background:var(--dim2);
}
.pane-split:hover{ background:var(--accent-dim); }
/* Кнопка обмена панелей. Появляется не сразу: у самой границы курсор оказывается
   и просто по дороге, а всплывающая под рукой кнопка сбивает прицел. Показываем
   после секунды удержания рядом с линией - тогда это уже намерение. */
.pane-swap{
  position:absolute; top:10px; left:50%; transform:translateX(-50%) scale(0.8);
  width:26px; height:26px; padding:0; border-radius:50%;
  background:var(--panel2); border:1px solid var(--accent); color:var(--accent);
  font-family:inherit; font-size:13px; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  opacity:0; pointer-events:none; transition:opacity 0.15s, transform 0.15s;
}
body.split-hint .pane-swap{ opacity:1; pointer-events:auto; transform:translateX(-50%) scale(1); }
.pane-swap:hover{ background:var(--accent); color:var(--panel); }
body.split-dragging{ cursor:col-resize; user-select:none; }
/* Пока тянут границу, курсор не должен превращаться в текстовый над содержимым
   панелей, а сами панели - ловить наведения. */
body.split-dragging .tab-pane{ pointer-events:none; }
#split-toggle.active{ color:var(--accent); }
/* Порог тот же, что в SPLIT_MIN_WIDTH: узкое окно делить незачем - в панели
   шириной в пол-экрана не помещается ни карта, ни список задач с количествами. */
@media (max-width: 1099px){
  #split-toggle{ display:none; }
}

/* ---------- КАРТА СВЯЗЕЙ ---------- */
.map-wrap{flex:1; overflow:auto; padding:24px; cursor:grab; user-select:none; -webkit-user-select:none;}
.map-wrap.map-panning{ cursor:grabbing; }
.map-empty{color:var(--dim2); text-align:center; padding:60px 20px; font-size:12px; line-height:1.6;}
/* Только собственная фигура блока (прямой потомок <g>): внутри блока теперь есть и
   свой rect у метатега формы/цвета, а правила вида ".map-node-item rect" красили
   его рамку заодно с рамкой блока. */
.map-node-item > rect{fill:var(--panel2); stroke:var(--dim); stroke-width:1;}
.map-node-item text{fill:var(--text); font-size:11px;}
/* Рамка нейтральная: цвет отдан под пометки о незаполненных данных. Процесс от
   продукта отличает форма, а внутри блока - жирная подпись. */
.map-node-recipe > rect{fill:var(--panel2); stroke:var(--dim); stroke-width:1;}
.map-node-recipe text{fill:var(--text); font-size:11px; font-weight:700;}
.map-edge{stroke:var(--line); stroke-width:1.4; fill:none;}
.map-group-box{fill:none; stroke:var(--dim); stroke-dasharray:4 3;}
.map-band-title{fill:var(--dim); font-size:11px; letter-spacing:1px; text-transform:uppercase;}
.map-legend{display:flex; gap:18px; padding:12px 24px; border-bottom:1px solid var(--line-soft); font-size:10.5px; color:var(--dim);}
.map-legend span{display:inline-flex; align-items:center; gap:6px;}
.map-legend .sw{width:10px; height:10px; border-radius:2px; display:inline-block;}

/* ---------- МЕТРИКИ ---------- */
/* Своя прокрутка вкладке нужна только в разделённом экране: там панель ограничена
   по высоте. В обычном режиме страницу листает окно, а лишний контейнер прокрутки
   здесь ломал бы прилипающие заголовки списков - они прилипали бы к невидимому
   краю этого контейнера, а не к шапке (см. .tasks-group-title). */
.metrics-wrap{flex:1; overflow:visible; padding:24px; display:flex; flex-direction:column; gap:24px;}
body.split-on .metrics-wrap{ overflow:auto; padding-top:0; }
/* Обязательно, иначе прокрутки не будет вовсе: в колоночном флексе с заданной
   высотой содержимое сжимается до размера контейнера вместо того, чтобы вылезти за
   него, и полоса прокрутки не появляется - список просто обрезается на середине. */
body.split-on .metrics-wrap > *{ flex-shrink:0; }
.metric-section-title{font-size:11px; letter-spacing:2px; color:var(--dim); text-transform:uppercase; margin-bottom:10px;}
.metric-cards{display:flex; gap:14px; flex-wrap:wrap;}
.metric-card{background:var(--panel2); border:1px solid var(--line); padding:16px 20px; min-width:170px;}
.metric-card .num{font-size:28px; font-weight:800; color:var(--accent);}
.metric-card .label{font-size:10.5px; color:var(--dim); letter-spacing:0.5px; margin-top:4px;}
.metric-table{width:100%; border-collapse:collapse; font-size:12px;}
.metric-table th{text-align:left; color:var(--dim); font-size:10px; letter-spacing:1px; text-transform:uppercase; padding:6px 10px; border-bottom:1px solid var(--line);}
.metric-table td{padding:7px 10px; border-bottom:1px dashed var(--line-soft);}
.metric-table tr.warn td{color:var(--orange);}
.metric-table tr.danger td{color:var(--red);}

/* ---------- РЕЦЕПТЫ / ПОЗИЦИИ СКЛАДА (та же тема монитора, просто отдельные вкладки) ---------- */
#tab-recipes, #tab-items { padding: 18px 22px; overflow: auto; }
#tab-recipes h2, #tab-items h2 { font-size: 15px; font-weight: 800; letter-spacing: 1px; color: var(--text); margin-bottom: 12px; }
#tab-recipes h3, #tab-items h3 { font-size: 13px; color: var(--accent); margin: 14px 0 8px; }
#tab-recipes h4, #tab-items h4 { font-size: 11px; letter-spacing:1px; text-transform:uppercase; color: var(--dim); margin: 14px 0 6px; }

#tab-recipes button, #tab-items button, #column-picker button {
    background: var(--panel2); border: 1px solid var(--line); color: var(--dim);
    font-family: var(--mono); font-size: 10px; letter-spacing: 1px; text-transform: uppercase;
    padding: 7px 12px; cursor: pointer; margin: 2px 4px 2px 0;
}
#tab-recipes button:hover, #tab-items button:hover, #column-picker button:hover { border-color: var(--accent); color: var(--accent); }
#tab-recipes button.danger, #tab-items button.danger, #tab-recipes .danger, #tab-items .danger { color: var(--red); border-color: var(--red-dim); }
#tab-recipes button.danger:hover, #tab-items button.danger:hover { background: rgba(255,84,112,0.1); }

#tab-recipes input, #tab-items input, #tab-recipes select, #tab-items select, #column-picker input {
    background: var(--panel2); border: 1px solid var(--line); color: var(--text);
    font-family: var(--mono); font-size: 12px; padding: 6px 8px; outline: none;
}
#tab-recipes input:focus, #tab-items input:focus, #tab-recipes select:focus, #tab-items select:focus { border-color: var(--accent); }
#tab-recipes select option, #tab-items select option { background: var(--panel2); color: var(--text); }

#tab-recipes table, #tab-items table { border-collapse: collapse; width: 100%; margin-bottom: 16px; font-size: 12px; }
#tab-recipes td, #tab-items td, #tab-recipes th, #tab-items th { border: 1px solid var(--line-soft); padding: 7px 10px; text-align: left; }
#tab-recipes th, #tab-items th { color: var(--dim); font-size: 10px; letter-spacing: 1px; text-transform: uppercase; background: var(--panel); }

.group-header {
    cursor: default; background: var(--panel2); border: 1px solid var(--line);
    padding: 9px 14px; margin-top: 12px; font-size: 12px; font-weight: 700; color: var(--text);
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.group-header-toggle { cursor: pointer; flex: 1 1 auto; }
.group-header:hover { border-color: var(--accent); color: var(--accent); }
.group-header-actions { flex: 0 0 auto; display: flex; gap: 4px; }
/* Восклицательный знак у позиции склада с проблемной единицей измерения. В шапке
   группы - тот же знак, если проблема есть хотя бы у одной строки внутри. */
.item-warn {
    display: inline-block; flex: 0 0 auto; margin-right: 6px; cursor: help;
    color: var(--orange); font-weight: 700;
}
.group-body { border: 1px solid var(--line-soft); border-top: none; padding: 10px; background: var(--panel); }
/* Шапка столбца кликается: сортировка внутри группы. Третий клик по тому же
   столбцу возвращает порядок по умолчанию. */
.col-sortable { cursor: pointer; user-select: none; }
.col-sortable:hover { color: var(--accent); }
.group-sub { margin-top: 3px; font-size: 10.5px; color: var(--dim); }

.cell-value { cursor: pointer; display: inline-block; min-width: 20px; padding: 2px 5px; color: var(--text); }
.cell-value:hover { background: var(--panel2); outline: 1px dashed var(--line); }
.empty-cell { color: var(--dim2); }
.cell-edit-wrap { position: relative; display: inline-block; }
/* Призрак невидим, но занимает место прежнего значения - ячейка не меняет размер. */
.cell-edit-ghost { display: inline-block; visibility: hidden; padding: 2px 5px; white-space: pre; }
.cell-edit {
    position: absolute; left: 0; top: 50%; transform: translateY(-50%); z-index: 40;
    display: inline-flex; align-items: center; gap: 4px;
    background: var(--panel2); border: 1px solid var(--accent); padding: 3px;
}
.cell-edit input, .cell-edit select { width: 220px; max-width: 52vw; min-width: 0; }
.cell-btn { padding: 3px 7px; font-size: 11px; }
/* Кнопка "×" (очистить значение ячейки) нужна редко, а видно её было всегда - в
   таблице из десятка столбцов это десяток красных крестов в каждой строке. Прячем
   прозрачностью, а не display:none: ширина ячейки не должна прыгать при наведении.
   Только там, где мышь есть: на тач-устройстве наведения не бывает, и кнопка,
   спрятанная до hover, стала бы недоступной совсем. */
@media (hover: hover) {
    td .cell-btn.danger { opacity: 0; transition: opacity .12s; }
    td:hover .cell-btn.danger,
    td .cell-btn.danger:focus-visible { opacity: 1; }
}

.drag-handle { cursor: grab; color: var(--dim2); text-align: center; width: 20px; user-select: none; touch-action: none; }
.recipe-group { margin-bottom: 4px; }
/* Столбец, у которого во всей группе одно и то же значение: он различает не строки,
   а саму группу, то есть повторяет её название. Подсветка слабая - это подсказка,
   а не ошибка: столбец может быть нужен и таким. */
.col-uniform { background: rgba(255, 182, 72, 0.07); }
th.col-uniform { background: rgba(255, 182, 72, 0.12); color: var(--orange); }
body.light-theme .col-uniform { background: rgba(163, 92, 0, 0.08); }
/* Столбец, по которому группа сейчас отсортирована вручную - перебивает и жёлтый
   "одинаковый у всех", иначе стрелку не видно. */
th.col-sorted, th.col-uniform.col-sorted { color: var(--accent); }
body.light-theme th.col-uniform { background: rgba(163, 92, 0, 0.14); }
.sortable-dragging { opacity: 0.95; box-shadow: 0 10px 28px rgba(0,0,0,0.65); background: var(--panel2); }
.sortable-placeholder { background: rgba(52,213,255,0.10); outline: 1px dashed var(--accent); outline-offset: -2px; }
.sortable-placeholder * { visibility: hidden; }
tr.role-input { background: rgba(52, 213, 255, 0.14); box-shadow: inset 3px 0 0 var(--accent); }
tr.role-output { background: rgba(61, 220, 132, 0.14); box-shadow: inset 3px 0 0 var(--green); }
tr.role-input:hover, tr.role-output:hover { filter: brightness(1.25); }

#recipe-editor { border-top: 1px solid var(--line); margin-top: 20px; padding-top: 16px; }

/* Пикер колонок - всплывает поверх всего, через document.body.appendChild */
#column-picker {
    position: fixed; top: 60px; left: 50%; transform: translateX(-50%);
    background: var(--panel2); border: 1px solid var(--line); padding: 12px; z-index: 1000;
    max-height: 70vh; overflow: auto; font-family: var(--mono); color: var(--text);
}
#column-picker input { width: 250px; }
#column-picker .cell-value { display: block; padding: 5px 6px; }
#column-picker .cell-value:hover { background: var(--panel); }


#mini-spinner {
    display: inline-block; width: 10px; height: 10px; margin-left: 4px;
    border: 2px solid #3a4a5c; border-top-color: #9fc6ff; border-radius: 50%;
    vertical-align: middle; animation: spin-loading-bar 0.7s linear infinite;
}
@keyframes spin-loading-bar { to { transform: rotate(360deg); } }
/* Спиннер внутри кнопки на время записи. Цвет берёт у самой кнопки, поэтому годится
   любой: видимая дуга - currentColor, остальное кольцо - линия рамки. */
.btn-spinner{
  display:inline-block; width:10px; height:10px; vertical-align:middle;
  border:2px solid var(--line); border-top-color:currentColor; border-radius:50%;
  animation: spin-loading-bar 0.7s linear infinite;
}


.row-flash { animation: rowFlash 1.5s ease-out; }
@keyframes rowFlash {
    0% { background: rgba(52, 213, 255, 0.35); }
    100% { background: transparent; }
}

.photo-cell { width: 40px; cursor: pointer; }
.photo-thumb { display: block; width: 32px; height: 32px; object-fit: cover; border: 1px solid var(--line); border-radius: 2px; }
.photo-thumb-empty {
    display: flex; align-items: center; justify-content: center;
    color: var(--dim2); font-size: 16px; background: var(--panel2);
}
.photo-cell:hover .photo-thumb { border-color: var(--accent); }
.photo-uploading { position: relative; opacity: 0.5; pointer-events: none; }
.photo-uploading::after {
    content: '';
    position: absolute; inset: 0; margin: auto;
    width: 16px; height: 16px;
    border: 2px solid var(--line); border-top-color: var(--accent);
    border-radius: 50%;
    animation: photo-spin 0.7s linear infinite;
}
@keyframes photo-spin { to { transform: rotate(360deg); } }

#photo-lightbox {
    position: fixed; inset: 0; z-index: 2000;
    background: rgba(5,8,12,0.85);
    display: flex; align-items: center; justify-content: center;
}
.photo-lightbox-box {
    background: var(--panel2); border: 1px solid var(--line);
    padding: 16px; max-width: 90vw; max-height: 90vh;
    display: flex; flex-direction: column; align-items: center; gap: 12px;
}
#photo-lightbox-img { max-width: 80vw; max-height: 70vh; object-fit: contain; }
#photo-lightbox-img.hidden { display: none; }
.photo-lightbox-actions { display: flex; gap: 8px; }

tr.row-new-highlight { background: rgba(52, 213, 255, 0.18); }

.item-picker-btn { width: 100%; min-width: 160px; text-align: left; }
/* Кнопка выбора фокуса на карте - группа + метатеги, без капса/разрядки tb-btn,
   иначе название и теги смотрелись бы криво. */
/* Кнопка показа/скрытия панели карты - слева, сразу под самой панелью. Место ей
   считает mapPositionControls: панель и кнопка висят поверх карты и должны стоять
   ниже шапки, а при разделении экрана - ниже названия вкладки. */
#map-controls-toggle{
  position:fixed; left:8px; z-index:941;
  width:34px; height:34px; line-height:1; font-size:16px;
  background:var(--panel2); color:var(--dim); border:1px solid var(--line);
  border-radius:6px; cursor:pointer;
}
#map-controls-toggle:hover{ color:var(--text); }
#map-controls-toggle.active{ color:var(--accent); border-color:var(--accent); }
.map-focus-btn{
  min-width:200px; text-align:left; cursor:pointer;
  background:var(--panel2); color:var(--text);
  border:1px solid var(--line); border-radius:6px; padding:6px 10px; font-size:12.5px;
  /* Группа и метатеги идут одной строкой: ужимать кнопку по остатку места нельзя -
     правый край подписи просто срезался. Растём по содержимому, а остальные
     органы управления переносятся на вторую строку (см. .map-controls). */
  flex:0 0 auto; white-space:nowrap; max-width:min(70vw, 720px);
}
.map-focus-btn:hover{ border-color:var(--accent); }
.map-focus-btn .tasks-pick-line{ display:inline-flex; }
.item-picker-panel {
    position: fixed; z-index: 2500;
    background: var(--panel2); border: 1px solid var(--line);
    min-width: 220px; max-height: 50vh; display: flex; flex-direction: column;
}
.item-picker-search { margin: 4px; flex: 0 0 auto; }
.item-picker-list { overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.item-picker-group-label { padding: 4px 8px; font-size: 10px; letter-spacing: 1px; text-transform: uppercase; color: var(--dim); background: var(--panel); }
.item-picker-option { padding: 5px 10px; cursor: pointer; }
.item-picker-option:hover { background: var(--panel); }
.item-picker-option.active { color: var(--accent); font-weight: 700; }

.map-controls {
  display: flex; flex-wrap: wrap; gap: 10px; padding: 10px 24px; align-items: center;
  transition: opacity .2s ease; opacity: 1;
  /* Ширину и положение задаёт mapPositionControls - на всё окно панель растягивать
     нельзя, при разделении экрана она легла бы поверх соседней вкладки. */
  position: fixed; left: 0; width: 100%; z-index: 940;
  background: var(--panel); border-bottom: 1px solid var(--line-soft);
}
.map-controls select { flex: 1; max-width: 360px; }
.map-controls.map-controls-hidden { opacity: 0; pointer-events: none; }

#tab-map { position: relative; }

/* ---------- ЦВЕТА ОШИБОК НА КАРТЕ ----------
   Раньше три разные беды красились одним красным, и по картинке нельзя было понять,
   что чинить: нет производителя, не хватает на складе или не проставлено место.
   Теперь у каждой свой цвет, и он один и тот же у блока и у стрелки:
     красный   - взять неоткуда: ни процесса, ни поставки. Данные неполны;
     розовый   - не указано место. Данные есть, но считать по ним нельзя;
     оранжевый - с данными всё в порядке, просто на складе не хватает.
   Оранжевый намеренно мягче двух других: это не поломка справочника, а сегодняшнее
   состояние склада, и завтра оно само изменится. */

/* Продукт, которого не выпускает ни один процесс: получить его нечем - в справочнике
   не хватает рецепта-производителя (даже "Поставки"). */
.map-node-noproducer > rect, .map-node-noproducer > polygon { stroke: var(--red) !important; stroke-width: 2px !important; }

.map-node-insufficient > rect, .map-node-insufficient > polygon { stroke: var(--orange) !important; stroke-width: 2px !important; }
.map-node-flash > rect, .map-node-flash > polygon { fill: var(--red) !important; transition: fill 0.15s ease; }

/* Окна списков висят над картой у нижнего края - поднимаем их над общей плашкой
   действий, иначе она накрывает их нижние строки. Левый и правый края им ставит
   mapPositionControls по прямоугольнику самой вкладки: при разделении экрана окна
   должны стоять внутри карты, а не поперёк обеих панелей. */
.map-side-panel{
  position:fixed; bottom:calc(var(--appbar-h, 58px) + 14px); z-index:950;
  background:var(--panel); border:1px solid var(--line);
  border-radius:8px; width:auto; min-width:var(--map-side-min); max-width:560px; max-height:384px;
  display:flex; flex-direction:column; overflow:hidden;
  box-shadow:0 -4px 16px rgba(0,0,0,0.35);
}
#map-purchase-panel{ left:16px; }
#map-task-panel{ right:16px; }
/* Два окна и поля между ними задают, насколько узкой может стать панель карты при
   разделении экрана: уже этого они начали бы наезжать друг на друга. Ограничение
   сверху обязательно - без него на узком мониторе карта выдавливала бы соседнюю
   панель за край окна. */
body.split-on #tab-map.active{ min-width:min(calc(var(--map-side-min) * 2 + 48px), 60%); }
.map-side-panel-header{
  padding:10px 14px; font-size:11px; letter-spacing:1px; text-transform:uppercase;
  cursor:pointer; display:flex; align-items:center; gap:8px;
  color:var(--text); border-bottom:1px solid var(--line-soft); user-select:none; flex-shrink:0;
}
.map-side-panel-count{ background:var(--red); color:#fff; border-radius:10px; padding:1px 7px; font-size:10px; }
.map-side-panel-count-warn{ background:none; color:var(--orange); border:1px solid var(--orange); }
.map-side-panel.collapsed .map-side-panel-body{ display:none; }
.map-side-panel-body{ overflow:auto; max-height:340px; overscroll-behavior:contain; }
.map-side-panel table{ width:100%; border-collapse:collapse; font-size:11px; }
.map-side-panel td{ padding:6px 10px; border-bottom:1px solid var(--line-soft); white-space:normal; word-break:break-word; }
.map-side-panel td:last-child{ text-align:right; white-space:nowrap; }
.map-side-panel tr{ cursor:pointer; }
.map-side-panel tr:hover td{ background:rgba(255,255,255,0.05); color:var(--accent); }
.map-side-row-warn td{ color:var(--orange); border-top:1px dashed var(--line-soft); }
.map-side-row-warn:hover td{ background:rgba(255,255,255,0.05); color:var(--orange); }
.map-side-panel-empty{ padding:10px 14px; font-size:11px; color:var(--dim); }
.map-side-row-assignee{ font-size:9.5px; color:var(--dim); }

.session-row { border-bottom: 1px solid var(--line-soft); padding: 8px 0; }
.session-row-top { display: flex; align-items: center; gap: 10px; cursor: pointer; flex-wrap: wrap; }
.session-recipe-name { font-weight: 700; }
.session-employee, .session-time, .session-op-count { color: var(--dim); font-size: 11px; }
.session-ops-list { margin: 6px 0 6px 20px; border-left: 2px solid var(--line-soft); padding-left: 10px; }
.op-row { display: flex; align-items: center; gap: 10px; padding: 4px 0; font-size: 11px; flex-wrap: wrap; }
.op-item { font-weight: 600; }
.op-loc, .op-date, .op-type { color: var(--dim); }
.op-qty-value { cursor: pointer; border-bottom: 1px dotted currentColor; color: var(--accent); }
.op-qty-value:hover { color: var(--text); }
.op-row-incoming { background: rgba(61, 220, 132, 0.1); border-left: 2px solid var(--green); padding-left: 6px; }
.op-row-incoming .op-item, .op-row-incoming .op-type { color: var(--green); }

.op-row-incoming { background: rgba(61, 220, 132, 0.1); border-left: 2px solid var(--green); padding-left: 6px; }
.op-row-incoming .op-item, .op-row-incoming .op-type { color: var(--green); }

.session-subrow { margin-left: 16px; border-left: 2px solid var(--line-soft); padding-left: 8px; border-bottom: none; }

.tb-input { background:var(--panel2); border:1px solid var(--line); color:var(--text); padding:4px 6px; font-family:inherit; font-size:12px; width:100%; }

/* ---------- РЕЦЕПТЫ / ПОЗИЦИИ СКЛАДА - мобильная адаптация ---------- */
@media (max-width:760px){
  #tab-recipes table, #tab-items table { font-size: 14px; }
  #tab-recipes td, #tab-items td, #tab-recipes th, #tab-items th { padding: 5px 6px; }
  #tab-recipes th, #tab-items th { font-size: 9px; }
  .cell-value { padding: 4px 5px; }
  .cell-btn { padding: 6px 9px; font-size: 12px; }
  .drag-handle { width: 24px; }
  #tab-recipes input, #tab-items input, #tab-recipes select, #tab-items select { font-size: 14px; padding: 7px 9px; }
}

.map-edge-back { stroke: var(--dim); stroke-dasharray: 6 5; opacity: 0.1; transition: opacity 0.15s; }
/* Галочка "Показывать обратные циклы" - петли видны наравне с основными ветками */
svg.show-back-cycles .map-edge-back { opacity: 1; }
.map-edge-back:hover, .map-edge-back.map-edge-hovered { opacity: 1 !important; }
/* Точки изгиба лежат прямо на линии, поэтому мелкие и чёрные с тонкой светлой
   обводкой - иначе на самой линии их не видно. */
.map-edge-handle { fill: #000; stroke: rgba(255,255,255,0.55); stroke-width: 0.8; opacity: 0; pointer-events: none; cursor: grab; touch-action: none; }
/* !important - у приглушённых связей (побочные, петли) точки не должны наследовать
   прозрачность самой линии, иначе в режиме правки их не найти. */
svg.map-edit-mode .map-edge-handle { opacity: 0.7 !important; pointer-events: auto; }
svg.map-edit-mode .map-edge-handle:hover,
svg.map-edit-mode .map-edge-handle.edge-handle-active { opacity: 1 !important; fill: var(--accent); }
/* Точка, предложенная наведением: пока за неё не взялись, она бледнее настоящих -
   видно, что это приглашение согнуть линию, а не уже заданный изгиб. */
svg.map-edit-mode .map-edge-handle.map-edge-handle-new { opacity: 0.5 !important; fill: var(--accent); stroke: var(--panel); stroke-width: 1.2; }

/* ---------- ЗАДАЧИ ---------- */
.tasks-layout{ display:flex; }
.tasks-main{ flex:1; min-width:0; }
/* Очередь переехала на свою вкладку. Рядом с задачами её теперь ставят разделением
   экрана (кнопка ◫ в панели вкладок) - это работает с любой парой вкладок, а не
   только с этой одной, ради которой раньше держали двухколоночную раскладку. */
.tasks-queue-panel{ flex:1; min-width:0; }
/* Заголовок очереди - та же синяя полоса, что у разделов списка задач
   (.tasks-group-title): выбиваться из общего ряда ей незачем. Сворачиваться больше
   нечему, поэтому ни стрелки, ни курсора-руки здесь нет. */
.tasks-priority-summary{
  font-size:12px; letter-spacing:1.2px; color:var(--text); text-transform:uppercase; font-weight:700;
  background:var(--accent-dim); border-radius:6px; padding:7px 12px; margin-bottom:10px;
  display:flex; align-items:center; gap:6px;
  /* Заголовки очереди прилипают к верху так же, как разделы списка задач: списки
     здесь такие же длинные, и без этого непонятно, что именно сейчас на экране. */
  position:sticky; top:var(--topbar-h, 0px); z-index:5;
}
body.split-on .tasks-priority-summary{ top:0; }



/* Срок заказа. Просроченный и горящий метим рамкой слева, а не заливкой: строки
   в очереди узкие, заливка перекрыла бы номер приоритета и метатеги. */
/* Срок - одна нажимаемая строка. Поле ввода лежит под ней прозрачным слоем: убирать
   его из разметки нельзя, системный календарь открывается именно от него и к его
   месту на экране привязывается. pointer-events:none - чтобы клик доставался кнопке,
   а не полю: по самому полю браузер открывает календарь только с иконки. */
.tasks-order-deadline{ position:relative; display:flex; margin-top:4px; }
.tasks-order-deadline-btn{
  align-self:flex-start; max-width:100%;
  font-family:inherit; font-size:11px; letter-spacing:0.3px; text-align:left;
  color:var(--dim); background:var(--panel); border:1px solid var(--line);
  border-radius:4px; padding:3px 9px; cursor:pointer;
}
.tasks-order-deadline-btn:hover{ color:var(--text); border-color:var(--accent); }
/* Цвет срочности здесь дублирует рамку карточки намеренно: рамка ведёт взгляд по
   списку сверху вниз, заливка отвечает на вопрос "а когда именно". */
.tasks-order-deadline-btn.overdue,
.tasks-order-deadline-btn.urgent{ background:rgba(220,80,80,0.28); color:var(--text); border-color:var(--red); font-weight:700; }
.tasks-order-deadline-btn.soon{ background:rgba(230,198,46,0.24); color:var(--text); border-color:#e6c62e; }
.tasks-order-deadline-btn.ok{ background:rgba(76,175,80,0.22); color:var(--text); border-color:#4caf50; }
/* Срок не задан - заливка красная и держится, пока дату не выберут. Мигание после
   перемотки к форме отсюда убрано: вспышку видит только тот, кто смотрел на экран в
   эту секунду, а к форме возвращаются и позже. Красным, а не жёлтым: заказ без срока
   не «скоро», он вообще не встаёт в очередь по приоритету. */
.tasks-order-deadline-btn.none{
  background:rgba(220,80,80,0.28); color:var(--text); border-color:var(--red); font-weight:700;
}
.tasks-order-deadline-input{
  position:absolute; left:0; bottom:0; width:100%; height:100%;
  opacity:0; pointer-events:none; border:none; padding:0; background:none;
}
.tasks-deadline-tag{ font-size:10px; letter-spacing:0.5px; text-transform:uppercase; }
.tasks-deadline-tag.urgent{ color:var(--orange); }
.tasks-deadline-tag.overdue{ color:var(--red); font-weight:700; }

.tasks-priority-list{ display:flex; flex-direction:column; gap:4px; }
/* touch-action тут не ставим. Он остался от перетаскивания заказов, которое давно
   убрали, а на телефоне запрещал браузеру считать касание жестом: карточки занимают
   почти всю панель, палец всегда попадает в них, и очередь просто не прокручивалась. */
.tasks-priority-row, .tasks-order-row{
  display:flex; align-items:flex-start; gap:8px; padding:8px 10px;
  background:var(--panel2); border:1px solid var(--line-soft); border-radius:6px;
  font-size:12.5px;
}

/* Номер в очереди стоит столбиком вместе с кнопками заказа и вдвое крупнее прежнего:
   по нему называют заказ вслух, и разглядывать его среди мелкого текста не должно
   приходиться. */
.tasks-priority-index{ color:var(--dim); font-size:21px; font-weight:700; line-height:1; text-align:center; }
/* Строка очереди: сверху название группы, снизу метатеги и управление.
   Ручка перетаскивания и номер стоят слева и выровнены по верху. */
/* Слева столбиком: ручка перетаскивания и корзина */
.tasks-order-side{ display:flex; flex-direction:column; align-items:center; gap:8px; flex-shrink:0; }
/* Миниатюра продукта - по ней заказ узнают раньше, чем прочитают название. */
.tasks-order-photo{
  width:44px; height:44px; flex-shrink:0; border-radius:6px; object-fit:cover;
  background:var(--panel2); border:1px solid var(--line-soft); display:block;
}
/* Предложения «что ещё можно сделать». Не задачи и не заказы - подсказка, поэтому
   без рамок и цвета: строка, число и место. */
/* Каждый блок предложений - в своей рамке. Их два подряд, и без границ строки
   одного перетекали в другой: непонятно, где кончается «выходит без закупок» и
   начинается «выходит, если докупить». */
.tasks-spare{
  margin-top:14px; padding:10px 12px;
  border:1px solid var(--line-soft); border-radius:6px; background:var(--panel2);
}
/* Полоса заголовка идёт от края до края блока, а не с отступом внутри него. */
.tasks-spare > .tasks-spare-title{ margin:-10px -12px 8px; border-radius:6px 6px 0 0; }
.tasks-spare:not([open]) > .tasks-spare-title{ margin-bottom:-10px; border-radius:6px; }
/* Та же синяя полоса, что у заголовка очереди (.tasks-priority-summary) и у разделов
   списка задач: это такой же раздел, просто сворачиваемый. */
.tasks-spare-title{
  font-size:12px; color:var(--text); text-transform:uppercase; letter-spacing:1.2px; font-weight:700;
  background:var(--accent-dim); border-radius:6px; padding:7px 12px;
  cursor:pointer; user-select:none; list-style:none; display:flex; align-items:center; gap:6px;
}
.tasks-spare-title::-webkit-details-marker{ display:none; }
/* Своя стрелка: стандартный маркер съезжает от заглавных букв с межбуквенным
   интервалом и на телефоне попадает мимо. */
.tasks-spare-title::before{ content:'▸'; transition:transform 0.15s; }
.tasks-spare[open] > .tasks-spare-title::before{ transform:rotate(90deg); }
.tasks-spare-title:hover{ color:var(--accent); }
/* Прилипает внутри своего блока - как шапки свёрнутых разделов в списке задач. */
.tasks-spare-title{ position:sticky; top:var(--topbar-h, 0px); z-index:4; }
body.split-on .tasks-spare-title{ top:0; }
.tasks-spare:not([open]){ padding-bottom:10px; }
.tasks-spare-hint{ font-size:10px; color:var(--dim2); margin:2px 0 6px; }
/* Предложение - такая же карточка, как заказ в очереди: рамка, скругление, название
   группы жирным сверху. Раньше это был ряд строк без границ, и десяток предложений
   сливался в сплошной текст, в котором не видно, где кончается одно и начинается
   следующее. Классы тела берём от карточки заказа - вид должен совпадать буквально,
   а не «примерно так же». */
.tasks-spare-row{
  display:flex; align-items:flex-start; gap:8px; padding:8px 10px; margin-top:6px;
  background:var(--panel); border:1px solid var(--line-soft); border-radius:6px;
  font-size:12.5px; min-width:0;
}
.tasks-spare-body{ flex:1; min-width:0; display:flex; flex-direction:column; gap:6px; }
/* Строка блока «Учёт врёт». Не карточка задачи: делать тут нечего, пока не
   пересчитают, - только посмотреть и пойти считать. */
/* Переучёты рисуются обычными карточками задач - своей разметки у них больше нет. */

/* Список докупки - таблица без рамок: имя слева, количество справа. Строк бывает
   пять-шесть, и через запятую они читались как сплошной текст. */
/* Обещание держится на позициях, которых в карте нет. Не ошибка, но человек должен
   видеть, на чём стоит число. */
.tasks-buy-table{ width:100%; border-collapse:collapse; font-size:10px; color:var(--orange); }
.tasks-buy-table td{ padding:1px 0; vertical-align:top; }
.tasks-buy-qty{ text-align:right; white-space:nowrap; padding-left:10px !important; font-family:var(--mono); }
/* Подпись позиции здесь та же, что в очереди: группа плюс метатеги. Обычный
   .tasks-pick-line - блочный flex, а в ячейке перед ним стоит значок 🛒/🏭, и строка
   ломалась пополам. inline-flex оставляет их в одной строке. */
.tasks-buy-table .tasks-pick-line,
.tasks-spare-assumed .tasks-pick-line{ display:inline-flex; vertical-align:middle; gap:6px; min-width:0; }
.tasks-buy-table .tasks-pick-line > span:first-child{ min-width:0; }
/* Заголовок списка недостающего. Раньше таблица начиналась сразу, без подписи, и
   читалась как продолжение карточки. */
.tasks-buy-missing-title{ font-size:11px; font-weight:700; color:var(--text); }
/* Позицию, которую взять неоткуда, метим цветом. Слово «Обеспечить» со значком
   занимало полстроки и повторялось у каждой такой строки - цвета достаточно. */
.tasks-buy-nosupply{ color:var(--red); }
/* Отметка "уже есть на месте" прямо в строке недостающего: у такой позиции нет
   карточки задачи, и поставить отметку больше негде. Снимается там же, где все
   остальные, - в блоке "Скоро понадобится купить". */
.tasks-buy-act{ width:1%; padding-left:8px !important; }
.tasks-buy-have{
  background:none; border:1px solid var(--line); border-radius:4px; color:var(--dim);
  font-family:inherit; font-size:10px; line-height:1; padding:2px 6px; cursor:pointer;
}
.tasks-buy-have:hover{ color:var(--accent); border-color:var(--accent); }
/* Общий список допущений под строкой предложения. Пунктами, а не через запятую:
   у каждого своя кнопка, и в строку они слипались в кашу. Заголовок у списка тот же,
   что у таблицы расходов - «Что понадобится», - поэтому и пункты зачёркнуты так же:
   иначе список под таким заголовком читался бы как «сходи возьми это». */
.tasks-spare-assumed{ flex:0 0 100%; font-size:10px; color:var(--dim); margin-top:4px; }
.tasks-spare-assumed ul{ margin:2px 0 0; padding-left:16px; }
/* Зачёркивание вешаем на текст названия (ниже), а не на всю строку: с родителя оно
   протягивается сквозь потомков и не отменяется - кнопка ✕ выходила перечёркнутой,
   а text-decoration:none на ней не помогал. */
/* Подпись позиции - inline-flex, а сквозь flex-контейнер text-decoration с родителя
   не проходит: черта обрывалась на пустом месте перед названием. Вешаем её на сам
   текст названия. Метатеги не зачёркиваем - на фигурках черта читается как дефект
   печати, а не как «эту позицию не покупаем». */
.tasks-spare-assumed li .tasks-pick-line{ text-decoration:none; }
.tasks-spare-assumed li .tasks-pick-line > span:first-child{ text-decoration:line-through; }
/* Кнопки ✕ стоят столбиком у правого края, как колонка .tasks-buy-act в таблице
   соседнего блока. Раньше кнопка шла сразу за текстом и у каждой строки оказывалась
   на своём месте - попасть пальцем можно было только прицелившись. Маркеры списка
   при display:flex пропадают, и это к лучшему: в таблице их тоже нет, а блоки должны
   выглядеть одинаково. */
.tasks-spare-assumed ul{ padding-left:0; list-style:none; }
.tasks-spare-assumed li{ display:flex; align-items:baseline; gap:8px; }
.tasks-spare-assumed li .tasks-pick-line{ flex:1 1 auto; min-width:0; }
.tasks-spare-assumed li .tasks-buy-have{ flex:0 0 auto; margin-left:auto; }
/* Допущение - вычеркнутая строка в той же таблице: видно, что позиция в расходе была
   бы, но её решили считать имеющейся. Кнопка ✕ возвращает её обратно в расход. */
.tasks-buy-assumed td{ text-decoration:line-through; color:var(--dim); }
.tasks-buy-assumed .tasks-buy-act{ text-decoration:none; }
/* То же, что в списке допущений: через inline-flex черта не наследуется. */
.tasks-buy-assumed td .tasks-pick-line{ text-decoration:none; }
.tasks-buy-assumed td .tasks-pick-line > span:first-child{ text-decoration:line-through; }
/* Работа на стороне стоит в общей таблице расходов вместе с докупкой - отличает её
   только значок. Он же на вкладке себестоимости, чтобы не заводить второй язык. */
.tasks-buy-work-mark{ font-size:9px; }
/* Деньги в строке недостающего и в строке платной операции. Цвет не оранжевый, как
   у самой строки: сумма - это факт из себестоимости, а не предупреждение, и глаз
   должен цеплять её отдельно от «чего не хватает». */
.tasks-buy-money{ font-family:var(--mono); white-space:nowrap; color:var(--text); }
.tasks-buy-money-none{ color:var(--dim); font-family:inherit; }
.tasks-buy-money-cell{ text-align:right; white-space:nowrap; padding-left:10px !important; }
/* Итог стоит в заголовке списка, а не отдельной строкой под ним: вопрос «во что
   обойдётся» задают до того, как читать состав, а не после. */
/* Приписка «ещё N без цены» идёт рядом с суммой - и в заголовке строки, и в списке.
   Тише самой суммы: это оговорка к числу, а не второе число. */
.tasks-buy-total{ font-weight:400; color:var(--dim); font-family:var(--mono); font-size:10px; }
.tasks-spare-assumed li{ margin:1px 0; }
/* Снятые допущения показываем в подсказке блока, а не в строке предложения: строка
   вместе с предложением исчезает, а вернуть допущение надо уметь и после этого. */
.tasks-spare-nostock{ color:var(--orange); }
/* Объём работы за предложением - по нему и выстроен порядок списка, поэтому он
   стоит в строке, а не в подсказке. */
.tasks-spare-work{ font-size:10px; color:var(--dim); }
/* Количество - подчёркнутый текст, а не поле: правят его редко, а места поле с двумя
   кнопками шага занимало полстроки в каждой карточке. Нажатие открывает системное
   окно ввода - тем же способом, что количество и срок в заказе. */
.tasks-spare-qty-btn{
  background:none; border:none; padding:0; cursor:pointer;
  font-family:var(--mono); font-size:12.5px; color:var(--accent);
  text-decoration:underline; text-underline-offset:2px;
}
.tasks-spare-qty-btn:hover{ color:var(--text); }
/* Полосы-футера «Добавить в заказы» больше нет: подстановка в форму переехала в ряд
   квадратных кнопок раскрытой строки, к остальным действиям. Отдельная кнопка во всю
   ширину занимала место в каждой строке списка ради действия, которым пользуются,
   уже выбрав строку. */
/* Количество стоит в одном ряду с местом и кнопкой - как в карточке заказа. */
.tasks-spare-qty{
  font-family:var(--mono); color:var(--accent);
  display:flex; align-items:center; gap:4px; flex-wrap:wrap;
}
/* Сам ряд тегов не переносим - это общее правило проекта. Если он не влез,
   на новую строку уходит ряд целиком, вместе с локацией. */
.tasks-spare-row .tasks-tags{ flex:0 0 auto; }
.tasks-spare-loc{ flex:0 0 auto; color:var(--dim); font-size:10px; }

/* Отмена и пауза переехали в ряд действий раскрытой строки (.tasks-card-act): в
   свёрнутой они стояли у самого края и ловились пальцем при прокрутке, а нужны
   раз в неделю. В боковой колонке осталась только ✅ - она про заказ, который
   прямо сейчас просит подтверждения. */
.tasks-order-done-btn{
  background:var(--panel); border:1px solid var(--line); border-radius:4px;
  padding:4px 6px; cursor:pointer;
  font-size:13px; line-height:1; opacity:0.65; transition:opacity 0.15s, border-color 0.15s;
}
.tasks-order-done-btn:hover{ border-color:var(--accent); opacity:1; }
/* Выполненный заказ фоном не выделяем: он не требует действий прямо сейчас, а
   цветная карточка в очереди читается как тревога. Хватает галочки и строки. */
.tasks-order-done{ margin-top:6px; font-size:11px; color:var(--green); }
.tasks-order-progress{ margin-top:6px; font-size:11px; color:var(--dim); }
.tasks-order-done-count{ margin-left:8px; font-size:11px; color:var(--green); }
/* Приостановленный - серый целиком, но остаётся на месте и читаемым. */
.tasks-order-paused{ opacity:0.5; filter:grayscale(1); }
.tasks-order-body{ flex:1; min-width:0; display:flex; flex-direction:column; gap:6px; }
/* Название группы - главное в строке: по нему заказ и находят глазами. */
.tasks-order-title{ font-size:12.5px; font-weight:700; }
/* Метатеги держим строго в один ряд - иначе размеры и форма разъезжаются
   по строкам и перестают читаться как единое описание позиции. */
.tasks-order-tags .tasks-tags{ flex-shrink:0; }
.tasks-order-controls{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:4px; }
/* Количество - такая же нажимаемая строка, как срок: правят его редко, а смотрят
   постоянно, поэтому в покое это текст, а не поле ввода. */
.tasks-order-qty-btn{
  align-self:flex-start; font-family:inherit; font-size:11px; letter-spacing:0.3px;
  color:var(--text); background:var(--panel); border:1px solid var(--line);
  border-radius:4px; padding:3px 9px; cursor:pointer;
}
.tasks-order-qty-btn:hover{ border-color:var(--accent); }
/* Локация - продолжение фразы о количестве, поэтому в той же строке и тем же
   приглушённым тоном, что и остальные пояснения. */
.tasks-order-place{ font-size:10.5px; color:var(--dim); }
.tasks-location-link{ font-size:10.5px; color:var(--dim); text-decoration:underline; cursor:pointer; }
.tasks-location-link:hover{ color:var(--accent); }
/* Форма добавления: по умолчанию только кнопка, поля разворачиваются по клику */
/* Кнопка добавления заказа живёт в нижней плашке - одним знаком, как и остальные
   действия там. Внутри панели её больше нет: форма разворачивается на месте. */
.tasks-appbar-add{
  background:var(--panel2); border:1px solid var(--line); color:var(--dim);
  font-family:inherit; font-size:18px; line-height:1; width:34px; height:34px;
  cursor:pointer; flex-shrink:0;
}
.tasks-appbar-add:hover{ color:var(--accent); border-color:var(--accent); }
/* Форма заказа - единственное место вкладки, где что-то вводят руками, поэтому
   рамка заметная: на фоне списков блок в тонкую линию терялся. */
.tasks-add-form{
  margin-top:10px; padding:10px; display:flex; flex-direction:column; gap:8px;
  background:var(--panel2); border:1px solid var(--accent-dim); border-radius:6px;
  box-shadow:0 0 0 1px rgba(52,213,255,0.08), 0 2px 10px rgba(0,0,0,0.25);
}
.tasks-add-row{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
/* Подпись над полем: у поля срока без неё не понять, что за дата - её вводят
   заранее, когда заказа ещё нет и подсказать некому. */
.tasks-add-picker-btn{
  width:100%; text-align:left; cursor:pointer;
  background:var(--panel); color:var(--text);
  border:1px solid var(--line); border-radius:6px; padding:6px 8px; font-size:12.5px;
}
/* Группа и метатеги в пункте списка - одной строкой, теги не переносим */
.tasks-pick-line{ display:flex; align-items:center; gap:8px; }
/* Пункт списка выбора: описание сверху, метатеги под ним. */
.tasks-pick-option{ display:flex; flex-direction:column; align-items:flex-start; gap:3px; }
.tasks-pick-option .tasks-tags{ margin:0; }
.tasks-pick-desc{ font-size:12px; color:var(--text); }
.tasks-pick-line .tasks-tags{ flex-shrink:0; margin:0; }

/* Фильтр по сотрудникам: одна строка с прокруткой и стрелками по краям. */
/* Полоса фильтра: прокручиваемая лента чипов и прижатая к правому краю кнопка
   обновления. Стрелки прокрутки лежат внутри .tasks-chips-scroll, а не всей полосы -
   иначе правая стрелка накрывала бы кнопку. */
.tasks-chips-bar{ display:flex; align-items:center; gap:8px; margin-bottom:16px; }
/* Счётчик задач-затычек «Обеспечить». Оранжевый, а не красный: это не поломка -
   красным на этой карте помечены места без источника вовсе и без места процесса, -
   а честное «карту тут ещё не дописали». Кегль и обводка как у прочих значков-
   счётчиков в верхних панелях, чтобы вкладки выглядели одним приложением. */
.tasks-placeholder-warn{
  flex:0 0 auto; font-size:11px; font-weight:700; white-space:nowrap;
  color:var(--orange); border:1px solid var(--orange); border-radius:10px;
  padding:1px 8px; line-height:1.6;
}
.tasks-chips-scroll{ position:relative; flex:1; min-width:0; }
.tasks-chips{
  display:flex; flex-wrap:nowrap; gap:6px; overflow-x:auto; overflow-y:hidden;
  scrollbar-width:none; -webkit-overflow-scrolling:touch;
}
.tasks-chips::-webkit-scrollbar{ display:none; }
.tasks-chip{
  background:var(--panel2); border:1px solid var(--line); color:var(--dim);
  border-radius:14px; padding:4px 12px; font-size:11px; cursor:pointer; font-family:inherit;
  flex-shrink:0; white-space:nowrap;
}
/* Стрелки лежат поверх крайних чипсов с растушёвкой к краю - так видно, что
   список продолжается, и при этом не теряется место под сами чипсы. */
.tasks-chips-arrow{
  position:absolute; top:0; bottom:0; z-index:2; display:none;
  align-items:center; justify-content:center; width:26px;
  background:none; border:none; color:var(--dim); font-size:17px; line-height:1;
  cursor:pointer; padding:0;
}
.tasks-chips-arrow:hover{ color:var(--accent); }
.tasks-chips-arrow.left{ left:0; background:linear-gradient(to right, var(--panel) 45%, transparent); }
.tasks-chips-arrow.right{ right:0; background:linear-gradient(to left, var(--panel) 45%, transparent); }
.tasks-chips-bar.can-left .tasks-chips-arrow.left{ display:flex; }
.tasks-chips-bar.can-right .tasks-chips-arrow.right{ display:flex; }
/* Выбранный чип красим той же заливкой, что и шапки списков: бледная подсветка
   терялась на ленте из полутора десятков чипов, и было не видно, кто выбран. */
.tasks-chip.active{ border-color:var(--accent); color:var(--text); background:var(--accent-dim); font-weight:700; }
.tasks-chips-empty{ font-size:11px; color:var(--dim); }

.tasks-refresh{
  background:none; border:1px solid var(--line); color:var(--dim); font-family:inherit;
  font-size:13px; line-height:1; padding:0; width:26px; height:26px;
  display:flex; align-items:center; justify-content:center;
  border-radius:4px; cursor:pointer; flex-shrink:0;
}
.tasks-refresh:hover{ border-color:var(--accent); color:var(--accent); }
.tasks-refresh:disabled{ cursor:default; opacity:0.5; }

.tasks-list{ display:flex; flex-direction:column; gap:8px; }
.tasks-card{
  display:flex; align-items:center; gap:14px; padding:12px 16px;
  background:var(--panel2); border:1px solid var(--line-soft); border-radius:8px;
  cursor:pointer; flex-wrap:wrap;
}
.tasks-card:hover{ border-color:var(--line); }
/* Верх карточки - отдельный ряд с flex-wrap:nowrap. Раньше подпись и количество
   лежали прямо в .tasks-card, а он переносящийся (это нужно блоку подробностей с
   flex-basis:100%), и при нехватке места флексбокс сбрасывал колонку количества
   на новую строку целиком, вместо того чтобы её сжать. */
.tasks-card-row{ display:flex; align-items:center; gap:14px; flex-wrap:nowrap; flex:1 1 100%; min-width:0; }
/* flex-basis:auto (а не 0) - чтобы флексбокс знал реальную ширину подписи в одну
   строку. Пока места хватает, ничего не происходит; как только не хватает,
   дефицит сначала целиком уходит в колонку количества (см. её flex-shrink), и
   только когда та упёрлась в свой минимум, начинает ужиматься сама подпись. */
.tasks-card-main{ flex:1 1 auto; min-width:0; }
/* Подпись идёт одной строкой: название группы, описание, прочие параметры, метатеги.
   Переносим только когда действительно не влезло. */
.tasks-card-headline{ display:flex; align-items:center; gap:8px 8px; flex-wrap:wrap; }
/* Метатеги переносятся ЦЕЛИКОМ, а не по одному: ряд тегов - это флекс-элемент,
   он уходит на новую строку сразу весь. Раньше здесь стояла распорка flex-basis:100%,
   которая гнала теги под заголовок всегда, даже когда до края оставалось полстроки.
   flex-wrap:wrap внутри самого ряда - последняя ступенька: она срабатывает, только
   если ряд шире карточки и не помещается даже на отдельной строке. */
.tasks-card-headline > .tasks-tags{ flex:0 1 auto; flex-wrap:wrap; max-width:100%; margin-top:0; }
.tasks-card-active{ display:inline-flex; align-items:center; gap:4px; font-size:11px; color:var(--green); font-weight:600; }
.tasks-card-name{ font-size:13px; font-weight:600; }
.tasks-card-subtitle{ font-size:12px; color:var(--text); }
/* Описание - то, что различает карточки внутри одной группы, когда метатегов нет.
   Чуть тише подзаголовка, но не в один тон с подсказками: это часть подписи. */
.tasks-card-desc{ font-size:11.5px; color:var(--text); opacity:0.8; }
.tasks-card-assumed-done .tasks-card-desc{ text-decoration:line-through; }

/* Вид самих метатегов задаётся в visual-tags.js - общем файле с терминалом цеха.
   Здесь остаются только правила про то, как ряд тегов встраивается в конкретные
   места админки: их в терминале нет. */
/* Огромный flex-shrink - это приоритет переносов, а не размер: при нехватке ширины
   первой сдаётся колонка количества ("ХВАТИТ СЫРЬЯ" / "НА 5 ШТ" в две строки), и
   лишь когда она сжалась до своего min-content, очередь доходит до метатегов и
   описания. nowrap перенесён с колонки на сами слова: сам ряд теперь переносим. */
.tasks-card-qty{ font-size:12px; color:var(--accent); flex-shrink:1000; font-weight:600; display:flex; flex-direction:column; gap:2px; align-items:flex-end; text-align:right; margin-left:auto; }
/* Ломаться пополам ("ХВАТИТ СЫРЬЯ" / "НА 5 ШТ") разрешено только помеченным строкам.
   Остальные - "срочно", "сделано", голое число - остаются в одну строку. */
.tasks-qty-row{ display:flex; align-items:baseline; justify-content:flex-end; flex-wrap:nowrap; gap:0 6px; }
.tasks-qty-row-split{ flex-wrap:wrap; }
/* Две строки количества - это два взгляда на одно число ("хватит сырья на" против
   "всего нужно", "срочно" против "всего нужно"). Тире посередине связывает их в пару,
   иначе читаются как два независимых числа. Псевдоэлемент вынесен из потока и
   центрирован по границе строк, поэтому расстояния между ними не прибавляет. */
.tasks-qty-row + .tasks-qty-row{ position:relative; }
.tasks-qty-row + .tasks-qty-row::before{
  content:'–'; position:absolute; left:50%; top:-1px;
  transform:translate(-50%, -50%);
  font-size:10px; font-weight:400; line-height:1; color:var(--dim2); pointer-events:none;
}
/* Миниатюра позиции у закупок. Размер по высоте двух строк количества, чтобы
   карточка не подрастала из-за картинки. */
.tasks-card-photo{
  width:38px; height:38px; flex-shrink:0; border-radius:6px; object-fit:cover;
  background:var(--panel2); border:1px solid var(--line-soft); display:block;
}
/* Прогресс задачи в работе идёт в три строки - выравниваем их по правому краю,
   как и остальные количества в карточке. */
.tasks-qty-val{ text-align:right; line-height:1.35; white-space:nowrap; }
.tasks-qty-tag{ font-size:10px; font-weight:400; color:var(--dim); text-transform:uppercase; letter-spacing:0.5px; white-space:nowrap; }
/* Время выравниваем по правому краю и фиксируем ширину - так две строки читаются
   столбиком, а не лесенкой. */
.tasks-qty-time{ font-size:11.5px; font-weight:400; color:var(--dim); min-width:74px; text-align:right; }
.tasks-card-duration{ font-size:11.5px; color:var(--dim); white-space:nowrap; flex-shrink:0; }
.tasks-card-actions{ display:flex; gap:6px; flex-shrink:0; }
.tasks-card-recount{ }
.tasks-card-supply .tasks-card-qty{ color:var(--accent); }

/* Галочка "считать выполненным" - поправка к остаткам, когда материал по факту
   есть на рабочем месте, а склад об этом не знает. */
/* Галочки "считать выполненным" на карточке больше нет: действие убирает
   потребность из расчёта всей цепочки, а снаружи оно ловилось случайным пальцем.
   Теперь это кнопка внутри раскрытой карточки, .tasks-why-btn. */
.tasks-card-assumed-done{ opacity:0.5; }
.tasks-card-assumed-done .tasks-card-name,
.tasks-card-assumed-done .tasks-card-subtitle{ text-decoration:line-through; }
.tasks-card-assumed-done .tasks-card-qty{ color:var(--green); }
.tasks-done-hint{ font-size:10.5px; color:var(--dim); margin-bottom:8px; line-height:1.6; }

.tasks-detail-warn{ color:var(--orange); }
/* Красным - только то, что означает ошибку в данных, а не просто ожидание.
   Оранжевый тут уже занят предупреждениями, которые в порядке вещей. */
.tasks-detail-alert{ color:var(--red); }
.tasks-card-alert{ color:var(--red); font-size:11px; margin-top:2px; }
.tasks-detail-quickwin{ color:var(--purple); }

/* Пачка подряд идущих задач одной группы - общая рамка с заголовком.
   Заголовок оформлен как имя карточки, чтобы не путаться с "ДЕЛАТЬ СЕЙЧАС"
   (тот - мелкая капслок-метка раздела, а это название конкретной работы). */
.tasks-run{
  display:flex; flex-direction:column; gap:6px;
  border:1px solid var(--line); border-radius:8px; padding:10px 12px;
}
.tasks-run-title{ font-size:13px; font-weight:600; color:var(--text); }
/* Карточки внутри пачки занимают её ширину целиком: роль отступа играет padding
   самой рамки. Раньше здесь были линии иерархии (вертикаль от заголовка + ветка
   вправо) и margin-left под них. Они говорили то же, что и рамка, - "эти карточки
   вместе", - но не показывали, где группа кончается, и были размечены фиксированными
   числами (top:20px, height:26px) под карточку одной высоты: у раскрытой или
   двухстрочной ветка уезжала мимо. Остались рамка и ровный левый край. */
.tasks-run .tasks-card{
  background:var(--bg); border-color:var(--line-soft);
  position:relative;
}

/* Задача, на которую сырья хватает не на весь объём. Рыжей рамки у неё больше нет -
   в этом списке рыжий читается как "горит", а тут ровно наоборот. Вместо этого
   приглушаем: делать её можно прямо сейчас, но придётся возвращаться, поэтому среди
   полностью обеспеченных работ она вторым эшелоном. Гасим слабее, чем блок "Ждут
   материалов" (там 0.6): та работа не начинается вовсе, а эта начинается.
   Под курсором и в раскрытом виде возвращаем полный цвет - читать подробности
   сквозь дымку неудобно. */
.tasks-card.tasks-card-partial{ opacity:0.45; }
.tasks-card.tasks-card-partial:hover,
.tasks-card.tasks-card-partial.tasks-card-expanded{ opacity:1; }
/* Задачи из блока "Ждут материалов": сырья нет вовсе, поэтому глушим сильнее -
   взгляд не должен цепляться за них при просмотре списка. */
.tasks-waiting-materials .tasks-card{ opacity:0.45; }
.tasks-waiting-materials .tasks-card:hover,
.tasks-waiting-materials .tasks-card.tasks-card-expanded{ opacity:1; }
.tasks-card.tasks-card-partial .tasks-card-qty{ color:var(--dim); }
/* Окно «почему столько». Таблица нарочно плотная: в ней сравнивают три числа в
   строке, и воздух между ними мешает больше, чем помогает. */
.tasks-why-btn{
  display:block; width:100%; text-align:left; margin-bottom:6px;
  background:rgba(52,213,255,0.06); border:1px solid var(--accent-dim); color:var(--accent);
  border-radius:4px; padding:6px 8px; font-family:var(--mono); font-size:11px; cursor:pointer;
}
.tasks-why-btn:hover{ background:rgba(52,213,255,0.14); }
.tasks-explain{ width:min(720px, 94vw); max-height:88vh; overflow-y:auto; }
.tasks-explain-lead{ color:var(--dim); font-size:11px; margin-bottom:10px; }
.tasks-explain-sub{ margin:12px 0 4px; color:var(--dim); font-size:11px; }
/* Цепочка расчёта текстом. Абзацы короткие, между ними воздух: читают их подряд,
   и слитная простыня сводит на нет весь смысл затеи.

   Подпись объекта внутри предложения ведёт себя как обычные слова: никаких своих
   переносов, никаких колонок - иначе фраза «Для процесса X нужно…» рвётся на три
   строки и перестаёт читаться. Метатеги тоже переносятся по месту, как слова.
   Правило действует только в этом окне: на карте и в карточках подпись остаётся
   вертикальной, там она заголовок блока, а не часть фразы. */
.tasks-explain-chain{ margin-bottom:10px; font-size:12px; line-height:1.5; }
.tasks-explain-chain p{ margin:0 0 7px; }
.tasks-explain-chain p:last-child{ margin-bottom:0; }
.tasks-explain-chain b{ color:var(--accent); font-weight:600; white-space:nowrap; }
/* Подпись объекта внутри предложения: она сама по себе flex-строка, поэтому
   выравниваем её по базовой линии текста, иначе съезжает вниз. */
/* Подпись объекта внутри предложения собирается в tasks.js обычными строчными
   элементами (tasks-explain-name), поэтому ей хватает пары правил: метатеги должны
   вести себя как слова и переноситься по месту, а не выстраиваться в неразрывный ряд. */
.tasks-explain-name{ color:var(--text); }
.tasks-explain-name .tasks-tags{ display:inline; }
.tasks-explain-name .tasks-tag-model,
.tasks-explain-name .tasks-tag-size,
.tasks-explain-name .tasks-tag-inspection{ display:inline-flex; vertical-align:middle; margin:0 2px; }
.tasks-explain-name .tasks-tag-shape{ vertical-align:middle; margin:0 2px; }
/* Красным - только сам ярлык заказа: он делит таблицу на цепочки, и по нему глаз
   находит начало каждой. Красить всю строку значит превратить её в тревогу. */
.tasks-explain-order{ color:var(--red); font-weight:600; }
.tasks-explain-hint{ color:var(--dim2); font-size:10px; margin-top:2px; }
/* Служебные слова между подписями объектов: «Для работы», «нужно N на единицу».
   Тусклые и мелкие - в ячейке главное сами объекты и числа. */
.tasks-explain-step{ color:var(--dim2); font-size:10px; margin:2px 0; }
.tasks-explain .entity-label{ display:flex; }
.tasks-explain-notes{ margin-top:10px; display:flex; flex-direction:column; gap:6px; font-size:11px; }
/* Лента операций в окне переучёта. Моноширинные цифры - чтобы столбик остатка
   читался сверху вниз как столбик, а не как рваный текст. */
/* Число на блоке - норма, а не потребность: спроса на процесс сейчас нет.
   Помечаем пунктиром снизу, чтобы не путать с посчитанной цифрой. */
.map-norm-only{ border-bottom:1px dotted currentColor; opacity:0.75; }
.tasks-recount-ops{ width:100%; border-collapse:collapse; font-size:11px; }
.tasks-recount-ops td{ padding:4px 8px 4px 0; border-bottom:1px solid var(--line-soft); vertical-align:top; }
.tasks-recount-op-date{ color:var(--dim); white-space:nowrap; }
.tasks-recount-op-qty, .tasks-recount-op-run{ font-family:var(--mono, monospace); text-align:right; white-space:nowrap; }
.tasks-recount-op-run{ color:var(--dim); }
.tasks-recount-op-neg .tasks-recount-op-run{ color:var(--red); font-weight:700; }
.tasks-recount-op-deleted td{ opacity:0.45; text-decoration:line-through; }
.tasks-recount-op-flag{ font-size:9.5px; color:var(--dim); text-decoration:none; display:inline-block; }
.tasks-explain-close{ margin-top:12px; }
/* Скрыть закупки. Значок один, состояние показывает перечёркивание: две разные
   картинки на одной кнопке читались бы как две разные кнопки. */
/* Значок выгрузки для ИИ - в нижней плашке и в строке заказа. Оформление общее:
   это одно и то же действие, отличается только объём выгрузки. */
.tasks-prompt-btn{ background:none; border:0; padding:0 6px; font-size:16px; line-height:1; cursor:pointer; opacity:.8; }
.tasks-prompt-btn:hover{ opacity:1; }
.tasks-order-prompt{ font-size:13px; padding:0 2px; }
/* Ряд действий в раскрытой карточке: слева направо, с запасом на будущие кнопки.
   Рамка и отступы обязательны - без них значок не читается как кнопка и по нему
   тяжело попасть пальцем. */
.tasks-card-actions{ display:flex; gap:6px; flex-wrap:wrap; margin:0 0 8px; }
.tasks-card-act{
  min-width:32px; height:30px; padding:0 9px;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--line); border-radius:6px; background:var(--card2, transparent);
  color:var(--text); font-size:15px; line-height:1; cursor:pointer;
}
.tasks-card-act:hover{ border-color:var(--accent-dim); }
.tasks-card-act:active{ transform:scale(.96); }
/* Отмена заказа - действие необратимое, поэтому единственная кнопка в ряду, которая
   краснеет при наведении. Обычным видом она стоит специально: красная с самого
   начала притягивала бы палец. */
.tasks-card-act-danger:hover{ border-color:var(--red); color:var(--red); }
/* Сообщение о результате: кнопки под рукой нет, а знать, сработало ли, надо. */
.tasks-prompt-toast{ position:fixed; left:50%; bottom:72px; transform:translateX(-50%) translateY(8px);
  background:var(--card,#222); color:var(--fg,#eee); border:1px solid var(--line,#444);
  border-radius:8px; padding:8px 14px; font-size:13px; z-index:9999;
  opacity:0; pointer-events:none; transition:opacity .18s, transform .18s; max-width:90vw; text-align:center; }
.tasks-prompt-toast.show{ opacity:1; transform:translateX(-50%) translateY(0); }
.tasks-supply-toggle{ position:relative; background:none; border:0; padding:0 6px; font-size:17px; line-height:1; cursor:pointer; opacity:.85; }
.tasks-supply-toggle.active{ opacity:.45; }
.tasks-supply-toggle.active::after{ content:''; position:absolute; left:4px; right:4px; top:50%; height:2px; background:var(--danger,#e5484d); transform:rotate(-20deg); }

/* Подробности - скрыты, раскрываются кликом (tasksToggleCardDetails). Один и тот же
   блок у карточки задачи, строки очереди и обоих предложений «можно сделать»: жест
   везде одинаковый, значит и разметка должна быть одна. */
.tasks-card-details{ display:none; }
.tasks-card-expanded .tasks-card-details{
  display:block; flex-basis:100%; margin-top:8px; padding-top:8px;
  border-top:1px dashed var(--line-soft); font-size:11px; color:var(--dim); line-height:1.7;
}
/* Раскрывается вся строка целиком, поэтому курсор ставим на неё, а не на заголовок:
   иначе непонятно, куда именно нажимать. У кнопок внутри свой курсор, он перебивает. */
.tasks-order-row, .tasks-spare-row{ cursor:pointer; }
/* Внутри подробностей ряд кнопок и так отбит снизу - двойной отступ не нужен. */
.tasks-card-details > .tasks-card-actions:first-child{ margin-top:0; }

/* Заголовки блоков - синие полосы во всю ширину. Раньше это была строчка того же
   роста и цвета, что подписи внутри карточек, и в потоке из полусотни строк переход
   между блоками просто не читался. Заливка делает из заголовка полосу, а не текст, -
   проскочить её глазом уже нельзя.
   Синий взят из --accent-dim, а не --accent: сплошная полоса неонового #34d5ff на
   почти чёрном фоне режет глаза, а приглушённый вариант держит контраст с текстом
   в обеих темах (на светлой он, наоборот, светлее текста).
   Иерархия осталась, но тише: у "В работе" и "Делать сейчас" акцентная грань слева -
   они всегда раскрыты и есть главное на экране. */
.tasks-group-title{
  display:flex; align-items:center; gap:8px;
  font-size:12px; text-transform:uppercase; letter-spacing:1.2px; font-weight:700;
  color:var(--text); background:var(--accent-dim);
  border-radius:6px; padding:7px 12px; margin:22px 0 8px;
  border-left:3px solid transparent;
}
.tasks-group-title-main{ border-left-color:var(--accent); }
/* Цвет шапки = состояние блока, и по нему список читается с одного взгляда, не
   вчитываясь в подписи: зелёное уже идёт, красное надо брать, жёлтое стоит и ждёт,
   красное перечёркнутое выключено руками. Фон приглушённый (--*-dim), а грань слева
   в полный цвет: сплошная заливка ярким на полсотни карточек рябит, а тонкая полоса
   держит различие даже боковым зрением. Значок дублирует цвет - на светлой теме
   разница между зелёным и жёлтым фоном меньше, чем хотелось бы, да и дальтонику
   цвет не подсказка. */
.tasks-group-go{ background:var(--green-dim); border-left-color:var(--green); }
.tasks-group-now{ background:var(--red-dim); border-left-color:var(--red); }
.tasks-group-wait{ background:var(--orange-dim); border-left-color:var(--orange); }
.tasks-group-off{ background:var(--red-dim); border-left-color:var(--red); }
.tasks-group-idle{ background:var(--panel2); border-left-color:var(--dim2); }

/* Число в кружке: глаз цепляется за него раньше, чем читает подпись. На синей полосе
   кружок берёт фон панели - он контрастен и в тёмной теме, и в светлой. */
.tasks-group-count{
  font-size:10px; font-weight:700; letter-spacing:0; color:var(--text);
  background:var(--panel); border-radius:10px; padding:1px 7px; line-height:1.5;
}
.tasks-list > .tasks-group-title:first-child{ margin-top:0; }
/* Шапка прилипает к верху прокрутки: в списке на полсотни карточек иначе не видно,
   куда именно смотришь - в "Делать сейчас" или уже в "Ждут материалов". У каждого
   свёрнутого блока свой контейнер (сам <details>), поэтому его шапка стоит только
   пока виден блок, и заголовки сменяют друг друга сами. Заголовки блоков идут выше
   главного: главный держится через весь список, и на стыке они накладываются. */
.tasks-group-title{ position:sticky; top:var(--topbar-h, 0px); z-index:4; }
/* В разделённом экране прокручивается сама панель, а не страница: её верх уже под
   шапкой, и поправка на её высоту увела бы заголовок вниз на пустое место. */
body.split-on .tasks-group-title{ top:0; }
.tasks-waiting-block > summary.tasks-group-title{ z-index:6; }
/* Своя стрелка вместо системного маркера: у flex-контейнера он не рисуется, да и
   от заглавных с межбуквенным интервалом системный съезжает - тем же приёмом
   сделаны заголовки в очереди заказов (.tasks-spare-title). */
.tasks-waiting-block > summary.tasks-group-title{ cursor:pointer; user-select:none; list-style:none; }
.tasks-waiting-block > summary.tasks-group-title::-webkit-details-marker{ display:none; }
.tasks-waiting-block > summary.tasks-group-title::before{ content:'▸'; font-size:10px; transition:transform 0.15s; }
.tasks-waiting-block[open] > summary.tasks-group-title::before{ transform:rotate(90deg); }
/* Свёрнутый блок раскрывают кликом, поэтому полоса реагирует на наведение. Меняем
   яркость, а не цвет: подбирать второй оттенок синего под обе темы незачем. */
.tasks-waiting-block > summary.tasks-group-title:hover{ filter:brightness(1.12); }
.tasks-waiting-block[open] > summary{ margin-bottom:8px; }
.tasks-waiting-block .tasks-card{ opacity:0.6; }
/* Пачку одинаковых работ гасим целиком, вместе с её заголовком: иначе название
   группы оставалось в полном цвете и выглядело ярче самих карточек под ним.
   Внутренним карточкам прозрачность возвращаем, чтобы она не умножилась дважды. */
.tasks-waiting-block .tasks-run{ opacity:0.6; }
.tasks-waiting-block .tasks-run .tasks-card{ opacity:1; }
.tasks-waiting-block .tasks-card + .tasks-card{ margin-top:8px; }

/* ---------- МОБИЛЬНАЯ ВЕРСТКА ---------- */
@media (max-width: 760px){
  /* Шапка только показывает, где ты находишься: всё управление в меню у нижнего края. */
  .topbar{ gap:10px; padding:10px 12px; }

  .appbar{ padding-left:10px; padding-right:10px; }
  .tasks-main{ width:100%; min-width:0; }
  .tasks-priority-row, .tasks-order-row{ font-size:13px; }

  /* Заслонки у стрелок прокрутки должны совпадать с фоном полосы, а не со страницей. */
  .tasks-chips-arrow.left{ background:linear-gradient(to right, var(--panel) 45%, transparent); }
  .tasks-chips-arrow.right{ background:linear-gradient(to left, var(--panel) 45%, transparent); }

  /* Карта: меньше полей вокруг холста - на узком экране они съедают полезное место. */
  .map-wrap{ padding:12px; }
  .map-legend{ flex-wrap:wrap; gap:10px; padding:10px 14px; }

  /* Окно нормы: фиксированная ширина не влезала, поля уезжали за край. */
  .map-qty-dialog{ min-width:0; width:92vw; max-width:92vw; padding:16px 14px 12px; }
  .map-qty-row{ flex-wrap:wrap; }
  .map-qty-label{ width:100%; }
  /* 16px - меньше этого Safari зумит страницу при фокусе на поле. */
  .map-qty-input{ font-size:16px; width:96px; }
  .map-qty-btn{ padding:6px 14px; }

  .metric-cards{ gap:10px; }
  .metric-card{ min-width:0; flex:1 1 140px; padding:12px 14px; }
  .metrics-wrap{ padding:14px; gap:16px; }

  /* Окно «почему столько» на телефоне остаётся таблицей: три числа в строке
     сравнивают глазами, и разложенные в столбик они перестают сравниваться.
     Ужимаем шрифт и отступы, числам разрешаем переносы, подпись объекта в первой
     колонке и так идёт в столбик - её ширина минимальная. */
  .tasks-explain{ width:96vw; padding:12px 10px; max-height:92vh; }
  .tasks-explain-chain{ font-size:11.5px; }
  .tasks-explain .entity-label{ font-size:10px; }
  .tasks-explain .tasks-explain-step{ font-size:9px; }
}

/* Меню правого клика и выбор продукта на карте связей. Стили держим здесь, а не
   в <style> внутри SVG: сами элементы живут в body, и правила из SVG до них
   доходили не всегда - меню оказывалось в потоке страницы, ниже и правее курсора. */
.map-context-menu{
  position:fixed; z-index:9999; background:var(--panel); border:1px solid var(--line);
  border-radius:6px; padding:4px; box-shadow:0 4px 14px rgba(0,0,0,0.35);
}
.map-context-menu button{
  background:transparent; border:none; color:var(--text); text-align:left;
  padding:7px 12px; cursor:pointer; border-radius:4px; font-family:var(--mono); font-size:12px;
}
.map-context-menu button:hover{ background:rgba(127,127,127,0.15); color:var(--accent); }

.map-picker-backdrop{
  position:fixed; inset:0; z-index:9999; background:rgba(0,0,0,0.45);
  /* Высокое окно (карточка блока со сводкой) при центрировании по вертикали уезжало
     верхушкой за край экрана - и до заголовка с полями было не добраться. Прижимаем
     к верху с отступом и прокручиваем сам фон. */
  display:flex; align-items:flex-start; justify-content:center;
  padding:16px; overflow-y:auto; overscroll-behavior:contain;
}
.map-picker{
  position:relative; background:var(--panel); border:1px solid var(--line);
  border-radius:8px; padding:16px; width:min(420px, 92vw); margin:auto;
  font-family:var(--mono); font-size:12px; color:var(--text);
  box-shadow:0 10px 40px rgba(0,0,0,0.5);
}
.map-picker-title{ margin-bottom:10px; margin-right:20px; }
/* Карточка блока карты: та же форма, что при создании, плюс фото и сводка снизу -
   в узкое окно выбора это уже не помещается. */
.map-picker-wide{ width:min(560px, 94vw); }
.map-edit-photo{ display:flex; flex-direction:column; gap:6px; align-items:flex-start; margin-bottom:8px; }
.map-edit-photo-img{ max-width:100%; max-height:180px; border:1px solid var(--line); border-radius:6px; }
.map-edit-details{ margin-top:14px; padding-top:12px; border-top:1px solid var(--line); }
/* Вид самой подписи (группа, описание, строки параметров, метатеги) задаётся в
   visual-tags.js - общем файле с терминалом цеха. */

/* Колонка метатегов в справочниках: только для чтения, не растягиваем таблицу. */
.tags-cell{ white-space:nowrap; }
.tags-cell .tasks-tags{ flex-shrink:0; }
.map-edit-add-panel{ border:1px solid var(--line); border-radius:6px; padding:6px; margin-bottom:8px; }
.map-edit-add-list{ max-height:220px; overflow-y:auto; margin-top:6px; }
.map-picker-search{ width:100%; font-family:var(--mono); font-size:12px; padding:5px 8px; margin-bottom:8px; }
.map-picker-list{ max-height:50vh; overflow-y:auto; }
.map-picker-option{ padding:6px 8px; cursor:pointer; border-radius:4px; }
/* Пункт "создать" стоит над списком и не должен теряться среди сотен позиций -
   отделяем чертой и подсвечиваем акцентом. */
.map-picker-create{ color:var(--accent); border:1px dashed var(--line); margin-bottom:6px; width:100%; text-align:left;
  background:transparent; font-family:inherit; font-size:inherit; }
/* Строка списка: название кликается целиком, кнопка дублирования прижата вправо. */
.map-picker-row{ display:flex; align-items:center; gap:4px; }
.map-picker-row .map-picker-option{ flex:1 1 auto; min-width:0; }
/* Описание - второй строкой, мельче и приглушённо: оно уточняет выбор, но не должно
   спорить с названием и метатегами. */
.map-picker-desc{ display:block; font-size:10px; color:var(--dim); margin-top:2px; }
.map-picker-dup{ flex:0 0 auto; cursor:pointer; background:transparent; border:1px solid var(--line);
  color:var(--dim); border-radius:4px; padding:2px 7px; font-size:12px; line-height:1.4; }
.map-picker-dup:hover{ color:var(--accent); border-color:var(--accent); }
/* Заголовок группы внутри списка выбора - те же правила, что у групп в пикере полей. */
.map-picker-group-label{ padding:6px 8px 2px; font-size:10px; letter-spacing:1px; text-transform:uppercase;
  color:var(--dim); position:sticky; top:0; background:var(--panel2); }
.map-picker-create:hover{ border-color:var(--accent); background:rgba(127,127,127,0.10); }
.map-newline-primary{ color:var(--accent); }
.map-picker-option:hover{ background:rgba(127,127,127,0.12); color:var(--accent); }

/* Окно создания связи на карте. */
.map-newline-body{ display:flex; flex-direction:column; gap:8px; }
.map-newline-arrow{ font-size:13px; line-height:1.5; }
.map-newline-note{ font-size:11px; color:var(--dim); line-height:1.5; }
.map-newline-label{ font-size:11px; color:var(--dim); margin-top:4px; }
.map-newline-select{ font-family:var(--mono); font-size:12px; padding:5px 8px; width:100%; }
.map-newline-actions{ display:flex; justify-content:flex-end; gap:8px; margin-top:14px; }

/* Пункт списка выбора фокуса на карте: название сверху, локация под ним. */
.map-pick-item{ display:flex; flex-direction:column; align-items:flex-start; gap:2px; }
.map-pick-loc{ font-size:10px; color:var(--dim); }

/* "Скоро понадобится купить" - позиции, которых нет на складе, но материал лежит
   у станка. Приглушены: это не дело на сегодня, а предупреждение на будущее. */
.tasks-wip-watch{ margin-top:18px; opacity:0.75; }
.tasks-wip-note{ font-size:11px; color:var(--dim); margin-bottom:8px; line-height:1.5; }
.tasks-wip-row{
  display:flex; align-items:baseline; gap:12px; padding:6px 0;
  border-bottom:1px dashed var(--line-soft); font-size:12px;
}
.tasks-wip-name{ flex:1; min-width:0; }
.tasks-wip-loc{ font-size:10px; color:var(--dim); }
.tasks-wip-qty{ color:var(--accent); white-space:nowrap; }
.tasks-wip-recipe{ font-size:10px; color:var(--dim); max-width:40%; text-align:right; }

/* Расшифровка расчёта количества в подробностях задачи. */
.tasks-detail-calc{ color:var(--dim); }

/* Цвет карточки заказа = запас времени. Правила стоят в конце файла намеренно:
   базовое .tasks-order-row задаёт свой фон, специфичность у них одинаковая, и
   побеждает то, что ниже. Кроме заливки - полоса слева: при ярком свете в цеху
   бледная заливка почти не видна. */
/* Заливкой красим не карточку, а только подпись срока: цветной прямоугольник во всю
   строку заслонял и номер, и метатеги, а срочность - свойство даты, а не заказа
   целиком. Цвет уходит в рамку целиком, слева она толще - по этой полосе список
   читается сверху вниз, не вчитываясь в сами карточки. */
.tasks-order-row.tasks-order-overdue,
.tasks-order-row.tasks-order-urgent{ border:1px solid var(--red); border-left:3px solid var(--red); }
.tasks-order-row.tasks-order-soon{ border:1px solid #e6c62e; border-left:3px solid #e6c62e; }
.tasks-order-row.tasks-order-ok{ border:1px solid #4caf50; border-left:3px solid #4caf50; }

/* Название группы - оно же переключатель фильтра. Пунктир снизу, а не цвет:
   заголовок карточки должен читаться как заголовок, а не как ссылка. */
.tasks-card-name-group{ cursor:pointer; border-bottom:1px dashed var(--line); }
/* Заголовок пачки - блочный элемент в колоночном флексе, и по умолчанию его
   растягивает на всю ширину списка (align-items:stretch), вместе с пунктиром.
   Прижимаем к левому краю, чтобы подчёркивание шло только под текстом. */
.tasks-run-title.tasks-card-name-group{ display:inline-block; align-self:flex-start; max-width:100%; }
.tasks-card-name-group:hover{ color:var(--accent); border-bottom-color:var(--accent); }
/* Сколько всего таких же работ можно делать прямо сейчас. Намеренно мелко:
   это подсказка к решению «ехать сейчас или подождать», а не часть названия. */
.tasks-card-name-count{ font-size:10px; font-weight:400; color:var(--dim); margin-left:4px; }

/* Плашка активного фильтра по группе работ. */
/* Плашка активного фильтра прибита к экрану прямо над нижней полосой действий -
   там же, где и кнопка, которой фильтр снимают. Фильтр действует на весь список,
   поэтому при прокрутке она не уезжает. */
.tasks-group-filter{
  display:flex; align-items:center; gap:10px;
  font-size:11px; color:var(--accent);
  position:fixed; left:0; right:0; bottom:var(--appbar-h, 58px); z-index:899;
  margin:0; padding:7px 12px;
  background:var(--panel2); border-top:1px solid var(--line);
}
/* Пока фильтр включён, нижние карточки не должны прятаться под ним. В разделённом
   экране отступ не нужен: там панель прокручивается сама и её низ и так выше плашки. */
body:has(.tasks-group-filter) .panes{ padding-bottom:calc(var(--appbar-h, 58px) + 38px); }
body.split-on:has(.tasks-group-filter) .panes{ padding-bottom:0; }
.tasks-group-filter button{
  background:transparent; border:1px solid var(--line); color:var(--dim);
  border-radius:4px; padding:3px 10px; cursor:pointer; font-family:var(--mono); font-size:10px;
}
.tasks-group-filter button:hover{ border-color:var(--accent); color:var(--accent); }

/* Пробел зажат - холст готов к перетаскиванию: показываем это курсором. */
.map-wrap.map-panning, .map-wrap.map-panning *{ cursor:grab !important; }
/* Курсор подсказывает, что сейчас сделает левая кнопка по пустому месту: ладонь -
   потащит холст, крестик - начнёт рамку выделения. Над блоками курсор свой. */
.map-wrap{ cursor:grab; }
.map-wrap svg.map-edit-mode{ cursor:crosshair; }
.map-wrap svg.map-edit-mode .map-node{ cursor:move; }
/* Подсказка про закреплённые поставки: они видны и с выключенной галочкой, и без
   этой строки поведение выглядит поломкой. */
.map-pinned-supply{ font-size:11px; color:var(--orange); display:inline-flex; align-items:center; gap:6px; }
.map-pan-hint{ font-size:10px; color:var(--dim); white-space:nowrap; }

/* ===== СТИЛИ КАРТЫ СВЯЗЕЙ =====
   Жили внутри <style> прямо в разметке SVG - 172 строки посреди функции отрисовки,
   которая и без них самая длинная в проекте. SVG вставляется в документ инлайном и
   наследует его стили, так что правила работают отсюда точно так же, а перерисовка
   карты больше не тащит их за собой в каждую сборку строки. */
    .map-node { transition: opacity 0.2s; cursor: pointer; touch-action: none; }
    .map-edge { transition: opacity 0.2s, stroke-width 0.2s, stroke 0.2s; fill: none; stroke: var(--dim); stroke-width: 1.5px; marker-end: url(#arrow); }
    .map-node.dimmed { opacity: 0.15; }
    .map-edge.dimmed { opacity: 0.08; marker-end: none; }
    /* Промежуточный отрезок длинной связи: наконечник нужен только там, где линия
       действительно упирается в блок, иначе стрелки сыплются по всему пути. */
    .map-edge-mid { marker-end: none; }
    .map-edge.highlighted { stroke: var(--accent) !important; stroke-width: 3px !important; opacity: 1 !important; marker-end: url(#arrow-hi) !important; }
    .map-node.highlighted > rect, .map-node.highlighted > polygon { stroke: var(--accent) !important; stroke-width: 2px !important; }
    /* ---------- ЧТО ЧЕМ ОБОЗНАЧЕНО ----------
       Форма  - что это: прямоугольник со скруглением - процесс, параллелограмм и
                терминатор - продукт. Одного признака достаточно, дублировать его
                цветом незачем.
       Рамка  - только состояние данных: красная «взять неоткуда», розовая «нет
                места», оранжевая «не хватает на складе». Любая цветная рамка на
                карте значит ровно одно - здесь что-то не заполнено. Раньше сюда же
                шли фиолетовый у процессов и зелёный у продуктов, и покрасневшую
                рамку было не отличить от обычной.
       Линия  - роли и маршруты: побочный выход, запасной вход, запасной маршрут,
                разбор запасов, возвратная петля. Это свойства связи, а не блока.
       Яркость - в основном ли потоке узел относительно текущего фокуса. */
    /* Рамка того же цвета, что и стрелки (--dim): блок и связь - части одного
       рисунка, и разная серость читалась как разница по смыслу, которой нет. */
    .map-node-recipe > rect { fill: var(--panel2); stroke: var(--dim); stroke-width: 1.5px; }
    .map-node-branch > rect { fill: var(--panel2); stroke: var(--map-dash); stroke-width: 1.6px; stroke-dasharray: 4 3; }
    .map-node-item > rect, .map-node-item > polygon { fill: var(--panel2); stroke: var(--dim); stroke-width: 1px; }
    /* Терминатор (сырьё без производителя) и параллелограмм (обычный продукт) - это
       формы, а не состояния. Зелёную обводку у них убрал вместе с остальными
       цветами сущностей. */
    .map-terminator-raw, .map-parallelogram { stroke: var(--dim); }
    .map-node-byproduct > rect, .map-node-byproduct > polygon { stroke: var(--map-dash) !important; }
    .map-node-byproduct { opacity: 0.1; transition: opacity 0.15s; }
    .map-edge-defect { opacity: 0.1; transition: opacity 0.15s; }
    .map-edge-branch { opacity: 0.1; transition: opacity 0.15s; }
    .map-edge-branch:hover, .map-edge-branch.map-edge-hovered { opacity: 1 !important; }
    .map-node-byproduct:hover, .map-edge-defect:hover { opacity: 1 !important; }
    .map-edge-hovered { stroke: var(--dim) !important; opacity: 1 !important; marker-end: url(#arrow) !important; }
    /* Подпись - это текст в рамке, а не линия: обводка и стрелка ей не нужны,
       от подсветки требуется только проявиться вместе со своей связью. */
    .map-edge-label.map-edge-hovered { stroke: none !important; marker-end: none !important; }
    /* Побочный узел тоже метим пунктиром, а не цветом - по той же причине.
       Галочку «Показывать тупики» включают ровно затем, чтобы их рассмотреть,
       поэтому при ней - полная яркость. Пунктир и так отличает их от основного
       потока, притушивать сверх этого незачем. */
    svg.show-defects .map-node-byproduct { opacity: 1 !important; }
    /* Штрих тот же, что у связи побочного выхода (7 5): блок и ведущая к нему линия
       должны выглядеть одинаково - по рамке сразу видно, каким путём узел связан
       с основным потоком. Было 5 4, и рисунки не совпадали. */
    .map-node-byproduct > rect, .map-node-byproduct > polygon { stroke-dasharray: 7 5; }
    /* Побочка, брак и всё, что не ведёт к фокусу - на карте таких блоков быть
       не должно. Если всё же попались (включена галочка побочных) - красный
       фон, чтобы сразу было видно. */
    /* Заливку побочных блоков не трогаем: тёмно-красный фон читался как ошибка и
       спорил с текстом. Их и так отличают приглушённость и жёлтая рамка. */
    svg.show-defects .map-edge-defect { opacity: 1 !important; }
    /* Не в основном потоке - альтернативный путь и возвратная петля. Раньше они
       метились цветом рамки (жёлтым и фиолетовым), но рамка отдана под поломки:
       узел на запасной ветке - не ошибка, и спорить с красным ему незачем.
       Теперь это приглушённость плюс пунктир, как у всего второстепенного. */
    .map-node-cat-alt > rect, .map-node-cat-alt > polygon,
    .map-node-cat-back > rect, .map-node-cat-back > polygon {
        fill: var(--panel2) !important; stroke: var(--map-dash) !important;
        stroke-width: 1.6px !important; stroke-dasharray: 5 4;
    }
    /* Приглушены, пока их не попросили показать. Включена своя галочка - видно в
       полную силу: иначе выходит, что человек нажал «показать», а блоки всё равно
       бледные. */
    /* Приглушение лёгкое: цвет рамки у них тот же, что у стрелок, и гасить его
       прозрачностью значит снова делать их бледно-серыми - ровно от этого и уходили.
       Отличать неосновную ветку должен пунктир, а не выцветание. */
    .map-node-cat-alt, .map-node-cat-back { opacity: 0.85 !important; }
    svg.show-alt-paths .map-node-cat-alt { opacity: 1 !important; }
    svg.show-back-cycles .map-node-cat-back { opacity: 1 !important; }
    .map-node-cat-alt:hover, .map-node-cat-back:hover { opacity: 1 !important; }
    .map-node-insufficient > rect, .map-node-insufficient > polygon { stroke: var(--orange) !important; stroke-width: 2px !important; }
    .map-node-flash > rect, .map-node-flash > polygon { fill: var(--red) !important; transition: fill 0.15s ease; }
    .node-text-wrap {
        display: flex; align-items: center; justify-content: center; height: 100%;
        text-align: center; font-family: var(--mono); font-size: 11px; line-height: 1.25;
        word-break: break-word; overflow: hidden; pointer-events: none; user-select: none; padding: 0 6px;
    }
    /* Подпись блока в четыре яруса: название, группа, описание, метатеги. Название
       серое и всегда в одну строку - длинные имена раздували блок и вытесняли всё
       остальное; полное имя остаётся в подсказке. */
    .node-text-lines { flex-direction: column; gap: 1px; }
    .node-text-lines > * { max-width: 100%; }
    /* Группа - главная подпись блока: тот же стиль, что был у названия, только
       жирный. Не сокращаем - переносим по словам, места под неё считает nodeHeightOf. */
    /* Подпись блока - та же разметка, что и везде (см. visual-tags.js). На карте
       она крупнее и по центру; наведение на группу показывает полное название. */
    .node-text-lines .entity-label { align-items: center; text-align: center; max-width: 100%; }
    /* Текст блока по умолчанию прозрачен для мыши - иначе он перехватывал бы клики,
       которыми блок тащат и открывают. Но подсказку с полным названием браузер
       показывает только тому, на что можно навести, поэтому группе события
       возвращаем: клик по ней всё равно всплывает до самого блока. */
    .node-text-lines .entity-label-group { pointer-events: auto; cursor: pointer; }
    .node-text-lines .entity-label-group,
    .node-text-lines .entity-label-desc {
        display: block; white-space: normal; word-break: break-word;
        color: var(--text); font-size: 1.2em; font-weight: 700;
    }
    .node-text-lines .entity-label-param { display: block; white-space: normal; word-break: break-word; }
    .node-text-lines .entity-label-tags { justify-content: center; }
    .map-node-loc { display: block; color: var(--dim); font-size: 9px; }
    .node-text-lines .map-node-cost-label { display: block; color: var(--accent); font-size: 10px; }
    .node-text-wrap .map-node-cost-label, .node-text-wrap .map-node-details-btn,
    .node-text-wrap .map-cost-fillin, .node-text-wrap input, .node-text-wrap button {
        pointer-events: auto;
    }
    .mc-table { width: auto; margin: 0 auto; border-collapse: collapse; }
    .mc-table td { padding: 0; white-space: nowrap; }
    .mc-table .mc-label { text-align: left; opacity: 0.85; }
    .mc-table .mc-int { text-align: right; padding-left: 6px; }
    .mc-table .mc-frac { text-align: left; }
    .mc-table .mc-raw { text-align: right; padding-left: 6px; }
    .mc-table .mc-icon { text-align: left; padding-left: 3px; width: 12px; }
    .mc-table .mc-total td { border-top: 1px solid var(--line-soft); font-weight: 700; padding-top: 2px; }
    .map-node-details-btn {
        background: transparent; border: 1px solid var(--line); color: var(--dim);
        border-radius: 4px; cursor: pointer; font-family: var(--mono);
    }
    .map-node-details-btn:hover { border-color: var(--accent); color: var(--text); }
    .mc-warn { color: var(--orange); }
    .mc-editable { cursor: pointer; border-bottom: 1px dotted currentColor; }
    .mc-editable:hover { color: var(--text); background: rgba(255,255,255,0.1); }
    .mc-override { color: var(--red) !important; }
    .mc-inline-input { width: 4.2em; font-size: 10px; padding: 0 2px; font-family: var(--mono); }
    .mc-inline-btns { display: block; margin-top: 2px; }
    .mc-inline-btn { font-size: 9px; padding: 0 4px; margin-right: 3px; cursor: pointer; }
    .map-node-recipe .node-text-wrap { color: var(--text); }
    .map-edge-label-bg { fill: var(--panel); stroke: var(--line); }
    .map-edge-label-manual { stroke: var(--orange); }
    /* Значки у нормы: жёлтый - нужна ваша правка, красный - факт выше нормы,
       бледная галочка - проверку замерами отключили вручную */
    .map-edge-remove { cursor: pointer; }
    .map-edge-remove circle { fill: var(--panel); stroke: var(--red); stroke-width: 1.2; }
    .map-edge-remove text { fill: var(--red); font-size: 10px; font-family: var(--mono); pointer-events: none; }
    .map-edge-remove:hover circle { fill: var(--red); }
    .map-edge-remove:hover text { fill: var(--panel); }
    /* Связь с побочным выходом: красная, чтобы отличать от основного потока.
       Прячется той же галочкой, что и боковые ветки - смотреть на брак нужно
       не всегда, а места он занимает много. */
    /* Побочный выход - роль, которую поставил человек, а не ошибка. Красным он спорил
       с настоящими пометками о поломках; пунктир и приглушённость говорят то же самое
       («не основной путь»), никого не пугая. */
    /* Пунктирные связи - того же цвета и той же плотности, что сплошные: их
       отличает рисунок штриха, а не бледность. Приглушение оставлено небольшим,
       только чтобы основной поток читался первым. */
    .map-edge-byproduct { stroke: var(--dim); stroke-dasharray: 7 5; opacity: 0.8; }
    /* Побочные связи гаснут, пока не включены тупики. Но возврат своих отходов -
       не тупик: узел и связь подчинены галочке обратных циклов, и гасить их второй
       галочкой значит показывать блок без видимых стрелок. Класс map-edge-defect
       карта на такие связи больше не вешает - по нему их и отличаем. */
    /* Гасим только связи к настоящим тупикам. Класс map-edge-defect карта вешает
       лишь тогда, когда позицию никто не берёт в дело; у побочного с потребителем
       его нет, и связь видна наравне с прочими. */
    svg:not(.show-defects) .map-edge-byproduct.map-edge-defect { opacity: 0.08; }
    /* Альтернативный вход - пунктиром и приглушённо, чтобы не путать его с
       основным путём. Показывается галочкой "Альтернативные пути". */
    .map-edge-altinput { stroke: var(--dim); stroke-dasharray: 5 4; opacity: 0.8; }
    /* Запасной маршрут: путь живой, просто пробовать его будут не первым. Пунктир
       длинный и редкий - линия читается как сплошная на расстоянии и как прерывистая
       вблизи, в отличие от побочного выхода (частый пунктир) и запасного входа
       (мелкий). Приглушать сильно нельзя: это рабочий путь, а не отход. */
    .map-edge-secondary { stroke: var(--dim); stroke-dasharray: 12 6; opacity: 0.85; }
    /* Разбор запасов: планировать через него нельзя вовсе. Точки вместо штрихов -
       линия есть, но она не про производство под заказ. */
    .map-edge-salvage-route { stroke: var(--orange); stroke-dasharray: 2 5; opacity: 0.75; }
    .map-edge-role { cursor: pointer; }
    .map-edge-role circle { fill: var(--panel); stroke: var(--dim); stroke-width: 1.2; }
    .map-edge-role text { fill: var(--dim); font-size: 10px; font-family: var(--mono); pointer-events: none; }
    /* Кружок «разбор запасов» - только у обычных выходов. Отдельным цветом от роли:
       это не роль, а способ появления работы, и путать их нельзя. Включённый
       заливаем, как и побочный, чтобы состояние читалось без наведения. */
    .map-edge-salvage { cursor: pointer; }
    /* Сплошной кружок, как у переключателя роли. Пунктирный и бледный терялся на
       светлом фоне: рядом три ярких значка, и четвёртый просто не находили. */
    .map-edge-salvage circle { fill: var(--panel); stroke: var(--dim); stroke-width: 1.2; }
    .map-edge-salvage text { fill: var(--dim); font-size: 10px; pointer-events: none; }
    .map-edge-salvage.is-on circle { fill: var(--orange); stroke: var(--orange); stroke-dasharray: none; }
    .map-edge-salvage.is-on text { fill: var(--panel); }
    /* Предпочтение задано - кружок сплошной, но не залитый: это не особый режим,
       а обычный путь, у которого просто указан порядок среди равных. */
    .map-edge-salvage.has-pref circle { stroke: var(--accent); stroke-dasharray: none; }
    .map-edge-salvage.has-pref text { fill: var(--accent); font-family: var(--mono); }
    .map-edge-salvage:hover circle { stroke: var(--accent); }
    .map-edge-role.is-byproduct circle { fill: var(--dim); }
    .map-edge-role.is-byproduct text { fill: var(--panel); }
    .map-edge-role:hover circle { stroke: var(--accent); }
    /* Кнопка локации на стрелке. Пустая - розовая, как и блоки без локации: один цвет
       на одну проблему, чтобы взгляд не искал два разных значения. */
    .map-edge-loc { cursor: pointer; }
    .map-edge-loc circle { fill: var(--panel); stroke: var(--dim); stroke-width: 1.2; }
    .map-edge-loc text { font-size: 9px; pointer-events: none; }
    .map-edge-loc.is-empty circle { fill: var(--pink-dim); stroke: var(--pink); }
    .map-edge-loc:hover circle { stroke: var(--accent); }
    .map-edge-role:hover text { fill: var(--accent); }
    /* Порты процесса: слева вход, справа выход. Появляются только в режиме
       редактирования - в обычном виде они бы только мешали читать карту. */
    /* touch-action: none - иначе на телефоне первое же движение пальцем с порта
       уходит браузеру на прокрутку, pointercancel убивает перетаскивание, и связь
       провести невозможно. Радиус попадания больше видимого кружка: пальцем в
       семь пикселей не попасть. */
    .map-port { cursor: crosshair; touch-action: none; }
    .map-port circle { fill: var(--panel); stroke: var(--accent); stroke-width: 1.2; }
    .map-port-hit { fill: transparent; stroke: none; }
    .map-port text { fill: var(--accent); font-size: 9px; font-family: var(--mono); pointer-events: none; }
    .map-port:hover circle { fill: var(--accent); }
    .map-port:hover text { fill: var(--panel); }
    .map-port-line { stroke: var(--accent); stroke-width: 1.5; stroke-dasharray: 4 3; }
    .map-lasso { fill: rgba(52,213,255,0.10); stroke: var(--accent); stroke-width: 1; stroke-dasharray: 4 3; pointer-events: none; }
    .map-node-droptarget > rect, .map-node-droptarget > polygon { stroke: var(--accent) !important; stroke-width: 2.5px !important; }
    .map-node-draft > rect { fill: var(--panel); stroke: var(--accent); stroke-dasharray: 5 3; }
    .map-undo-toast {
        position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 9998;
        display: flex; align-items: center; gap: 12px;
        background: var(--panel); border: 1px solid var(--line); border-radius: 6px;
        padding: 10px 14px; font-family: var(--mono); font-size: 12px; color: var(--text);
        box-shadow: 0 6px 24px rgba(0,0,0,0.4);
    }
    .map-undo-toast button {
        background: transparent; border: 1px solid var(--line); color: var(--accent);
        border-radius: 4px; padding: 4px 12px; cursor: pointer; font-family: var(--mono); font-size: 11px;
    }
    .map-undo-toast button:hover { border-color: var(--accent); }
    .map-undo-hint { color: var(--dim); font-size: 10px; }
    .map-norm-warn { color: #e6c62e; margin-left: 4px; cursor: pointer; font-size: 0.8em; }
    .map-norm-alert { color: var(--red); margin-left: 4px; cursor: pointer; font-size: 0.9em; font-weight: bold; }
    .map-qty-dialog-backdrop {
        position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,0.45);
        display: flex; align-items: center; justify-content: center;
    }
    .map-qty-dialog {
        position: relative; background: var(--panel); border: 1px solid var(--line);
        border-radius: 8px; padding: 18px 20px 14px; min-width: 340px; max-width: 470px;
        font-family: var(--mono); font-size: 12px; color: var(--text);
        box-shadow: 0 10px 40px rgba(0,0,0,0.5);
    }
    .map-qty-close {
        position: absolute; top: 6px; right: 8px; background: transparent; border: none;
        color: var(--dim); cursor: pointer; font-size: 14px; padding: 2px 4px;
    }
    .map-qty-close:hover { color: var(--text); }
    .map-qty-title { margin-right: 18px; line-height: 1.5; }
    .map-qty-title div + div { margin-top: 2px; }
    .map-qty-title-gap { margin-bottom: 14px; }
    .map-qty-alert {
        border-left: 2px solid var(--red); background: rgba(220,80,80,0.10);
        padding: 7px 10px; margin: 0 18px 12px 0; border-radius: 0 4px 4px 0; line-height: 1.45;
    }
    .map-qty-tabs { display: flex; flex-direction: column; gap: 2px; margin: 0 0 10px; }
    .map-qty-tab {
        background: transparent; border: none; border-left: 2px solid transparent;
        color: var(--dim); padding: 6px 10px; cursor: pointer; text-align: left;
        font-family: var(--mono); font-size: 11px; border-radius: 0 4px 4px 0;
    }
    .map-qty-tab:hover { color: var(--text); background: rgba(127,127,127,0.10); }
    .map-qty-tab.active { color: var(--accent); border-left-color: var(--accent); background: rgba(127,127,127,0.08); }
    .map-qty-pane[hidden] { display: none; }
    .map-qty-hint { color: var(--dim); font-size: 11px; margin-top: -2px; }
    .map-qty-check { display: flex; align-items: center; gap: 6px; color: var(--dim); cursor: pointer; font-size: 11px; }
    .map-qty-check:hover { color: var(--text); }
    .map-qty-check input { cursor: pointer; }
    .map-qty-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
    .map-qty-label { width: 128px; color: var(--dim); flex: none; }
    .map-qty-value { min-width: 76px; }
    .map-qty-empty { color: var(--dim); font-style: italic; }
    .map-qty-input { width: 76px; font-family: var(--mono); font-size: 12px; padding: 3px 5px; }
    .map-qty-unit { color: var(--dim); }
    .map-qty-btn {
        margin-left: auto; background: transparent; border: 1px solid var(--line); color: var(--text);
        border-radius: 4px; padding: 3px 12px; cursor: pointer; font-family: var(--mono); font-size: 11px;
    }
    .map-qty-btn:hover { border-color: var(--accent); color: var(--accent); }
    .map-edge-label { cursor: pointer; }
    .map-edge-label-text { fill: var(--dim); font-size: 11px; font-family: var(--mono); pointer-events: none; }
    .map-edge-label:hover .map-edge-label-bg { stroke: var(--accent); }
    .map-edge-label:hover .map-edge-label-text { fill: var(--accent); }
    .node-item .node-text-wrap { color: var(--text); opacity: 0.9; }

/* Блок, у которого хоть одна строка рецепта заведена без локации. Розовая заливка -
   это про незаполненные данные, а не про ошибку расчёта: остаток по такой строке
   считается сразу по всем складам, и задача может проситься туда, где материала нет.
   Правило идёт последним, чтобы перебивать заливку категорий. */
/* Локация принадлежит СВЯЗИ, а не блоку: у процесса шесть строк, и каждая может
   брать материал со своего склада. Красим только саму стрелку - обводка на блоке
   говорила лишь "где-то тут не заполнено" и висела на пол-карты, не показывая где. */
.map-edge-noloc { stroke: var(--pink) !important; stroke-width: 2 !important; }
/* Счётчик строк без места - в одной строке с галочками панели. Красный, а не серый:
   это не настройка вида, а поломка данных, из-за которой рецепт выпадает из расчёта
   работ целиком. Прячется сам, когда таких строк не осталось. */
.map-noloc-warn{
  display:inline-flex; align-items:center; gap:6px;
  font-size:11px; color:var(--red); white-space:nowrap;
}
.map-noloc-warn.hidden{ display:none; }
.map-noloc-warn b{ font-family:var(--mono); }
/* Варианты в окне «как получают продукт». Радиокнопка с пояснением в две-три
   строки: без пояснения разницу между «разбором запасов» и «предпочтением» по одним
   названиям не понять, а ошибка тут молча отрезает товар от планирования. */
.map-route-opt{
  display:flex; gap:8px; align-items:flex-start;
  padding:8px 0; border-bottom:1px solid var(--line-soft);
  font-size:11px; line-height:1.5; color:var(--dim); cursor:pointer;
}
.map-route-opt:last-of-type{ border-bottom:none; }
.map-route-opt b{ color:var(--text); font-size:12px; }
.map-route-opt input[type=radio]{ margin-top:3px; flex:0 0 auto; }
.map-route-opt input[type=number]{ display:block; margin-top:6px; width:90px; }

/* Обязательное поле в карточке блока. Помечаем словом, а не звёздочкой: звёздочку
   рядом с подписью читают как сноску и ищут пояснение внизу формы, которого нет. */
/* Включённая кнопка в ряду действий - например, ручная срочность заказа. Заливка,
   а не рамка: состояние должно читаться в свёрнутой строке краем глаза, без
   наведения и без раскрытия карточки. */
.tasks-card-act.is-on{ background:var(--red-dim); border-color:var(--red); }

.map-field-required{
  margin-left:6px; font-size:9px; letter-spacing:0.5px; text-transform:uppercase;
  color:var(--red); border:1px solid var(--red); border-radius:3px; padding:0 4px;
}
/* Предупреждение под незаполненным обязательным полем: то же место, что у обычной
   пояснительной строки формы, но красным - это не подсказка, а несделанное дело. */
.map-newline-note-warn{ color:var(--red); }

/* Узел с непроставленным местом - у самого процесса или у любой его строки. Розовым,
   как и стрелки без места: это одна и та же поломка, и глаз должен связывать их
   между собой. Рамка, а не заливка: внутри узла уже есть свои цвета состояния. */
/* Рамка побочного блока повторяет штрих связи, которая к нему ведёт (7 5, как у
   .map-edge-byproduct): один смысл - один вид, и по рамке сразу ясно, каким путём
   узел связан с основным потоком.

   Правило намеренно перекрывает оранжевую пометку о нехватке остатка. «Не хватает»
   про побочное бессмысленно: добрать его нельзя ни закупкой, ни запуском процесса,
   оно получается попутно. Я трижды пробовал не ставить эту пометку в расчёте и
   трижды промахивался мимо нужной ветки - здесь же перекрытие работает независимо
   от того, откуда взялся класс.

   Настоящие поломки исключены и перекрывают рамку по-прежнему: розовая «нет места»
   и красная «взять неоткуда» - это дыры в данных, и молчать о них нельзя. */
svg .map-node-byproduct:not(.map-node-noloc):not(.map-node-noproducer) > rect,
svg .map-node-byproduct:not(.map-node-noloc):not(.map-node-noproducer) > polygon{
  stroke: var(--map-dash) !important;
  /* Толще сплошных намеренно. Пунктир при равной толщине и равном цвете читается
     светлее: глаз усредняет штрихи с просветами, и рамка выглядит выцветшей, хотя
     цвет тот же. Прибавка возвращает ей тот же вес, что у соседних блоков. */
  stroke-width: 1.6px !important;
  stroke-dasharray: 7 5 !important;
}

/* Ветка вне планирования: через неё нельзя построить цепочку под заказ, и всё, что
   её кормит, существует ради неё одной. Пунктир тот же, что у побочного блока, -
   смысл один: это не основной путь. Поломки по-прежнему главнее и рамку перекрывают. */
svg .map-node-unplanned:not(.map-node-noloc):not(.map-node-noproducer) > rect,
svg .map-node-unplanned:not(.map-node-noloc):not(.map-node-noproducer) > polygon{
  stroke: var(--map-dash) !important;
  stroke-width: 1.6px !important;
  stroke-dasharray: 7 5 !important;
}

.map-node-noloc rect{ stroke: var(--pink) !important; stroke-width: 2 !important; }

/* Пояснение к цветам - прямо в панели карты. Без него цвет остаётся загадкой: он
   виден постоянно, а расшифровка живёт в голове того, кто это писал. */
.map-legend{ display:inline-flex; align-items:center; gap:12px; font-size:11px; color:var(--dim); }
.map-legend span{ display:inline-flex; align-items:center; gap:5px; white-space:nowrap; }
.map-legend i{ width:14px; height:0; border-top:2px solid currentColor; display:inline-block; }
.map-legend .lg-nosrc{ color:var(--red); }
.map-legend .lg-noloc{ color:var(--pink); }
.map-legend .lg-stock{ color:var(--orange); }
/* Связь чернового блока: настоящая строка рецепта, но блок ещё не вошёл в подграф
   фокуса - показываем её приглушённо, как и сам черновик. */
.map-edge-draft { opacity: 0.75; }

/* Галочка "Можно по частям" в карточке заказа - мелкая служебная строка под сроком,
   она не должна спорить с количеством и датой. */
/* Заказ с дырами в составе: зачёркнут и не участвует в расчёте. Приглушаем весь
   ряд, но кнопки оставляем живыми - количество и срок менять можно, это часто и
   есть способ обойти проблему. */
.tasks-order-broken .tasks-order-title,
.tasks-order-broken .tasks-order-controls{ text-decoration:line-through; opacity:0.6; }
.tasks-order-problems{
  margin-top:6px; padding:6px 8px; border-radius:4px; font-size:11px; line-height:1.45;
  background:rgba(255,84,112,0.07); border:1px solid var(--red-dim); color:var(--text);
}
.tasks-order-problems b{ color:var(--red); }
.tasks-order-problems ul{ margin:4px 0 6px; padding-left:16px; }
.tasks-order-problems li{ margin-bottom:2px; }
.tasks-order-problems-more{ color:var(--dim); margin-bottom:6px; }
/* Замечания по цепочке заказа: столько же, сколько показала бы панель проблем, если
   встать на этот продукт фокусом. Не ошибка - считать они не мешают, - поэтому
   только значок с числом, а сам перечень в подсказке. */
.tasks-order-warn{
  margin-left:6px; color:var(--orange); font-size:11px; white-space:nowrap; cursor:help;
}
/* Переключатель режима расчёта. Два состояния подписаны словами, а не галочкой:
   «Всё сразу» - обычный режим, «Можно по частям» - послабление, поэтому включённое
   состояние подсвечено акцентом, а выключенное выглядит нейтрально. */
.tasks-order-partial{
  align-self:flex-start; margin-top:4px; padding:3px 9px;
  background:var(--panel); border:1px solid var(--line); border-radius:4px;
  font-family:inherit; font-size:10px; letter-spacing:0.5px; color:var(--dim);
  cursor:pointer; user-select:none; white-space:nowrap;
}
.tasks-order-partial:hover{ color:var(--text); border-color:var(--accent); }
.tasks-order-partial.on{ color:var(--accent); border-color:var(--accent); }
.tasks-order-partial:disabled{ cursor:default; }

/* Закупка, временно отмеченная выполненной: в списке "скоро понадобится" она стоит
   по другой причине, чем остальные, - помечаем, чтобы не путали с расчётным остатком
   у станка. */
.tasks-wip-assumed{ opacity: 0.75; }
.tasks-wip-assumed .tasks-wip-recipe{ font-style: italic; }

/* Галочка снятия отметки прямо в строке списка - иначе отметку по исчезнувшей задаче
   можно было убрать только сбросом всех сразу. */
.tasks-wip-uncheck{ display:inline-flex; align-items:center; margin-right:5px; cursor:pointer; }
.tasks-wip-uncheck input{ margin:0; cursor:pointer; }

/* ---------- ПРОЕКТЫ И КОНТАКТЫ ----------
   Список с поиском и карточка. Ширина ограничена: длинные строки на широком
   мониторе читать тяжело, а на телефоне всё в одну колонку. */
#projects-wrap, #contacts-wrap{ gap:14px; max-width:980px; width:100%; margin:0 auto; box-sizing:border-box; }
.prj-top{ display:flex; flex-direction:column; gap:10px; }
.prj-top .tb-input, .prj-card .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; }
.prj-chips{ display:flex; flex-wrap:wrap; gap:6px; }
.prj-new{ display:flex; gap:8px; }
.prj-new .tb-input{ flex:1; min-width:0; }
.prj-new .tb-btn{ flex-shrink:0; }
.prj-list{ display:flex; flex-direction:column; border-top:1px solid var(--line-soft); }
.prj-row{
  display:flex; align-items:center; gap:12px; width:100%; text-align:left;
  background:none; border:none; border-bottom:1px solid var(--line-soft);
  color:var(--text); font-family:inherit; padding:10px 4px; cursor:pointer;
}
.prj-row:hover{ background:var(--panel2); }
.prj-row.closed{ opacity:0.55; }
.prj-row-main{ flex:1; min-width:0; display:flex; flex-direction:column; gap:3px; }
.prj-row-name{ font-size:13px; overflow-wrap:anywhere; }
.prj-row-sub{ font-size:11px; color:var(--dim); overflow-wrap:anywhere; }
/* В списке проектов каждая строка - ровно одна, с «…»: строки одной высоты, длинное
   описание не раздувает список. Целиком - в подсказке при наведении и в карточке. */
.prj-row .prj-line{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; overflow-wrap:normal; }
.prj-row-desc{ font-size:12px; color:var(--dim); color:color-mix(in srgb, var(--text) 72%, var(--bg)); }
.prj-row .prj-row-sub{ font-size:10.5px; color:var(--dim); }
.prj-row-side{ flex-shrink:0; display:flex; flex-direction:column; align-items:flex-end; gap:3px; }
.prj-row-sum{ font-size:11px; color:var(--dim); white-space:nowrap; }
/* Раскрытая строка: название целиком, а описание и мелкая строка уходят в
   подробности под ней - строка и подробности читаются одним блоком. */
.prj-row.open{ background:var(--panel2); border-bottom-color:transparent; }
.prj-row.open .prj-row-name{ white-space:normal; overflow:visible; overflow-wrap:anywhere; }
.prj-row.open .prj-row-desc, .prj-row.open .prj-row-sub{ display:none; }
.prj-peek{
  display:flex; flex-direction:column; gap:8px; padding:0 10px 12px 36px;
  background:var(--panel2); border-bottom:1px solid var(--line-soft); font-size:12px; color:var(--text);
}
.prj-peek-row{ display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 8px; }
.prj-peek-label, .prj-peek-title{ font-size:10px; letter-spacing:0.5px; color:var(--dim); text-transform:uppercase; }
.prj-peek-label{ flex-shrink:0; }
.prj-peek-val{ min-width:0; overflow-wrap:anywhere; }
.prj-peek-block{ display:flex; flex-direction:column; gap:4px; }
/* текст - как записан, с переносами строк */
.prj-peek-text{ white-space:pre-wrap; overflow-wrap:anywhere; line-height:1.45; }
.prj-peek-comment{ padding-left:8px; border-left:2px solid var(--line); }
.prj-peek-photos{ display:flex; flex-wrap:wrap; gap:6px; }
.prj-peek .prj-thumb{ width:72px; height:72px; }
.prj-peek-kids{ overflow-wrap:anywhere; }
.prj-peek-foot{ display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-end; gap:10px; }
.prj-peek-foot .prj-muted{ margin-right:auto; }
/* вид «Сейчас»: путь мелко над названием, справа - когда было последнее событие */
.prj-views .tb-btn{ flex:1; }
.prj-now-row{ padding-left:10px; }
.prj-now-path{ font-size:10.5px; color:var(--dim); }
.prj-now-when{ font-size:11px; color:var(--dim); white-space:nowrap; }
/* статус в строке «Сейчас» нажимается - окно смены статуса */
.prj-now-row .prj-status{ cursor:pointer; }
.prj-status-list .map-picker-option{ justify-content:flex-start; }
.prj-status-confirm{ margin-top:10px; display:flex; flex-direction:column; gap:4px; font-size:12px; overflow-wrap:anywhere; }
.prj-status-change{ font-size:14px; }
/* Окно выбора (prjPick): имя и путь в две строки, галочка при выборе нескольких */
.prj-pick .prj-pick-name{ flex:1; min-width:0; display:flex; flex-direction:column; gap:1px; text-align:left; }
.prj-pick .prj-pick-name .prj-muted{ font-size:10.5px; }
.prj-pick-check{ flex:none; width:16px; color:var(--accent); }
/* «＋ Создать «текст»» под списком выбора (§86): на всю ширину, список прокручивается над ней */
.prj-pick-create{ display:block; width:100%; margin-top:8px; text-align:left; white-space:normal; overflow-wrap:anywhere; text-transform:none; }
/* общее окно «Новое: <категория>» для справочников с одним названием */
.prj-dict{ display:flex; flex-direction:column; gap:10px; }
/* Окно «Новый проект»: поля-кнопки, файлы */
.prj-new-media{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.prj-new-media .tb-btn{ font-size:16px; padding:4px 10px; }
.prj-new-files{ display:flex; flex-wrap:wrap; gap:6px; }
.prj-new-files:empty{ display:none; }
.prj-new-file{ position:relative; display:inline-flex; align-items:center; gap:4px; max-width:100%; border:1px solid var(--line); padding:2px 4px; font-size:12px; }
.prj-new-file img{ width:44px; height:44px; object-fit:cover; display:block; }
.prj-new-field{ display:flex; flex-direction:column; gap:3px; }
.prj-new-label{ font-size:12px; color:var(--dim); }
.prj-new-val{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; min-width:0; }
.prj-new-pick{ max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; text-transform:none; }
.prj-new-from{ font-size:11px; }
/* Подставлено само: один вид для окна «Новый проект» и формы «Времени» - жёлтая рамка и ⚠.
   !important - чтобы пересилить рамку чипов вкладки «Время» (они заданы через #tab-time). */
.prj-auto{ border-color:var(--auto) !important; box-shadow:0 0 0 1px var(--auto); }
.prj-new-val.prj-auto{ border:1px solid var(--auto); background:var(--auto-bg); padding:2px 4px; }
.prj-auto-x{ color:var(--auto); cursor:pointer; font-size:14px; line-height:1; padding:0 2px; font-weight:700; }
.prj-auto-x:hover, .prj-auto-x:focus-visible{ outline:1px solid var(--auto); }
.prj-new-chip{ display:inline-flex; align-items:center; gap:4px; border:1px solid var(--accent-dim); color:var(--accent); padding:2px 6px; font-size:12px; }
.prj-new-chip-x{ background:none; border:none; color:var(--dim); cursor:pointer; padding:0 2px; font:inherit; }
/* окно длинное - «Создать» всегда видна внизу, прокручиваются поля */
.prj-new-dialog .prj-dialog-btns{ position:sticky; bottom:-16px; background:var(--panel); padding:8px 0; margin-bottom:-8px; z-index:1; }
/* Окно проекта (§34) - вместо карточки, поверх списка. Шапка с «Закрыть» прилипает к верху. */
.prj-card-dialog{ width:min(760px, 100%); box-sizing:border-box; padding-top:0; }
.prj-card-dialog .prj-card-head{ position:sticky; top:-16px; z-index:2; background:var(--panel); padding:12px 0 8px; }
.prm-group.empty .prm-row.prm-none{ font-size:12px; }
.prm-btn.prm-add-one{ margin-left:6px; vertical-align:middle; }
.prm-btn[data-act="edit"]:hover{ color:var(--accent); border-color:var(--accent-dim); }
.prj-more{ border-top:1px solid var(--line); padding-top:8px; }
.prj-more > summary{ cursor:pointer; font-size:11px; letter-spacing:0.5px; text-transform:uppercase; color:var(--dim); padding:4px 0; }
.prj-more.warn > summary{ color:var(--red); }
.prj-more[open] > summary{ margin-bottom:8px; }
.prj-ask{ width:min(420px, 100%); }
.prj-ask-text{ font-size:14px; line-height:1.4; overflow-wrap:anywhere; }
.prj-now-totals{ font-size:12px; color:var(--accent); }
.prj-now-ev{ display:flex; gap:10px; align-items:baseline; padding:2px 0; }
.prj-now-ev-when{ flex-shrink:0; width:92px; font-size:11px; color:var(--dim); white-space:nowrap; }
.prj-now-ev-what{ min-width:0; overflow-wrap:anywhere; }
.prj-status{
  font-size:10px; letter-spacing:0.5px; text-transform:uppercase; white-space:nowrap;
  padding:2px 6px; border:1px solid var(--line); color:var(--dim);
}
.prj-status.s-5105{ color:var(--accent); border-color:var(--accent-dim); }
.prj-status.s-5333{ color:var(--orange); border-color:var(--orange-dim); }
.prj-status.s-541{ color:var(--green); border-color:var(--green-dim); }
.prj-status.s-5104{ color:var(--green); border-color:var(--green-dim); }
.prj-status.s-5920{ color:var(--purple); border-color:var(--purple-dim); }
.prj-status.s-5106, .prj-status.s-9572{ color:var(--dim2); }
.prj-status.s-zp{ color:var(--pink); border-color:var(--pink-dim); }
.prj-unnamed{ color:var(--dim); font-style:italic; }
.prj-tree-mark{ color:var(--dim2); flex-shrink:0; }
.prj-overdue{ font-size:10px; color:var(--red); text-transform:uppercase; letter-spacing:0.5px; }
.prj-more{ padding:12px 4px; }
.prj-muted{ font-size:11px; color:var(--dim); }

.prj-card{ display:flex; flex-direction:column; gap:12px; }
.prj-card-head{ display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; }
.prj-title-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; }
.prj-title{ font-size:18px; line-height:1.3; overflow-wrap:anywhere; }
.prj-section{ display:flex; flex-direction:column; gap:8px; padding-top:12px; border-top:1px solid var(--line-soft); }
.prj-section-title{ font-size:11px; letter-spacing:2px; color:var(--dim); text-transform:uppercase; }
.prj-section > .tb-btn{ align-self:flex-start; }
/* Заголовок блока с действиями справа - мелкими словами, без рамок: кнопки не
   спорят с содержимым. */
.prj-section-head{ display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; }
.prj-section-head .prj-section-title{ margin-right:auto; }
.prj-head-act{ background:none; border:none; padding:2px 0; font-family:inherit; font-size:11px; color:var(--accent); cursor:pointer; }
.prj-head-act:hover{ text-decoration:underline; text-underline-offset:3px; }
.prj-textarea{ resize:vertical; min-height:56px; }
.prj-thumb{
  width:96px; height:96px; display:flex; align-items:center; justify-content:center; overflow:hidden;
  background:var(--panel2); border:1px solid var(--line); color:var(--dim); font-size:11px; text-decoration:none;
}
.prj-thumb img, .prj-thumb video{ width:100%; height:100%; object-fit:cover; display:block; }
button.prj-thumb{ position:relative; padding:0; font-family:inherit; cursor:zoom-in; }
.prj-thumb[data-kind="video"], .prj-thumb[data-kind="file"]{ cursor:pointer; }
.prj-play{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-size:26px; color:#fff; text-shadow:0 1px 6px rgba(0,0,0,0.8); pointer-events:none;
}
.prj-thumb-text{ font-size:10px; line-height:1.3; padding:4px; text-align:center; overflow-wrap:anywhere; }
/* Миниатюры в строках «Сейчас»: полосой под названием (на узком экране переносится), лишнее -
   «+N», документы - 📄 N.
   Плитка - не кнопка (строка сама кнопка), поэтому курсор и размер - здесь. */
.prj-row-media{ display:flex; align-items:center; gap:4px; margin-top:6px; flex-wrap:wrap; max-width:100%; }
.prj-row .prj-row-thumb{ width:56px; height:56px; flex:none; position:relative; cursor:zoom-in; }
.prj-row .prj-row-thumb .prj-play{ font-size:18px; }
.prj-row-more, .prj-row-docs{ flex:none; font-size:11px; color:var(--dim); padding:0 4px; white-space:nowrap; }
.prj-row-docs[hidden]{ display:none; }
/* Голосовые: кнопка ▶ с длительностью играет на месте (projects.js, prjVoiceHtml); в строке их до 3, дальше «+N».
   span role=button - строка сама кнопка. */
.prj-voice{
  display:inline-flex; align-items:center; gap:5px; box-sizing:border-box; min-height:30px; padding:3px 11px; flex:none;
  border:1px solid var(--line); border-radius:15px; background:var(--panel2); color:var(--text);
  font:inherit; font-size:12px; line-height:1; text-decoration:none; cursor:pointer; user-select:none; -webkit-user-select:none;
}
.prj-voice:hover, .prj-voice:focus-visible{ border-color:var(--accent); outline:none; }
.prj-voice.playing{ border-color:var(--accent); color:var(--accent); }
.prj-voice.bad{ color:var(--dim); text-decoration:underline; text-underline-offset:3px; }
.prj-voice-dur{ font-variant-numeric:tabular-nums; color:var(--dim); }
.prj-voice.playing .prj-voice-dur{ color:inherit; }
.prj-row-voices{ display:inline-flex; flex-wrap:wrap; align-items:center; gap:4px; }
.prj-voice-more{ flex:none; font-size:11px; color:var(--dim); padding:0 4px; white-space:nowrap; }
.prj-thumb[data-kind="audio"]{ cursor:pointer; }
/* Просмотр фото и видео поверх страницы. Масштаб страницы здесь снимаем (как у --ui-zoom выше): пальцы, колесо и
   сдвиг считаются в настоящих пикселях экрана. Вверху ✕, посередине файл (зум и сдвиг - transform у картинки),
   ниже строка состояния, лента миниатюр и кнопки. */
.prj-viewer{
  position:fixed; inset:0; z-index:10001; background:rgba(0,0,0,0.95); zoom:calc(1 / var(--ui-zoom));
  display:flex; flex-direction:column; align-items:stretch; gap:8px; padding:10px 10px calc(10px + env(safe-area-inset-bottom));
  box-sizing:border-box; overflow:hidden; font-size:14px;
}
.prj-viewer-x{ position:absolute; top:calc(8px + env(safe-area-inset-top)); right:10px; z-index:3; width:40px; height:40px; padding:0; font-size:18px; background:rgba(0,0,0,0.55); }
.prj-viewer-body{ position:relative; flex:1; min-height:0; width:100%; display:flex; align-items:center; justify-content:center; overflow:hidden; touch-action:none; }
.prj-viewer-body img, .prj-viewer-body video{ max-width:100%; max-height:100%; object-fit:contain; background:#000; }
.prj-viewer-body > img{ transform-origin:50% 50%; will-change:transform; user-select:none; -webkit-user-select:none; -webkit-user-drag:none; }
.prj-viewer-body.zoomed{ cursor:grab; }
.prj-viewer-body.zoomed.dragging{ cursor:grabbing; }
.prj-viewer-note{ color:#dbe6ef; font-size:14px; text-align:center; line-height:1.6; }
.prj-live-wrap{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; background:#000; z-index:2; }
.prj-live-wrap video{ width:100%; height:100%; }
.prj-live-x{ position:absolute; top:6px; left:6px; width:40px; height:40px; padding:0; font-size:18px; background:rgba(0,0,0,0.6); }
.prj-viewer-status{ min-height:18px; font-size:12.5px; line-height:1.4; color:#dbe6ef; text-align:center; flex:none; }
.prj-viewer-status:empty{ min-height:0; }
.prj-viewer-strip{ display:flex; gap:6px; overflow-x:auto; overflow-y:hidden; flex:none; padding:3px 2px; -webkit-overflow-scrolling:touch; scrollbar-width:thin; }
.prj-vt{
  position:relative; flex:none; width:60px; height:60px; box-sizing:border-box; display:flex; align-items:center; justify-content:center;
  border:2px solid transparent; background:#10161c; color:#dbe6ef; font-size:22px; cursor:pointer; overflow:hidden; opacity:.75;
}
.prj-vt:first-child{ margin-left:auto; }
.prj-vt:last-child{ margin-right:auto; }
.prj-vt.cur{ border-color:var(--accent); opacity:1; }
.prj-vt img{ width:100%; height:100%; object-fit:cover; display:block; }
.prj-vt-chk{
  display:none; position:absolute; top:2px; right:2px; width:24px; height:24px; box-sizing:border-box; border-radius:50%;
  border:2px solid #fff; background:rgba(0,0,0,0.5); color:#fff; font-size:15px; line-height:20px; text-align:center; align-items:center; justify-content:center;
}
.prj-viewer.selecting .prj-vt-chk{ display:flex; }
.prj-vt-chk.on{ background:var(--accent); border-color:var(--accent); color:#04222c; }
.prj-vt-chk.on::before{ content:"✓"; font-weight:700; }
.prj-viewer-bar{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:8px; flex:none; }
.prj-viewer-bar .tb-btn{ text-decoration:none; font-size:14px; padding:8px 12px; }
.prj-viewer-bar .tb-btn.on{ border-color:var(--accent); color:var(--accent); }
.prj-viewer-orig{ font-size:13px; padding:8px 6px; color:var(--accent); font-weight:600; white-space:nowrap; }
.prj-viewer-nopv b{ font-size:20px; }
.prj-viewer-nopv .tb-btn{ margin-top:10px; }
.prj-viewer-main{ font-size:14px; padding:8px 12px; color:var(--accent); font-weight:600; white-space:nowrap; }
.prj-viewer-bar .tb-btn:disabled{ opacity:.45; }
.prj-viewer-sel{ display:contents; }
.prj-viewer-pos{ color:#dbe6ef; font-size:13px; min-width:48px; text-align:center; }
.prj-viewer-cap{ flex:1 1 100%; text-align:center; color:#dbe6ef; font-size:13px; line-height:1.35; overflow-wrap:anywhere; padding:0 8px; }
@media (max-width:640px){
  .prj-viewer-bar{ gap:6px; }
  .prj-viewer-bar .tb-btn{ font-size:13px; padding:8px 9px; letter-spacing:0; }
  .prj-viewer-pos{ min-width:40px; }
}
.prj-quick-btns{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.prj-quick-file{ cursor:pointer; }
.prj-field{ display:flex; gap:8px; }
.prj-field select{ flex:1; min-width:0; }
.prj-field .tb-btn{ flex-shrink:0; min-width:64px; }
.prj-row-field{ font-size:11px; color:var(--orange); overflow-wrap:anywhere; }

/* Все параметры объекта: имя шаблона из базы, под ним значения. */
.prm-list{ display:flex; flex-direction:column; }
.prm-group{ padding:7px 0; border-bottom:1px solid var(--line-soft); display:flex; flex-direction:column; gap:4px; }
.prm-name{ font-size:10px; letter-spacing:0.5px; color:var(--dim); text-transform:uppercase; }
.prm-id{ font-size:10px; color:var(--dim2); text-transform:none; letter-spacing:0; }
.prm-count{ font-size:10px; color:var(--orange); text-transform:none; letter-spacing:0; }
.prm-row{ display:flex; align-items:flex-start; gap:8px; }
.prm-val{ flex:1; min-width:0; font-size:13px; line-height:1.45; white-space:pre-wrap; overflow-wrap:anywhere; padding:3px 0; }
.prm-val.editable{ cursor:pointer; }
.prm-val.editable:hover{ color:var(--accent); }
.prm-btn{
  flex-shrink:0; width:30px; height:30px; padding:0; background:none; border:1px solid transparent;
  color:var(--dim2); font-family:inherit; font-size:16px; line-height:1; cursor:pointer;
}
.prm-btn:hover{ color:var(--red); border-color:var(--red-dim); }
.prm-link{
  background:none; border:none; padding:0; font:inherit; color:var(--accent); cursor:pointer;
  text-decoration:underline; text-decoration-color:var(--accent-dim); text-underline-offset:3px; text-align:left;
}
.prm-warn{ font-size:11px; color:var(--orange); }
/* Альбом - плиткой, а не столбиком: фото бывает десяток. */
.prm-group.media{ flex-direction:row; flex-wrap:wrap; gap:8px; }
.prm-group.media .prm-name{ width:100%; }
.prm-group.media .prm-row{ gap:2px; }
.prm-group.media .prm-val{ flex:none; padding:0; }
.prm-row.editing{ display:block; }
.prm-edit{ display:flex; flex-direction:column; gap:8px; padding:4px 0; }
.prm-edit .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; }
.prm-edit-btns{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.prm-add{ display:flex; flex-direction:column; gap:8px; padding-top:10px; }
.prm-add > .tb-btn{ align-self:flex-start; }
.prm-add-panel{ display:flex; flex-direction:column; gap:6px; }
.prm-add-panel .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; }
.prm-add-list{ display:flex; flex-direction:column; max-height:320px; overflow:auto; border:1px solid var(--line-soft); }
.prm-pick{
  text-align:left; background:none; border:none; border-bottom:1px solid var(--line-soft);
  color:var(--text); font-family:inherit; font-size:12px; padding:9px 10px; cursor:pointer;
}
.prm-pick:hover{ background:var(--panel2); color:var(--accent); }
/* Основное / дополнительное название и кнопка «основным». */
.prm-tag{ font-size:9px; letter-spacing:0.5px; text-transform:uppercase; color:var(--dim2); border:1px solid var(--line); padding:1px 4px; margin-right:4px; vertical-align:middle; }
.prm-btn.prm-btn-text{ width:auto; padding:0 6px; font-size:10px; letter-spacing:0.5px; text-transform:uppercase; }
.prm-btn.prm-btn-text:hover{ color:var(--accent); border-color:var(--accent-dim); }
.prm-ref{ display:flex; flex-wrap:wrap; align-items:baseline; gap:6px; font-size:12px; padding:4px 2px; border-bottom:1px solid var(--line-soft); }

/* Подсказки: в какой вид привести. Только текст и кнопки - решает человек. */
.prj-hints{ display:flex; flex-direction:column; gap:8px; padding:10px 12px; border:1px solid var(--orange-dim); background:rgba(255,182,72,0.05); }
.prj-hint{ font-size:12px; line-height:1.45; display:flex; flex-direction:column; gap:6px; }
.prj-hint + .prj-hint{ padding-top:8px; border-top:1px solid var(--line-soft); }
.prj-hint-btns{ display:flex; flex-wrap:wrap; gap:6px; }
/* в кнопках подсказок - названия проектов: верхний регистр их искажал бы */
.prj-hint-btns .tb-btn{ text-align:left; text-transform:none; letter-spacing:0; font-size:12px; }
/* пустой Заказчик/Исполнитель у части дела: рекомендация родительского - красным */
.prj-hint-warn{ color:var(--red); }

/* «Сейчас»: фильтры по Заказчику и Исполнителю. В кнопке - имя контакта, без верхнего регистра. */
.prj-sides .tb-btn{ text-transform:none; letter-spacing:0; max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.prj-side-on{ display:inline-flex; min-width:0; max-width:100%; }
.prj-side-on .tb-btn:first-child{ min-width:0; border-top-right-radius:0; border-bottom-right-radius:0; }
.prj-side-on .prj-side-x{ flex:none; border-left:none; border-top-left-radius:0; border-bottom-left-radius:0; }
.prj-side-opt{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; width:100%; text-align:left;
  background:transparent; border:none; color:var(--text); font-family:inherit; font-size:inherit; }
.prj-side-opt.active{ color:var(--accent); font-weight:700; }
.prj-side-opt .prj-line{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.prj-side-note{ padding:4px 2px 8px; }
.prj-side-empty{ padding:8px; }

/* Родитель и подпроекты: выбор через поиск. */
.prj-parent{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; font-size:13px; }
.prj-picker{ display:flex; flex-direction:column; gap:6px; }
.prj-picker .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; }
.prj-pick-list{ display:flex; flex-direction:column; max-height:360px; overflow:auto; }
.prj-pick-list:empty{ display:none; }
.prj-pick-row{
  display:flex; flex-direction:column; gap:2px; text-align:left; background:none; border:none;
  border-bottom:1px solid var(--line-soft); color:var(--text); font-family:inherit; font-size:13px; padding:9px 6px; cursor:pointer;
}
/* только с мышью: на телефоне :hover «залипает» на строке, куда пришёлся тап */
@media (hover: hover){ .prj-pick-row:hover{ background-color:var(--panel2); color:var(--accent); } }
.prj-pick-row:disabled{ opacity:0.5; cursor:default; }
.prj-kid{ display:flex; align-items:center; gap:4px; }
.prj-kid .prj-row{ flex:1; min-width:0; }

/* Окно «новый проект / контакт» (кнопка «+» в нижней плашке). */
/* Ширина - в процентах от фона окна, а не в vw: vw про общий zoom не знает. */
.prj-dialog{ width:min(720px, 100%); box-sizing:border-box; }
/* Окно выбора проекта - почти во весь экран: дереву нужно место. Высота делится
   на --ui-zoom по той же причине, что и у #dashboard; 32px - отступы фона. */
.prj-dialog-tall{
  height:calc(100vh / var(--ui-zoom) - 32px); height:calc(100dvh / var(--ui-zoom) - 32px); max-height:960px;
  display:flex; flex-direction:column; margin:0 auto;
}
.prj-dialog-tall .prj-dialog-body{ flex:1; min-height:0; }
.prj-dialog-tall .prj-tree-picker{ flex:1; min-height:0; }
.prj-dialog-tall .prj-tree{ flex:1; min-height:0; max-height:none; }
.prj-dialog-tall .prj-dialog-btns{ margin-top:10px; }
/* Дерево «папок» в окне выбора родителя. */
.prj-tree-picker{ display:flex; flex-direction:column; gap:6px; text-transform:none; letter-spacing:0; }
.prj-tree-picker .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; }
.prj-tree-legend{ color:var(--green); }
.prj-tree-legend:empty{ display:none; }
.prj-tree{ position:relative; border:1px solid var(--line-soft); border-radius:6px; }
.prj-dialog-field .prj-tree{ max-height:calc(40vh / var(--ui-zoom)); max-height:calc(40dvh / var(--ui-zoom)); }
.prj-tree-row{
  flex-direction:row; align-items:baseline; gap:8px;
  padding-left:calc(8px + var(--depth, 0) * 18px);
  background-image:repeating-linear-gradient(to right, var(--line) 0 1px, transparent 1px 18px);
  background-size:calc(var(--depth, 0) * 18px) 100%; background-position:8px 0; background-repeat:no-repeat;
}
.prj-tree-name{ flex:1; min-width:0; overflow-wrap:anywhere; }
.prj-tree-n{ font-size:11px; color:var(--dim); white-space:nowrap; }
.prj-tree-here{ font-size:10.5px; color:var(--dim); white-space:nowrap; }
.prj-tree-top{ color:var(--dim); }
.prj-pick-row.sugg{ background-color:color-mix(in srgb, var(--green-dim) 55%, transparent); box-shadow:inset 3px 0 0 var(--green); }
.prj-pick-row.chosen, .prj-pick-row.chosen:hover{ background-color:var(--accent-dim); color:var(--text); box-shadow:inset 3px 0 0 var(--accent); }
.prj-dialog-body{ display:flex; flex-direction:column; gap:10px; }
.prj-dialog-body label, .prj-dialog-field{ display:flex; flex-direction:column; gap:4px; font-size:10px; letter-spacing:0.5px; color:var(--dim); text-transform:uppercase; }
.prj-dialog-body .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; text-transform:none; letter-spacing:0; }
.prj-dialog-field .prj-parent{ text-transform:none; letter-spacing:0; color:var(--text); }
.prj-dialog-field .prj-pick-list{ max-height:200px; text-transform:none; letter-spacing:0; }
.prj-dialog-btns{ display:flex; align-items:center; justify-content:flex-end; flex-wrap:wrap; gap:8px; margin-top:14px; }
.prj-dialog-btns .prj-muted{ flex:1 1 100%; text-align:right; }
.prj-dialog-btns .prj-muted:empty{ display:none; }
.prj-quick-file.disabled{ opacity:0.5; pointer-events:none; }

/* Выделение в списке проектов: долгий тап включает, панель - над нижней плашкой,
   как у фильтра групп в «Задачах» и как в Платежах. */
#prj-list .prj-row{ -webkit-user-select:none; user-select:none; -webkit-touch-callout:none; }
.prj-check{
  flex-shrink:0; width:20px; height:20px; border:1px solid var(--dim2); border-radius:3px;
  display:flex; align-items:center; justify-content:center; font-size:13px; color:var(--accent);
}
.prj-row.selected{ background:rgba(52,213,255,0.08); }
/* в выделении галочку ставит тап по квадратику - попасть в него должно быть легко */
.prj-check{ position:relative; }
.prj-check::after{ content:''; position:absolute; left:-10px; right:-10px; top:-14px; bottom:-14px; }
.prj-row.selected .prj-check{ border-color:var(--accent); }
.prj-selbar{
  position:fixed; left:0; right:0; bottom:var(--appbar-h, 58px); z-index:899;
  display:flex; flex-wrap:wrap; align-items:center; gap:8px; padding:8px 12px;
  background:var(--panel2); border-top:1px solid var(--accent-dim);
  box-shadow:0 -2px 12px rgba(0,0,0,0.25);
}
.prj-selbar-count{ font-size:12px; color:var(--accent); margin-right:auto; }
.prj-selbar .tb-btn{ padding:7px 10px; }
.prj-selbar-exit{ font-size:13px; letter-spacing:0; }
.prj-selbar-note{ flex:1 1 100%; font-size:11px; color:var(--orange); }
.prj-selbar .tb-btn:disabled{ opacity:0.45; cursor:default; }
/* пока панель видна, низ списка не должен прятаться под ней */
body:has(#tab-projects.active #prj-selbar:not(.hidden)) .panes{ padding-bottom:calc(var(--appbar-h, 58px) + 96px); }
body.split-on:has(#tab-projects.active #prj-selbar:not(.hidden)) .panes{ padding-bottom:0; }
body.split-on #projects-wrap:has(#prj-selbar:not(.hidden)){ padding-bottom:96px; }
.prj-note{ font-size:12px; color:var(--green); padding:8px 10px; border:1px solid var(--green-dim); }
/* Удаление проекта - внизу карточки, отдельно и красным: действие необратимое. */
.prj-danger{ border-top-color:var(--red-dim); }
.prj-del-btn{ color:var(--red); border-color:var(--red-dim); align-self:flex-start; }
.prj-del-btn:hover:not(:disabled){ color:var(--red); border-color:var(--red); background:rgba(255,84,112,0.08); }
.prj-del-btn:disabled{ opacity:0.4; cursor:default; }
/* Ручка перетаскивания и стрелка группы в дереве. Ручка не прокручивает страницу
   пальцем (touch-action) - иначе тянуть было бы нельзя. */
.prj-drag{
  flex-shrink:0; align-self:stretch; display:flex; align-items:center; justify-content:center;
  width:24px; margin-left:-4px; color:var(--dim2); font-size:16px; cursor:grab; touch-action:none;
}
.prj-drag:hover{ color:var(--accent); }
.prj-toggle, .prj-toggle-sp{ flex-shrink:0; width:20px; align-self:stretch; display:flex; align-items:center; justify-content:center; }
/* ручка и стрелка - вплотную, без общего зазора строки */
.prj-drag + .prj-toggle, .prj-drag + .prj-toggle-sp{ margin-left:-10px; }
.prj-toggle{ color:var(--accent); font-size:13px; cursor:pointer; }
/* Заголовок хэштега в дереве: не строка проекта - не выделяется, не принимает перетаскивание. */
.prj-tag-head{
  display:flex; align-items:baseline; gap:6px; width:100%; text-align:left; cursor:pointer;
  background:var(--panel2); border:none; border-bottom:1px solid var(--line-soft);
  color:var(--text); font-family:inherit; font-size:13px; padding:9px 6px;
}
.prj-tag-head:hover{ color:var(--accent); }
.prj-tag-arrow{ flex-shrink:0; width:14px; color:var(--accent); font-size:13px; }
.prj-tag-name{ min-width:0; overflow-wrap:anywhere; }
.prj-tag-n{ flex-shrink:0; color:var(--dim); font-size:12px; }
.prj-row.dragging{ opacity:0.4; }
.prj-row.drop-ok{ outline:2px dashed var(--accent); outline-offset:-2px; background:rgba(52,213,255,0.10); }
body.prj-dragging, body.prj-dragging *{ cursor:grabbing !important; user-select:none; }
.prj-drag-ghost{
  position:fixed; z-index:10000; pointer-events:none; max-width:260px;
  padding:6px 10px; font-size:12px; color:var(--text); background:var(--panel2);
  border:1px solid var(--accent); box-shadow:0 6px 20px rgba(0,0,0,0.45);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.prj-drop-top{
  position:fixed; top:0; left:0; right:0; z-index:9999; padding:16px 12px; text-align:center;
  font-size:12px; color:var(--accent); background:var(--panel2); border-bottom:2px dashed var(--accent-dim);
}
.prj-drop-top.over{ background:rgba(52,213,255,0.18); border-bottom-color:var(--accent); }
.prj-kpis{ display:grid; grid-template-columns:repeat(auto-fill, minmax(140px, 1fr)); gap:8px; }
.prj-kpis > div{ background:var(--panel2); border:1px solid var(--line-soft); padding:8px 10px; display:flex; flex-direction:column; gap:3px; }
.prj-kpis b{ font-size:15px; font-weight:normal; white-space:nowrap; }
.prj-kpis b.in{ color:var(--green); }
.prj-kpis b.out{ color:var(--red); }
.prj-kpis span{ font-size:10px; color:var(--dim); }
.prj-sub{ font-size:10px; letter-spacing:1px; color:var(--dim); text-transform:uppercase; margin-top:6px; }
.prj-pay{
  display:grid; grid-template-columns:auto minmax(0, 1fr) auto; gap:10px; align-items:baseline;
  font-size:12px; padding:5px 2px; border-bottom:1px solid var(--line-soft);
}
.prj-pay > span:first-child{ color:var(--dim); white-space:nowrap; }
.prj-pay-who{ overflow-wrap:anywhere; }
.prj-pay-sum{ white-space:nowrap; }
.prj-pay.in .prj-pay-sum{ color:var(--green); }
.prj-pay.out .prj-pay-sum{ color:var(--red); }
.prj-now{ font-weight:normal; color:var(--accent); }

@media (max-width: 760px){
  #projects-wrap, #contacts-wrap{ padding:12px 10px; }
  .prj-kpis{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
  .prj-kpis b{ font-size:14px; }
  .prj-row{ padding:11px 2px; }
  .prj-thumb{ width:84px; height:84px; }
  .prj-row .prj-row-thumb{ width:44px; height:44px; }
  /* 14px с общим зумом 1.2 - больше 16: меньше этого Safari зумит страницу при фокусе. */
  .prj-top .tb-input, .prj-card .tb-input, .prm-edit .tb-input, .prm-add-panel .tb-input, .prj-picker .tb-input, .prj-dialog-body .tb-input{ font-size:14px; }
  /* на телефоне окно почти во весь экран */
  .prj-dialog-backdrop{ padding:8px; }
  .prj-dialog{ padding:12px; }
  .prj-dialog-tall{ height:calc(100vh / var(--ui-zoom) - 16px); height:calc(100dvh / var(--ui-zoom) - 16px); }
  .prj-tree-row{ padding-top:11px; padding-bottom:11px; }
}

/* ---------- ВКЛАДКА «ВРЕМЯ» ----------
   Стили экрана графиков из приложения «Время» (style.css), каждый под #tab-time,
   тёмные константы заменены переменными админки - светлая тема работает и здесь.
   Масштаб вкладки - 1:1, без общего зума админки: шкала считает касания и
   размеры в пикселях экрана, а шрифт - тот же, что во «Времени», под него
   рассчитана ширина колонок. */
#tab-time{
  zoom:calc(1 / var(--ui-zoom));
  --panel-2:var(--panel2); --muted:var(--dim); --danger:var(--red); --warn:var(--orange);
  font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size:13px; color:var(--text); background:var(--panel);
}
#tab-time.active{ display:flex; flex-direction:column; min-height:0; }
body.split-on #tab-time.active{ height:auto; }
/* Подпись панели при разделении экрана - общая для всех вкладок: возвращаем ей
   масштаб и шрифт админки, иначе у «Времени» она мельче соседней. */
#tab-time > .pane-title{ zoom:var(--ui-zoom); font-family:var(--mono); }
#tab-time .time-bar{
  display:flex; align-items:center; gap:8px; flex-shrink:0;
  padding:6px 10px; background:var(--panel); border-bottom:1px solid var(--line);
}
#tab-time .time-bar-title{ color:var(--dim); font-size:12px; }
#tab-time #dayPanel{ flex:1; min-height:0; overflow:auto; border-bottom:none; }
#tab-time #dayPanelBody{ max-height:none; overflow:visible; padding-bottom:16px; }
/* Нижняя плашка админки лежит поверх всех вкладок: окно правки встаёт над ней
   (высоту плашки кладёт time.js в --time-appbar-h), календарь и так сверху. */
#tab-time .modal.sheet{ bottom:var(--time-appbar-h, 0px); }
/* Приглушение блоков при правке сделано затемнением - на светлой теме из блоков
   получались тёмные пятна. Здесь гасим в сторону фона. */
body.light-theme #tab-time .bd-seg.dim, body.light-theme #tab-time .bd-pause.dim{ filter:saturate(0.35) brightness(1.3); }
@keyframes time-spin { to { transform: rotate(360deg); } }
#tab-time .spinner-small {
  display: inline-block; width: 14px; height: 14px;
  border: 2px solid rgba(14,26,34,0.35);
  border-top-color: var(--panel);
  border-radius: 50%;
  animation: time-spin 0.7s linear infinite;
  vertical-align: -2px;
}
#tab-time .topbar-date { display: flex; align-items: center; gap: 5px; flex-shrink: 0; margin: 0 4px; }
#tab-time .topbar-date.warn #shiftsDateInput { border-color: var(--danger); color: var(--danger); font-weight: 700; background: var(--red-dim); }
#tab-time .topbar-seg {
  background: none; border: 1px solid var(--line); border-radius: 8px; color: var(--accent);
  font-size: 12px; padding: 4px 6px; cursor: pointer;
}
#tab-time #dayPanel { flex: 1; min-height: 0; overflow-y: auto; border-bottom: none; }
#tab-time .day-panel-body { max-height: none; overflow: visible; padding-bottom: 16px; }
#tab-time .day-panel { background: var(--panel); border-bottom: 1px solid var(--line); flex-shrink: 0; font-size: 13px; }
#tab-time .day-panel-body { max-height: 40vh; overflow-y: auto; padding: 2px 12px 6px; }
#tab-time .modal.sheet { align-items: flex-end; padding: 0; background: none; pointer-events: none; }
#tab-time .modal.sheet .modal-card { pointer-events: auto; box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.45); }
#tab-time /* окно всегда влезает в экран: карточка не выше экрана, #tab-time длинный список
   проектов прокручивается внутри себя, #tab-time кнопки снизу остаются на виду */
.modal.sheet .modal-card {
  border-radius: 16px 16px 0 0; max-width: 560px; padding-bottom: env(safe-area-inset-bottom, 0px);
  max-height: 38dvh; display: flex; flex-direction: column; border-top: 1px solid var(--line);
}
#tab-time .modal.sheet .modal-body { padding: 8px 12px 12px; }
#tab-time .modal.sheet .modal-header { padding: 6px 12px; }
#tab-time .modal.sheet .modal-body { flex: 1; min-height: 0; overflow-y: auto; }
#tab-time .modal.sheet h2 { font-size: 15px; }
#tab-time .sheet-btn {
  display: block; width: 100%; text-align: left; margin: 6px 0; padding: 12px;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line); border-radius: 10px; font-size: 16px; cursor: pointer;
}
#tab-time .sheet-btn.danger { color: var(--danger); }
#tab-time .sheet-btn.primary { background: var(--accent); color: #111; border-color: var(--accent); text-align: center; font-weight: 600; }
#tab-time /* шапка окна: закрыть слева, #tab-time "Сохранить" справа */
.sheet-header { align-items: center; gap: 8px; }
#tab-time .sheet-title { flex: 1; }
#tab-time .sheet-save {
  background: var(--accent); color: var(--panel); border: none; border-radius: 8px;
  padding: 8px 14px; font-size: 14px; font-weight: 600; cursor: pointer;
}
#tab-time .sheet-save:disabled { opacity: 0.4; }
#tab-time .sheet-btn:disabled { opacity: 0.45; }
#tab-time .sheet-actions { display: flex; gap: 8px; }
#tab-time .sheet-actions .sheet-btn { text-align: center; }
#tab-time .sheet-label { color: var(--muted); font-size: 13px; margin: 10px 0 4px; }
#tab-time .sheet-time-row { position: relative; display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 4px; }
#tab-time /* список часов/минут — вертикально над полем времени */
.time-drop {
  position: fixed; transform: translateX(-50%);
  width: 168px; z-index: 1200; display: flex; gap: 4px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 12px; padding: 4px;
}
#tab-time .time-col { flex: 1; overflow-y: auto; scrollbar-width: none; }
#tab-time .time-col::-webkit-scrollbar { width: 0; }
#tab-time .time-opt {
  display: block; width: 100%; padding: 8px; background: none; border: none; cursor: pointer;
  color: var(--text); font-size: 18px; font-variant-numeric: tabular-nums; border-radius: 8px;
}
#tab-time .time-opt.on { background: var(--accent); color: var(--panel); font-weight: 700; }
#tab-time /* Поле времени — главный элемент формы: крупнее и цветом, #tab-time чтобы не путалось
   с чипами времени над ним. .modal-body input задаёт width:100% — перебиваем. */
/* время как две кнопки: часы и минуты */
.sheet-time .time-part {
  background: none; border: none; color: inherit; font: inherit; cursor: pointer; padding: 0 2px;
}
#tab-time .sheet-time .time-colon { opacity: 0.7; }
#tab-time .modal-body .sheet-time, #tab-time .modal-body input.sheet-time {
  font-size: 24px; font-weight: 700; letter-spacing: 1px; padding: 6px 12px;
  background: var(--panel-2); color: var(--orange);
  border: 2px solid var(--orange); border-radius: 10px;
  flex: none; text-align: center; font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center;
}
#tab-time .modal-body input.sheet-time:focus { outline: none; box-shadow: 0 0 0 3px rgba(232, 163, 62, 0.25); }
#tab-time .sheet-rel { color: var(--muted); font-size: 13px; }
#tab-time /* Оба ряда чипов времени (точные времена над полем и сдвиги под ним) —
   строго одна строка с прокруткой вбок. */
.sheet-chips.sheet-time-chips, #tab-time .sheet-chips.sheet-nudge {
  display: flex; flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch; max-width: 100%;
}
#tab-time /* Полосы прокрутки у рядов чипов не показываем: они съедают высоту и мелькают */
.sheet-chips, #tab-time .tla-btns, #tab-time .bd, #tab-time .day-panel { scrollbar-width: none; }
#tab-time .sheet-chips::-webkit-scrollbar, #tab-time .tla-btns::-webkit-scrollbar { width: 0; height: 0; }
#tab-time .sheet-nudge { margin-top: 6px; }
#tab-time .sheet-time-chips .chip, #tab-time .sheet-nudge .chip, #tab-time .sheet-proj-chips .chip { flex: 0 0 auto; white-space: nowrap; font-size: 14px; padding: 6px 10px; }
#tab-time .sheet-chips { display: flex; flex-wrap: wrap; gap: 6px; }
#tab-time .sheet-chips .chip { font-size: 16px; }
#tab-time .sheet-emp-chips { margin-bottom: 4px; flex-wrap: nowrap; overflow-x: auto; }
#tab-time .sheet-chips.sheet-time-chips { margin-bottom: 6px; padding-bottom: 2px; }
#tab-time /* переключатель СТОП / ПРОЕКТ */
.seg-switch { display: flex; gap: 0; margin: 10px 0 6px; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
#tab-time .seg-switch .seg {
  flex: 1; padding: 7px; background: var(--panel-2); color: var(--muted);
  border: none; font: inherit; font-weight: 600; cursor: pointer;
}
#tab-time .seg-switch .seg.seg-on { background: var(--accent); color: var(--panel); }
#tab-time .seg-switch .seg.stop.seg-on { background: var(--danger); color: #1a0f0c; }
#tab-time .sheet-search {
  width: 100%; box-sizing: border-box; margin-bottom: 6px; padding: 8px 10px; font-size: 16px;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line); border-radius: 10px;
}
#tab-time /* Чипы проектов — тоже одна строка с прокруткой вбок (класс задан вместе с
   .sheet-chips, #tab-time поэтому селектор из двух классов: иначе перенос переопределял) */
.sheet-chips.sheet-proj-chips { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; }
#tab-time .chip.chip-new { border-color: var(--accent); color: var(--accent); }
/* Выбор проекта: чип в две строки (название и путь родителей), ряд детей, строка пути.
   Стоит на 390 без выхода за ширину: чип не шире 200, длинное обрезается многоточием. */
#tab-time .tl-projrow { display: flex; gap: 6px; align-items: stretch; }
#tab-time .tl-projrow-chips.sheet-chips.sheet-proj-chips { position: relative; flex: 1 1 auto; min-width: 0; }
#tab-time .tl-kids.sheet-chips.sheet-proj-chips { position: relative; }
#tab-time .chip.chip-proj { display: inline-flex; align-items: center; gap: 6px; max-width: 200px; border-radius: 14px; text-align: left; }
#tab-time .chip-proj-main { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
#tab-time .chip-proj-t, #tab-time .chip-proj-p { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#tab-time .chip-proj-p { font-size: 11px; opacity: 0.7; }
#tab-time .chip-proj-dim { color: var(--muted); }
#tab-time .chip.chip-selected .chip-proj-dim { color: inherit; opacity: 0.8; }
#tab-time .chip.chip-trail { border-color: var(--accent); color: var(--accent); }
#tab-time .tl-projrow .chip.chip-new { flex: 0 1 auto; max-width: 45%; overflow: hidden; text-overflow: ellipsis; font-size: 14px; padding: 6px 10px; white-space: nowrap; }
#tab-time .sheet-chips.tl-kids { margin-top: 6px; padding-left: 8px; border-left: 2px solid var(--accent-dim); }
#tab-time .tl-path { display: flex; flex-wrap: nowrap; align-items: center; gap: 6px; margin: 2px 0 8px; font-size: 14px; line-height: 1.3; white-space: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
#tab-time .tl-path::-webkit-scrollbar { width: 0; height: 0; }
#tab-time .tl-path > * { flex: 0 0 auto; }
#tab-time .tl-path-seg { background: none; border: none; padding: 2px 0; font: inherit; color: var(--accent); cursor: pointer; text-align: left; }
#tab-time .tl-path-sep { color: var(--muted); }
#tab-time .tl-path-cur { font-weight: 700; }
#tab-time .chip.chip-stop { border-color: var(--danger); color: var(--danger); }
#tab-time .chip.chip-stop.chip-selected { background: var(--danger); color: #fff; }
#tab-time .sheet-preview { margin: 12px 0 6px; font-size: 14px; line-height: 1.5; }
#tab-time .sheet-preview.err { color: var(--danger); }
#tab-time .sheet-preview:empty { margin: 0; }
#tab-time .dp-empty, #tab-time .dp-warn { color: var(--muted); padding: 6px 0; }
#tab-time /* сотрудник без записей за день — приглушён, #tab-time чтобы работавшие выделялись */
.bd-head.empty { color: var(--muted); font-weight: 500; }
#tab-time .dp-warn { color: var(--danger); }
#tab-time #shiftsDateInput {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 8px; color: var(--text); padding: 4px 6px; font-size: 13px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
#tab-time .shifts-unclosed-warn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--red); color: #fff; font-weight: 700; font-size: 13px; line-height: 1;
  flex-shrink: 0;
}
#tab-time .shifts-unclosed-warn.short { background: var(--orange); }
#tab-time /* Прижат к верху, #tab-time а не по центру: когда закрывается клавиатура (тап по
   кнопке из поля причины), #tab-time центрированное окно съезжало бы между нажатием
   и отпусканием пальца, #tab-time и тап попадал бы в соседнюю кнопку или другой день. */
.cal-backdrop {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(0, 0, 0, 0.55);
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: calc(12px + env(safe-area-inset-top, 0px));
}
#tab-time .cal-box {
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  padding: 12px; width: min(320px, calc(100vw - 24px));
}
#tab-time .cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; font-weight: 600; }
#tab-time .cal-nav {
  background: var(--panel-2); border: none; color: var(--text);
  width: 34px; height: 34px; border-radius: 8px; font-size: 20px; cursor: pointer;
}
#tab-time .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
#tab-time .cal-dow span { text-align: center; font-size: 11px; opacity: 0.6; padding-bottom: 2px; }
#tab-time .cal-day {
  aspect-ratio: 1; border: none; border-radius: 8px; cursor: pointer;
  background: var(--panel-2); color: var(--text); font-size: 14px;
}
#tab-time .cal-day.unclosed { background: var(--red); color: #fff; font-weight: 600; }
#tab-time .cal-day.short { background: var(--orange); color: #fff; font-weight: 600; }
#tab-time .cal-day.acked { box-shadow: inset 0 0 0 2px var(--green); }
#tab-time .cal-day.today { box-shadow: inset 0 0 0 1px var(--accent); }
#tab-time .cal-day.selected { box-shadow: inset 0 0 0 2px var(--accent); font-weight: 700; }
#tab-time .cal-day.detail { outline: 2px solid var(--text); outline-offset: -2px; }
#tab-time .cal-legend { margin-top: 8px; font-size: 12px; opacity: 0.8; display: flex; flex-wrap: wrap; gap: 4px 12px; }
#tab-time .cal-legend span { display: inline-flex; align-items: center; gap: 6px; }
#tab-time .cal-legend i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }
#tab-time .cal-legend .lg-unclosed { background: var(--red); }
#tab-time .cal-legend .lg-short { background: var(--orange); }
#tab-time .cal-legend .lg-acked { box-shadow: inset 0 0 0 2px var(--green); }
#tab-time .cal-box { max-height: calc(100dvh - 24px); overflow-y: auto; }
/* Окно сообщений «Времени»: по центру, поверх формы внизу и плашки админки (z-index выше формы 50 и
   плашки 960); не выше экрана, длинный список листается внутри - само окно прокручивать не надо. */
#tab-time .msg-backdrop { align-items: center; padding: 16px; z-index: 1300; }
#tab-time .msg-box {
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  padding: 14px; width: min(420px, 100%); max-height: calc(100dvh - 32px);
  display: flex; flex-direction: column; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
#tab-time .msg-box h2 { margin: 0 0 10px; font-size: 16px; }
#tab-time .msg-body { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }
#tab-time .msg-row {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 7px 10px; border-radius: 8px; font-size: 14px; line-height: 1.35;
  border: 1px solid var(--line); background: var(--panel-2);
}
#tab-time .msg-row .msg-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
#tab-time .msg-row.ok { border-color: var(--green-dim); }
#tab-time .msg-row.warn { border-color: var(--auto); background: var(--auto-bg); }
#tab-time .msg-row.error { border-color: var(--red); background: rgba(255, 84, 112, 0.1); }
#tab-time .msg-open {
  flex-shrink: 0; background: none; border: 1px solid var(--auto); border-radius: 8px;
  color: var(--text); font: inherit; font-size: 13px; padding: 5px 9px; cursor: pointer;
}
#tab-time .msg-ok {
  margin-top: 12px; width: 100%; padding: 11px; border: none; border-radius: 10px;
  background: var(--accent); color: var(--panel); font: inherit; font-weight: 700; cursor: pointer;
}
#tab-time .cal-detail { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
#tab-time .cal-detail-title { font-weight: 600; }
#tab-time .cal-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
#tab-time .cal-row span { flex: 1; min-width: 0; }
#tab-time .cal-act {
  background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
  border-radius: 8px; padding: 6px 10px; font-size: 12px; cursor: pointer; flex-shrink: 0;
}
#tab-time .cal-act:disabled { opacity: 0.5; }
#tab-time .cal-act.wide { width: 100%; padding: 8px; }
#tab-time .cal-act.primary { background: var(--accent); color: var(--panel); border-color: var(--accent); font-weight: 600; }
#tab-time .cal-reason {
  width: 100%; box-sizing: border-box; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 8px; color: var(--text); padding: 6px 8px; font-size: 13px;
}
#tab-time .cal-err { color: var(--danger); font-size: 12px; }
#tab-time .cal-err:empty { display: none; }
#tab-time .chip {
  flex-shrink: 0;
  background: var(--panel-2); border: 1.5px solid var(--line); color: var(--text);
  border-radius: 21px; padding: 4px 10px; font-size: 19px; cursor: pointer; white-space: nowrap;
  transition: background .12s, border-color .12s, transform .08s;
}
#tab-time .chip:active { transform: scale(0.96); }
#tab-time .chip.chip-now { border-color: var(--accent); color: var(--accent); font-weight: 600; }
#tab-time .chip.chip-selected {
  background: var(--accent); color: var(--panel); border-color: var(--accent); font-weight: 700;
  box-shadow: 0 0 0 2px rgba(46,166,160,0.35);
}
#tab-time .modal {
  position: fixed; inset: 0; background: rgba(0,0,0,0.5);
  display: flex; align-items: center; justify-content: center;
  z-index: 50; padding: 16px;
}
#tab-time .modal-card {
  background: var(--panel); border-radius: 16px;
  width: 100%; max-width: 460px; max-height: 82vh;
  display: flex; flex-direction: column; overflow: hidden;
}
#tab-time .modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--line);
}
#tab-time .modal-header h2 { margin: 0; font-size: 16px; }
#tab-time .modal-header button { background: none; border: none; color: var(--muted); font-size: 18px; cursor: pointer; }
#tab-time .modal-body { padding: 14px 16px; overflow-y: auto; font-size: 14px; line-height: 1.6; }
#tab-time .modal-body label { display: block; margin: 12px 0 4px; font-size: 13px; color: var(--muted); }
#tab-time .modal-body input, #tab-time .modal-body textarea {
  width: 100%; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 8px; color: var(--text); padding: 8px 10px; font-size: 14px; font-family: inherit;
}
#tab-time .bd { --bd-axis: 44px; padding-bottom: 8px; width: max-content; min-width: 100%; }
#tab-time #dayPanel { overflow: auto; }
#tab-time .bd-heads {
  display: grid; grid-template-columns: var(--bd-axis) var(--bd-grid);
  position: sticky; top: 0; z-index: 3; background: var(--panel); padding: 4px 0;
  border-bottom: 1px solid var(--line);
}
#tab-time .bd-head { font-weight: 600; font-size: 13px; line-height: 15px; padding: 0 6px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#tab-time .bd-head b { display: block; color: var(--muted); font-weight: 500; font-size: 12px; }
#tab-time .bd-body { position: relative; margin-top: 8px; }
#tab-time /* отступ — чтобы первая метка не пряталась под шапкой */
/* тонкие линии часов через всю ширину, #tab-time получасы — ещё бледнее */
.bd-line { position: absolute; left: 0; border-top: 1px solid var(--line); }
#tab-time .bd-line.half { border-top-style: dotted; border-top-color: var(--line-soft); }
#tab-time .bd-line span {
  position: absolute; left: 0; top: -9px; height: 18px; width: calc(var(--bd-axis) - 6px);
  display: flex; align-items: center; justify-content: flex-end;
  font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; background: var(--panel); padding-right: 2px;
}
#tab-time .bd-line.draft { border-top: 2px dashed var(--accent); z-index: 2; }
#tab-time .bd-line.draft span { color: var(--accent); font-weight: 700; }
#tab-time .bd-now { position: absolute; left: var(--bd-axis); right: 0; border-top: 2px solid var(--accent); z-index: 1; }
#tab-time .bd-now span {
  position: absolute; left: calc(var(--bd-axis) * -1); top: -8px; width: calc(var(--bd-axis) - 6px);
  text-align: right; font-size: 11px; font-weight: 700; color: var(--accent);
  background: var(--panel); padding-right: 2px;
}
#tab-time .bd-cols {
  position: absolute; top: 0; bottom: 0; left: var(--bd-axis); right: 0;
  display: grid; grid-template-columns: var(--bd-grid);
}
#tab-time .bd-col { position: relative; }
#tab-time /* блоки — сплошная заливка цветом проекта, #tab-time без рамок; тёмный текст читается
   на всех цветах палитры */
.bd-seg {
  position: absolute; left: 3px; right: 3px; border-radius: 5px; overflow: hidden; cursor: pointer; z-index: 1;
  background: var(--tl-color);
  padding: 1px 5px; font-size: 11px; line-height: 13px; color: rgba(0, 0, 0, 0.85);
  display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center;
}
#tab-time /* выделенный блок и его метки времени */
.bd-seg.sel { outline: 2px solid var(--text); outline-offset: -2px; }
#tab-time /* во время правки линии и подписи приглушаем вместе с блоками */
.bd-line.dim { border-top-color: var(--line-soft); }
#tab-time .bd-line.dim span { opacity: 0.4; }
#tab-time .bd-line.hot { border-top-color: var(--text); border-top-width: 2px; }
#tab-time /* участок до колонки: линия обычная, #tab-time подпись — белая и жирная */
.bd-line.hot-label { border-top-color: var(--text); border-top-width: 2px; }
#tab-time .bd-line.hot-label span, #tab-time .bd-line.hot span { color: var(--text) !important; font-weight: 700; }
#tab-time .bd-line.hot span { color: var(--text); font-weight: 700; top: -17px; height: 34px; }
#tab-time .bd-line.hot-label span { top: -17px; height: 34px; }
#tab-time /* черновик новой записи: пока не выбран проект, #tab-time он только на экране */
.bd-draft-grip {
  position: absolute; left: 0; right: 0; top: -6px; height: 14px;
  border-top: 3px solid var(--accent); border-radius: 3px;
}
#tab-time /* Гасим яркостью, #tab-time а не прозрачностью: при opacity сквозь блок просвечивали
   линии времени, #tab-time которые должны оставаться под ним. */
.bd-seg.dim, #tab-time .bd-pause.dim { filter: brightness(0.45) saturate(0.75); }
#tab-time /* черновик всегда тёмный, #tab-time цвет проекта — в рамке и подписи */
.bd-draft.colored { border-color: var(--tl-color); color: var(--tl-color); }
#tab-time .bd-draft {
  position: absolute; left: 3px; right: 3px; z-index: 1; border-radius: 5px;
  border: 2px dashed var(--accent); color: var(--accent); font-size: 10px; line-height: 11px;
  display: flex; align-items: center; justify-content: center; text-align: center;
  padding: 0 3px; overflow: hidden; background: var(--bg);
}
#tab-time /* панель действий над выделенным блоком — внизу экрана */
.tl-actions {
  flex-shrink: 0; background: var(--panel); border-top: 1px solid var(--line);
  padding: 6px 10px calc(6px + env(safe-area-inset-bottom, 0px));
  display: flex; flex-direction: column; gap: 6px;
}
#tab-time .tla-title { font-size: 12px; color: var(--muted); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#tab-time .tla-btns { display: flex; gap: 6px; overflow-x: auto; }
#tab-time .tla-btn {
  flex: 0 0 auto; white-space: nowrap; background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px; font-size: 14px; cursor: pointer;
}
#tab-time .tla-btn.danger { color: var(--danger); }
#tab-time /* окно во время сохранения */
.modal-card.sheet-busy { position: relative; pointer-events: none; }
#tab-time .modal-card.sheet-busy::after {
  content: ""; position: absolute; inset: 0; background: rgba(14, 26, 34, 0.45);
  border-radius: inherit;
}
#tab-time .bd-projedit { text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
#tab-time .bd-edit {
  display: inline-flex; align-items: center; justify-content: flex-end;
  min-height: 34px; padding-right: 4px; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
#tab-time .bd-seg.jt { border-top-left-radius: 0; border-top-right-radius: 0; }
#tab-time .bd-seg.jb { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
#tab-time /* пауза — слабо-серая заливка без рамок, #tab-time стыкуется с отрезками без зазора */
.bd-pause {
  position: absolute; left: 3px; right: 3px;
  /* Штриховка поверх непрозрачного фона: линии времени сквозь паузу не видны,
     и она не путается ни с блоками работы, ни с сеткой. */
  background-color: var(--panel);
  /* штриховка и боковые границы — один и тот же сплошной цвет, без прозрачности */
  background-image: repeating-linear-gradient(45deg, var(--line) 0 5px, transparent 5px 10px);
  border-left: 5px solid var(--line); border-right: 5px solid var(--line);
  color: var(--muted); font-size: 11px; line-height: 12px;
  padding: 0 5px; overflow: hidden; box-sizing: border-box; text-align: center;
  display: flex; align-items: center; justify-content: center;
}
#tab-time .bd-pause.tl-tap { cursor: pointer; }
#tab-time .bd-add.stop { color: var(--danger); }
#tab-time .bd-add.tall { height: 40px; font-size: 20px; }
#tab-time /* завершить / сменить проект — крупная цель для пальца */
/* Лаконичный "+" без рамки и фона. На цветных блоках (штриховка стопа) —
   с лёгкой подложкой, #tab-time иначе не читается. */
.bd-add {
  position: absolute; left: 3px; right: 3px; height: 20px; z-index: 2; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: var(--dim); font-size: 18px; border-radius: 5px;
  background: var(--panel);
}
#tab-time /* пустое место над первым и под последним блоком — вся область тапается */
.bd-zone {
  position: absolute; left: 3px; right: 3px; z-index: 1; cursor: pointer;
  display: flex; justify-content: center;
  color: var(--dim); font-size: 20px; line-height: 1; /* незаметный серый "+" */
}
#tab-time .bd-zone.top { align-items: flex-end; padding-bottom: 2px; }
#tab-time .bd-zone.bottom { align-items: flex-start; padding-top: 2px; }
#tab-time .bd-zone:active { background: rgba(46, 166, 160, 0.10); border-radius: 6px; }
#tab-time .bd-seg.open { background: linear-gradient(to bottom, var(--tl-color), transparent); }
#tab-time .bd-seg.pending {
  background: repeating-linear-gradient(135deg, var(--danger) 0 4px, transparent 4px 7px);
  color: var(--danger); font-weight: 700; text-align: center; padding: 0;
}
/* Название в блоке и в черновике: переносится по словам БЕЗ знаков переноса (hyphens: none), слово,
   которое не влезает в ширину, режется по буквам без знака (overflow-wrap: anywhere); строк
   столько, сколько помещается по высоте (--tl-lines кладёт time.js), последняя видимая строка
   заканчивается «…». Самые низкие блоки (tiny) - одна строка мелким. */
#tab-time .bd-name, #tab-time .bd-draft-name {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--tl-lines, 1);
  overflow: hidden; white-space: normal; hyphens: none; overflow-wrap: anywhere;
  min-width: 0; max-width: 100%;
}
#tab-time .bd-name { font-weight: 600; flex: 0 1 auto; }
#tab-time .bd-seg.tiny .bd-name { display: block; white-space: nowrap; text-overflow: ellipsis; }
#tab-time .bd-seg.tiny { padding: 0 3px; font-size: 9px; line-height: 9px; }
/* Тонкая светлая граница между соседними блоками (1px сверху и снизу цветом фона): подряд идущие
   блоки одного цвета видны отдельными. Интервал 0 минут - линия 2px без границы и подписи. */
#tab-time .bd-seg { box-shadow: inset 0 1px 0 var(--bg), inset 0 -1px 0 var(--bg); }
#tab-time .bd-seg.zero { box-shadow: none; min-height: 0; padding: 0; opacity: 0.8; }
#tab-time .bd-dur { opacity: 0.85; }
/* Незакрытая смена за прошлый день: пометка красным (как день в календаре). */
/* Окно «Слить проекты». */
.prj-merge{ gap:14px; }
.prj-merge-sec{ display:flex; flex-direction:column; gap:6px; }
.prj-merge-title{ font-size:10px; letter-spacing:0.5px; color:var(--dim); text-transform:uppercase; }
.prj-dialog-body label.prj-merge-opt{ flex-direction:row; align-items:flex-start; gap:8px; font-size:13px; color:var(--text); text-transform:none; letter-spacing:0; cursor:pointer; }
.prj-merge-opt input[type=radio], .prj-merge-opt input[type=checkbox]{ margin-top:3px; flex-shrink:0; accent-color:var(--accent); }
.prj-merge-opt > span{ display:flex; flex-direction:column; gap:2px; min-width:0; overflow-wrap:anywhere; }
.prj-merge-opt .tb-input{ margin-top:4px; }
.prj-merge-name{ font-size:13px; }
.prj-dialog-body label.prj-merge-chk{ color:var(--dim); font-size:12px; }
.prj-merge-sum{ margin:0; padding-left:18px; display:flex; flex-direction:column; gap:4px; font-size:12.5px; color:var(--text); text-transform:none; letter-spacing:0; }
.prj-merge-block{ font-size:12px; color:var(--red); }

/* Вкладка «Имущество»: слева (на узком экране сверху, сворачивается) ветки, справа объекты. */
#property-wrap{ gap:12px; max-width:1200px; width:100%; margin:0 auto; box-sizing:border-box; }
.prop-wrap{ display:flex; flex-direction:column; gap:12px; min-width:0; }
.prop-main{ min-width:0; display:flex; flex-direction:column; gap:10px; }
.prop-tree{ border:1px solid var(--line); background:var(--panel); min-width:0; }
.prop-tree-toggle{
  display:flex; align-items:center; justify-content:space-between; gap:8px; width:100%; box-sizing:border-box;
  background:none; border:none; color:var(--text); font-family:inherit; font-size:13px; padding:10px 12px; cursor:pointer; text-align:left;
}
.prop-tree-toggle span:first-child{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.prop-tree-body{ padding:4px 0 8px; max-height:44vh; overflow:auto; border:1px solid var(--line-soft); }
.prop-node{ display:flex; align-items:stretch; padding-left:calc(var(--d) * 14px); }
.prop-node.sel{ background:var(--panel2); box-shadow:inset 2px 0 0 var(--accent); }
.prop-caret{ flex:none; width:28px; background:none; border:none; color:var(--dim); font-family:inherit; font-size:12px; cursor:pointer; padding:0; }
span.prop-caret{ cursor:default; }
.prop-node-btn{
  flex:1; min-width:0; display:flex; align-items:center; justify-content:space-between; gap:8px; text-align:left;
  background:none; border:none; color:var(--text); font-family:inherit; font-size:13px; padding:8px 10px 8px 0; cursor:pointer;
}
.prop-node-btn:hover{ color:var(--accent); }
.prop-node-name{ min-width:0; overflow-wrap:anywhere; }
.prop-count{ flex:none; font-size:11px; color:var(--dim); }
.prop-tools{ display:flex; flex-wrap:wrap; gap:8px; }
.prop-tools .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; }
.prop-tools #prop-search{ flex:1 1 220px; width:auto; min-width:0; }
.prop-placeset{ flex:1 1 160px; min-width:0; display:flex; gap:4px; }   /* «📍 Место» и ✕ (Переучёт-7б) */
.prop-placebtn{ flex:1 1 auto; min-width:0; text-align:left; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; }
.prop-placebtn.active{ border-color:var(--accent); font-weight:600; }
.prop-placex{ flex:none; min-width:40px; }
.prop-placeset[hidden]{ display:none; }
.prop-summary{ font-size:11px; color:var(--dim); min-height:14px; }
.prop-item{ border-bottom:1px solid var(--line-soft); }
.prop-row{ display:flex; gap:10px; align-items:flex-start; padding:10px 4px; cursor:pointer; min-width:0; }
.prop-row:hover, .prop-row:focus-visible{ background:var(--panel2); outline:none; }
/* Первое фото крупнее (в 1,5 раза), рядом до 3 маленьких и «+N»; нажатие на любую - просмотр с этой фото и
   листанием, строка не раскрывается. Голосовые - кнопками ▶ там же. */
.prop-photo{ --pp-u:88px; display:block; align-self:flex-start; max-width:100%; margin-top:4px; cursor:default; }
.prop-photo .prj-row-media{ margin:0; flex-wrap:wrap; gap:6px; }
.prop-photo .prj-row-thumb{ width:var(--pp-u); height:var(--pp-u); flex:none; position:relative; cursor:zoom-in; }
.prop-photo .prj-row-thumb:first-child{ width:calc(var(--pp-u) * 1.5); height:calc(var(--pp-u) * 1.5); }
.prop-photo .prj-row-thumb .prj-play{ font-size:20px; }
.prop-photo .prj-row-thumb:first-child .prj-play{ font-size:28px; }
.prop-photo .prj-row-more{ cursor:zoom-in; font-size:12px; padding:0 6px; }
.prop-info{ flex:1; min-width:0; display:flex; flex-direction:column; gap:3px; }
.prop-title{ font-size:14px; overflow-wrap:anywhere; }
.prop-flag{ display:inline-block; margin-left:8px; padding:0 6px; border-radius:8px; font-size:10.5px; line-height:16px; vertical-align:2px; border:1px solid var(--line); color:var(--dim); white-space:nowrap; }
.prop-flag.ev{ color:var(--orange); border-color:var(--orange); background:var(--orange-dim); }
.prop-flag.weak{ color:var(--purple); border-color:var(--purple); background:var(--purple-dim); }
.prop-flag.done{ color:var(--green); border-color:var(--green); }
.prop-flag[data-why]{ cursor:pointer; white-space:normal; max-width:100%; overflow-wrap:anywhere; }
.prop-why{ display:flex; flex-direction:column; gap:2px; padding:4px 8px; font-size:12px; color:var(--dim); border-left:2px solid var(--line); overflow-wrap:anywhere; }
.prop-why[hidden]{ display:none; }
.prop-flag.noown, .prop-flag.noplace{ color:var(--red); border-color:var(--red); background:var(--red-dim); }
.prop-item.prop-done{ opacity:.55; }   /* разобран - в «Разборе» серый и в конце списка */
.prop-cat{ font-size:10.5px; color:var(--dim); }
.prop-ads{ display:flex; flex-wrap:wrap; gap:4px 6px; min-width:0; }
.prop-ad{ max-width:100%; padding:2px 8px; font:inherit; font-size:12px; line-height:1.4; text-align:left; overflow-wrap:anywhere; color:var(--green); background:transparent; border:1px solid var(--green); border-radius:10px; cursor:pointer; }
.prop-ad:hover, .prop-ad:focus-visible{ background:rgba(127,127,127,0.12); }
/* запрос покупателя - та же плашка, другой цвет; мелко «← площадка объявления» (211) */
.prop-ad.prop-req{ color:var(--accent); border-color:var(--accent); }
.prop-ad-from{ display:block; font-size:10.5px; line-height:1.3; color:var(--dim); }
/* нажимаемая ссылка в тексте (projects.js: prjLinkify) */
.prj-url{ color:var(--accent); text-decoration:underline; overflow-wrap:anywhere; }
/* важные поля в окнах проекта и «Новый проект» (§88); сам механизм - .imp-miss / .imp-bang выше */
.prm-group.imp-miss{ padding:7px 8px; }
.prj-new-field.imp-miss, .prj-new label.imp-miss, .prj-dialog-body label.imp-miss{ padding:6px 8px; }
.prj-new-field.imp-miss > .prj-new-label{ color:var(--danger); }
.imp-lab{ display:inline; }
.prj-requests{ display:flex; align-items:center; gap:8px; }
.prj-req-list{ flex-direction:column; align-items:stretch; }
.ol-note{ font-size:12px; overflow-wrap:anywhere; }
.prj-new-obj{ overflow-wrap:anywhere; min-width:0; }
.prop-meta{ display:flex; flex-wrap:wrap; gap:4px 12px; font-size:12px; }
.prop-chip{ min-width:0; max-width:100%; overflow-wrap:anywhere; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3; line-clamp:3; overflow:hidden; }
.prop-chip-l{ color:var(--dim); font-size:10.5px; }
.prop-peek{ padding:4px 4px 14px 4px; display:flex; flex-direction:column; gap:8px; }
.prop-fields{ display:flex; flex-direction:column; }
.prop-field{ padding:6px 0; border-bottom:1px solid var(--line-soft); display:flex; flex-direction:column; gap:3px; }
.prop-field-val{ font-size:13px; line-height:1.45; white-space:pre-wrap; overflow-wrap:anywhere; }
.prop-field.media .prop-field-val{ display:flex; flex-wrap:wrap; gap:6px; }
.prop-field.ev, .prop-field.weak{ padding-left:8px; box-shadow:inset 3px 0 0 var(--orange); }
.prop-field.weak{ box-shadow:inset 3px 0 0 var(--purple); }
.prop-field.ev .prm-name{ color:var(--orange); }
.prop-field.weak .prm-name{ color:var(--purple); }
.prop-v + .prop-v{ margin-top:3px; }
.prop-when{ margin-left:8px; font-size:10.5px; color:var(--dim); white-space:nowrap; }
.prop-long summary{ cursor:pointer; }
.prop-long[open] summary{ display:inline; }
.prop-backs{ display:flex; flex-direction:column; gap:4px; font-size:12.5px; line-height:1.4; overflow-wrap:anywhere; }
.prop-back.in{ color:var(--orange); }
/* Чипы признаков, режим «Разбор»: панель «Всем показанным», кнопки в строке, «Записать». */
.prop-tools #prop-owner{ flex:1 1 200px; width:auto; min-width:0; }
.prop-review-btn.active{ font-weight:600; }
.prop-chips{ display:flex; flex-wrap:wrap; gap:6px; }
.prop-fchip{ font-size:12px; padding:5px 10px; }
.prop-fchip[aria-pressed="true"]{ border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.08); }
.prop-fchip.ev[aria-pressed="true"]{ border-color:var(--orange); color:var(--orange); background:var(--orange-dim); }
.prop-fchip.weak[aria-pressed="true"]{ border-color:var(--purple); color:var(--purple); background:var(--purple-dim); }
.prop-fchip.danger[aria-pressed="true"]{ border-color:var(--red); color:var(--red); background:var(--red-dim); }
.prop-mig:empty{ display:none; }
.prop-mig{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; min-width:0; font-size:12px; }
.prop-mig-btn{ max-width:100%; white-space:normal; text-align:left; }
.prop-mig-list{ max-height:45vh; }
.prop-review{ border:1px solid var(--line); background:var(--panel); padding:10px; display:flex; flex-direction:column; gap:10px; min-width:0; }
.prop-hints-bar, .prop-bulk-row{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; min-width:0; }
.prop-review[hidden]{ display:none; }
.prop-bulk{ min-width:0; }
.prop-bulk-body{ display:flex; flex-direction:column; gap:8px; margin-top:8px; min-width:0; }
.prop-bulk-head{ font-size:12.5px; cursor:pointer; }
.prop-bulk .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; width:100%; }
.prop-bulk-hint{ font-size:11px; }
.prop-review .tb-btn, .prop-own .tb-btn{ max-width:100%; white-space:normal; text-align:left; overflow-wrap:anywhere; }
.prop-own{ display:flex; flex-direction:column; gap:6px; padding:0 4px 12px; min-width:0; }
.prop-dec-row{ display:flex; flex-wrap:wrap; gap:6px; }
.prop-dec{ font-size:12px; }
.prop-dec-our.on{ border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.10); }
.prop-dec-other.on, .prop-dec-gone.on{ border-color:var(--orange); color:var(--orange); background:var(--orange-dim); }
.prop-who{ font-size:11px; }
.prop-own .prop-note{ font-size:13px; padding:7px 10px; box-sizing:border-box; width:100%; }
.prop-will{ font-size:11.5px; color:var(--dim); overflow-wrap:anywhere; }
.prop-will:empty{ display:none; }
.prop-will.warn{ color:var(--orange); }
.prop-hint{ display:flex; align-items:flex-start; justify-content:space-between; gap:8px; font-size:12px; padding:6px 8px; border:1px dashed var(--purple); min-width:0; }
.prop-hint-text{ min-width:0; overflow-wrap:anywhere; }
.prop-hint-note{ display:block; color:var(--dim); margin-top:2px; }
.prop-hint > .tb-btn{ flex:0 0 auto; white-space:nowrap; }   /* «Принять» не ломать по буквам на телефоне */
.prop-conf{ font-size:10.5px; color:var(--dim); white-space:nowrap; }
.prop-conf-h{ color:var(--accent); }
.prop-conf-l{ color:var(--orange); }
.prop-writebar{ position:sticky; bottom:var(--appbar-h, 58px); z-index:5; display:flex; flex-wrap:wrap; align-items:center; gap:10px; padding:10px; background:var(--panel); border:1px solid var(--line); font-size:12px; }
.prop-writebar[hidden]{ display:none; }
body.split-on .prop-writebar{ bottom:0; }
.prop-wsum{ display:flex; flex-direction:column; gap:6px; font-size:13px; margin-bottom:10px; overflow-wrap:anywhere; }
.prop-skip{ margin:0; padding-left:18px; font-size:12px; max-height:40vh; overflow:auto; }
.prop-peek-foot{ display:flex; align-items:center; justify-content:space-between; gap:8px; flex-wrap:wrap; }
.prop-peek-foot .tb-btn{ text-decoration:none; }
.prop-foot{ display:flex; flex-direction:column; align-items:flex-start; gap:8px; padding-bottom:8px; }
.prop-err{ font-size:12px; color:var(--red); }
.prop-tools [hidden], .prop-views [hidden]{ display:none; }
/* виды «Обзор / Переучёт / Продажи» */
.prop-views{ display:flex; flex-wrap:wrap; gap:6px; }
.prop-view-btn{ font-size:13px; padding:6px 12px; }
.prop-view-btn.active{ border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.08); font-weight:600; }
/* правка в строке: подпись и значение, на телефоне - друг под другом */
.prop-edit{ display:flex; flex-direction:column; gap:6px; padding:0 4px 12px; min-width:0; }
.prop-ed-row{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 10px; min-width:0; }
.prop-ed-l{ flex:0 0 9em; font-size:11px; color:var(--dim); }
.prop-ed-v{ flex:1 1 220px; min-width:0; display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.prop-edit .tb-btn{ max-width:100%; white-space:normal; text-align:left; overflow-wrap:anywhere; font-size:12px; }
.prop-ed-row.imp-miss{ padding:4px 6px; }
.prop-edit .prop-ed-note{ font-size:13px; padding:7px 10px; box-sizing:border-box; width:100%; }
.prop-ed-msg{ font-size:11.5px; color:var(--orange); overflow-wrap:anywhere; }
.prop-ed-msg:empty{ display:none; }
.prop-sopt.on{ border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.10); }
/* «Продажи» (журнал §100): вес, «не дешевле», оценки, «+ оценка», цена металлолома */
.prop-chip-gl{ flex:0 0 100%; font-size:11px; color:var(--dim); margin-top:2px; }
.prop-sales .prop-sopt{ font-size:11px; padding:5px 8px; letter-spacing:.02em; }
.prop-num-row{ gap:6px; }
.prop-sales .prop-num{ width:9em; max-width:100%; font-size:13px; padding:6px 8px; box-sizing:border-box; }
.prop-sales .prop-tol{ width:6em; }
.prop-tol-l{ font-size:13px; color:var(--dim); }
.prop-unit-hint{ font-size:11.5px; overflow-wrap:anywhere; }
.prop-unit-hint.bad, .ow-unit-hint.bad, .prm-unit-hint.bad{ color:var(--orange); }
.prop-old-val{ font-size:11.5px; }
.prop-ests .prop-ed-v{ flex-direction:column; align-items:flex-start; gap:4px; }
.prop-est{ font-size:12.5px; line-height:1.4; overflow-wrap:anywhere; }
.prop-est.stale .prop-est-line{ color:var(--dim); }
.prop-flag.stale{ color:var(--orange); border-color:var(--orange); background:var(--orange-dim); }
.prop-est-form{ display:flex; flex-direction:column; gap:8px; padding:8px; border:1px solid var(--line); background:var(--panel2); width:100%; box-sizing:border-box; }
.prop-ef-pair{ display:flex; flex-wrap:wrap; align-items:flex-end; gap:6px 8px; }
.prop-ef{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.prop-ef-l{ font-size:11px; color:var(--dim); }
.prop-ef-cond{ display:flex; flex-direction:column; gap:3px; }
.prop-ef-btns{ display:flex; flex-wrap:wrap; gap:6px; }
.prop-video-hint[hidden]{ display:none; }
.prop-scrap{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 8px; font-size:13px; margin:2px 0; }
.prop-scrap[hidden]{ display:none; }
.prop-scrap-l{ color:var(--dim); }
.prop-scrap-in{ width:9em; max-width:100%; font-size:13px; padding:5px 8px; box-sizing:border-box; }
.prop-scrap-msg{ font-size:11.5px; color:var(--orange); overflow-wrap:anywhere; }
.prop-scrap-msg:empty{ display:none; }
.ow-unit-hint, .prm-unit-hint{ font-size:11.5px; margin-top:2px; overflow-wrap:anywhere; }
.prj-tol{ color:var(--dim); white-space:nowrap; }
.prop-cmts{ display:flex; flex-direction:column; gap:3px; font-size:12.5px; line-height:1.4; min-width:0; }
.prop-cmt{ white-space:pre-wrap; overflow-wrap:anywhere; }
.prop-cmt .prop-when{ margin-left:0; }
/* Компактная строка и карточка (журнал §103): значки полей, место отдельной строкой, артикул последним, «Поля ▾», свёрнутый ввод «Продаж» */
.prop-ic{ font-style:normal; }
.prop-place{ display:block; min-width:0; max-width:100%; white-space:normal; overflow-wrap:anywhere; font-size:12.5px; }   /* §155: место полным путём переносится строкой, не обрезается */
.prop-place.miss .prop-ic, .prop-chip-warn{ color:var(--red); }
.prop-art{ display:block; font-size:10.5px; color:var(--dim); }
.prop-sum{ display:flex; flex-wrap:wrap; gap:2px 14px; font-size:12.5px; min-width:0; }
.prop-vhint{ font-size:11.5px; align-self:center; }
.prop-vhint[hidden]{ display:none; }
.prop-sum-i{ display:inline-flex; align-items:baseline; gap:4px; min-width:0; max-width:100%; margin:0; padding:3px 0; border:0; background:none; color:inherit; font:inherit; text-align:left; cursor:pointer; overflow-wrap:anywhere; }
.prop-sum-i.empty .prop-sum-v{ color:var(--dim); text-decoration:underline dotted; }
.prop-sum-ed{ color:var(--dim); font-size:12px; }
.prop-sum-i:hover .prop-sum-ed, .prop-sum-i:focus-visible .prop-sum-ed{ color:var(--accent); }
.prop-edit .prop-s-close{ padding:3px 8px; color:var(--dim); }
.prop-fields{ position:relative; }
.prop-fields-pop{ position:absolute; z-index:20; top:100%; left:0; margin-top:4px; min-width:220px; max-width:calc(100vw - 32px); box-sizing:border-box; display:flex; flex-direction:column; gap:2px; padding:8px 12px; border:1px solid var(--line); border-radius:8px; background:var(--panel); box-shadow:0 6px 20px rgba(0,0,0,.35); }
.prop-fields-pop[hidden]{ display:none; }
.prop-fld{ display:flex; align-items:center; gap:8px; min-height:30px; font-size:13px; cursor:pointer; }
.prop-fld.locked{ color:var(--dim); cursor:default; }
.prop-fields-reset{ align-self:flex-start; margin-top:4px; font-size:12px; }
@media (max-width:640px){
  .prop-switches{ position:relative; }
  .prop-fields{ position:static; }
  .prop-fields-pop{ left:0; right:0; max-width:none; }
}
@media (max-width:640px){
  .prop-ed-l{ flex:1 0 100%; }
}
/* Показ «Список / Карточки» (журнал §92): карточка - большое главное фото 4:3, под ним ряд миниатюр, ниже то же, что в строке.
   Карточек в ряд - сколько влезает от 240px (на телефоне одна); число миниатюр в ряду считает property.js (propCardSlots). */
.prop-switches{ display:flex; flex-wrap:wrap; gap:6px 16px; }
.prop-list.prop-list-cards{ display:grid; grid-template-columns:repeat(auto-fill, minmax(min(240px, 100%), 1fr)); gap:12px; align-items:stretch; }
.prop-card{ display:flex; flex-direction:column; min-width:0; border:1px solid var(--line); background:var(--panel); }
.prop-card-photo{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin:0; width:100%; max-width:none; box-sizing:border-box; }
.prop-card-main{ flex:0 0 100%; display:block; aspect-ratio:4 / 3; overflow:hidden; position:relative; background:var(--panel2); }
.prop-card-main .prj-row-thumb{ width:100%; height:100%; border:none; position:relative; cursor:zoom-in; }
.prop-card-main .prj-row-thumb .prj-play{ font-size:44px; }
.prop-card-main .prj-row-thumb[hidden]{ display:none; }
/* листание: свайп по горизонтали, вертикальное - прокрутка списка */
.prop-card-main[data-slides]{ touch-action:pan-y; }
.prop-card-main[data-slides]:focus-visible{ outline:2px solid var(--accent, #4a90e2); outline-offset:-2px; }
.prop-slide-pos{ position:absolute; z-index:2; right:6px; bottom:6px; padding:1px 6px; border-radius:9px; background:rgba(0,0,0,.55); color:#fff; font-size:11px; pointer-events:none; }
.prop-slide-cap{ position:absolute; z-index:2; left:6px; bottom:6px; max-width:60%; padding:1px 6px; border-radius:9px; background:rgba(0,0,0,.55); color:#fff; font-size:11px; line-height:1.4; pointer-events:none; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.prop-slide-cap[hidden]{ display:none; }
.prop-slide-more{ position:absolute; z-index:2; right:0; bottom:0; padding:3px 8px; border-radius:6px 0 0 0; background:rgba(0,0,0,.6); color:#fff; font-size:12px; pointer-events:none; }
.prop-slide-more[hidden]{ display:none; }
.prop-slide-arrow{ display:none; position:absolute; z-index:2; top:50%; transform:translateY(-50%); width:28px; height:44px; padding:0; border:none; background:rgba(0,0,0,.45); color:#fff; font-size:22px; line-height:1; cursor:pointer; align-items:center; justify-content:center; }
.prop-slide-arrow.prev{ left:0; border-radius:0 6px 6px 0; }
.prop-slide-arrow.next{ right:0; border-radius:6px 0 0 6px; }
.prop-slide-arrow[hidden]{ display:none !important; }
.prop-card-bars{ display:none; flex:0 0 100%; box-sizing:border-box; gap:3px; padding:0 10px; }
.prop-card-bars i{ flex:1 1 0; height:3px; border-radius:2px; background:var(--line); }
.prop-card-bars i.on{ background:var(--text, #ddd); }
.prop-card-strip .prj-row-thumb.cur{ outline:2px solid var(--accent, #4a90e2); outline-offset:-2px; }
/* мышь: вместо «2 / 7» - полоски по зонам, стрелки при наведении; касание: подпись «2 / 7», стрелок и полосок нет */
@media (pointer: fine) and (hover: hover){
  .prop-slide-pos{ display:none; }
  .prop-card-bars{ display:flex; }
  .prop-card-main:hover .prop-slide-arrow{ display:flex; }
}
.prop-card-none{ display:flex; align-items:center; justify-content:center; width:100%; height:100%; box-sizing:border-box; color:var(--dim); font-size:13px; }
.prop-card-strip{ flex:0 0 100%; box-sizing:border-box; display:flex; flex-wrap:nowrap; align-items:center; gap:4px; padding:0 10px; overflow:hidden; }
.prop-card-strip .prj-row-thumb{ width:40px; height:40px; flex:none; position:relative; cursor:zoom-in; }
.prop-card-strip .prj-row-thumb .prj-play{ font-size:14px; }
.prop-card-strip .prj-row-more{ cursor:zoom-in; font-size:12px; padding:0 6px; }
.prop-card-photo > .prj-row-docs, .prop-card-photo > .prj-row-voices{ margin-left:10px; }
.prop-card-body{ flex:1 1 auto; padding:6px 10px 10px; }
.prop-card .prop-edit, .prop-card .prop-own{ padding:0 10px 12px; }
.prop-card .prop-ed-v{ flex-basis:160px; }
/* «Также найдено в других категориях» */
.prop-out:empty{ display:none; }
.prop-out{ display:flex; flex-direction:column; gap:6px; min-width:0; padding-bottom:8px; }
.prop-out-head{ font-size:13px; padding-top:6px; border-top:1px solid var(--line); }
.prop-og{ border:1px solid var(--line-soft); min-width:0; }
.prop-og-head{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:6px 10px; padding:4px 6px; min-width:0; }
.prop-og-toggle{ flex:1 1 200px; min-width:0; display:flex; align-items:baseline; gap:8px; padding:6px 2px; background:none; border:none; color:var(--text); font:inherit; font-size:13px; text-align:left; cursor:pointer; }
.prop-og-path{ flex:1; min-width:0; overflow-wrap:anywhere; }
.prop-og-go{ font-size:12px; }
.prop-og-body{ display:flex; flex-direction:column; align-items:flex-start; gap:8px; padding:0 6px 8px; min-width:0; }
.prop-og-body .prop-item{ align-self:stretch; }
/* «Похоже на то, что вы ищете» (§108) */
.prop-sim:empty{ display:none; }
.prop-sim{ display:flex; flex-direction:column; align-items:stretch; gap:6px; min-width:0; padding-bottom:8px; }
.prop-sim-head{ font-size:13px; padding-top:6px; border-top:1px solid var(--line); }
.prop-sim-toggle{ display:flex; align-items:baseline; gap:8px; max-width:100%; padding:6px 2px; background:none; border:none; color:var(--text); font:inherit; font-size:13px; text-align:left; cursor:pointer; }
.prop-sim-body{ display:flex; flex-direction:column; align-items:flex-start; gap:8px; min-width:0; }
.prop-sim-item{ align-self:stretch; min-width:0; border-bottom:1px solid var(--line-soft); }
.prop-sim-item .prop-item{ border-bottom:none; }
.prop-sim-path{ font-size:12px; color:var(--dim); padding:2px 10px 0; overflow-wrap:anywhere; }
.prop-sim-why{ display:flex; flex-direction:column; gap:2px; padding:0 10px 8px; font-size:12px; color:var(--dim); min-width:0; overflow-wrap:anywhere; }
.prop-sim-l{ color:var(--text); }
.prop-sim-why mark{ background:var(--auto-bg); color:var(--text); border-bottom:1px solid var(--auto); padding:0 1px; }
.prop-sim-tag{ font-size:11px; color:var(--orange); border:1px solid var(--orange-dim); padding:0 4px; white-space:nowrap; }
@media (max-width:640px){
  #property-wrap{ padding:12px 10px; }
  /* Размер маленькой миниатюры - четверть ширины строки (страница увеличена на --ui-zoom), крупная в 1,5 раза больше;
     что не помещается в строку - переносится, горизонтальной прокрутки нет */
  .prop-photo{ --pp-u:min(88px, calc((100vw / var(--ui-zoom) - 80px) / 4)); }
}
/* ---------- ОКНО «ОБЪЕКТ» (objwin.js) ----------
   Широкий диалог на компьютере, на телефоне - на весь экран. Шапка с «Закрыть» и «Сохранить» прилипает к верху. */
.ow-backdrop{ padding:16px; }
.ow-dialog{ width:min(980px, 100%); box-sizing:border-box; padding:0 16px 16px; min-width:0; }
.ow-bar{ position:sticky; top:0; z-index:3; background:var(--panel); padding:12px 0 8px; display:flex; flex-wrap:wrap; align-items:center; gap:8px; border-bottom:1px solid var(--line-soft); }
.ow-title{ flex:1 1 0; min-width:0; font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ow-status{ flex:1 1 100%; font-size:11.5px; color:var(--dim); overflow-wrap:anywhere; }
.ow-status:empty{ display:none; }
.ow-status.warn{ color:var(--orange); }
.ow-busy .ow-body{ pointer-events:none; opacity:.6; }
.ow-notice{ margin-top:10px; padding:8px 10px; border:1px solid var(--orange); background:var(--orange-dim); font-size:12.5px; line-height:1.45; overflow-wrap:anywhere; }
.ow-notice ul{ margin:4px 0 6px; padding-left:18px; }
.ow-body{ display:flex; flex-direction:column; gap:16px; padding-top:12px; min-width:0; }
.ow-head{ display:grid; grid-template-columns:minmax(0, 1fr); gap:10px 16px; min-width:0; }
.ow-sec{ display:flex; flex-direction:column; gap:8px; min-width:0; }
.ow-title-line{ font-size:11px; letter-spacing:.5px; text-transform:uppercase; color:var(--dim); border-bottom:1px solid var(--line-soft); padding-bottom:4px; }
.ow-field{ display:flex; flex-direction:column; gap:4px; min-width:0; padding-bottom:8px; border-bottom:1px solid var(--line-soft); }
.ow-field.head{ border-bottom:none; padding-bottom:0; }
.ow-field.ev, .ow-field.weak{ padding-left:8px; box-shadow:inset 3px 0 0 var(--orange); }
.ow-field.weak{ box-shadow:inset 3px 0 0 var(--purple); }
.ow-field.ev > .ow-label{ color:var(--orange); }
.ow-field.weak > .ow-label{ color:var(--purple); }
/* «важные поля» (§88): пустое важное поле - красная рамка (токен --danger) и «!» с подсказкой; одно на все окна */
.imp-miss{ border:1px solid var(--danger); border-radius:8px; }
.imp-miss > .ow-label, .imp-miss > .prm-name, .imp-miss > .imp-lab{ color:var(--danger); }
.imp-bang{ display:inline-flex; align-items:center; justify-content:center; flex:none; width:16px; height:16px; border-radius:50%; background:var(--danger); color:#fff; font-size:11px; font-weight:700; line-height:1; text-transform:none; letter-spacing:0; }
.ow-field.imp-miss{ padding:6px 8px; }
.ow-warn-note{ font-size:12px; color:var(--danger); overflow-wrap:anywhere; }
.ow-label{ min-height:22px; font-size:10.5px; letter-spacing:.5px; text-transform:uppercase; color:var(--dim); display:flex; align-items:center; flex-wrap:wrap; gap:6px; overflow-wrap:anywhere; }
/* строка значения: поле и «×» рядом, дата записи - мелко под полем */
.ow-row{ display:grid; grid-template-columns:minmax(0, 1fr) auto; align-items:center; gap:2px 8px; min-width:0; }
.ow-row.sole{ grid-template-columns:minmax(0, 1fr); }
.ow-row + .ow-row{ margin-top:6px; }
.ow-row > .ow-val, .ow-row > .ow-gone{ grid-column:1; min-width:0; }
.ow-row > .ow-x, .ow-row > .ow-restore{ grid-column:2; grid-row:1; }
.ow-row > .ow-when{ grid-column:1; grid-row:2; justify-self:start; }
.ow-row > .ow-empty-note{ grid-column:1 / -1; }
.ow-val{ min-width:0; display:flex; align-items:center; flex-wrap:wrap; gap:6px; }
.ow-field > .ow-val{ flex:none; }
.ow-in{ width:100%; box-sizing:border-box; font-size:13px; padding:8px 10px; }
.ow-in.bad{ border-color:var(--red); }
.ow-pick{ max-width:100%; text-align:left; white-space:normal; overflow-wrap:anywhere; text-transform:none; letter-spacing:0; }
.ow-when{ font-size:10.5px; color:var(--dim); white-space:nowrap; text-transform:none; letter-spacing:0; }
.ow-x, .ow-add{ flex:none; width:28px; height:28px; padding:0; background:none; border:1px solid var(--line); color:var(--dim); font:inherit; font-size:16px; line-height:1; cursor:pointer; align-self:center; text-transform:none; }
.ow-x:hover{ color:var(--red); border-color:var(--red); }
.ow-add{ width:22px; height:22px; font-size:14px; }
.ow-add:hover{ color:var(--accent); border-color:var(--accent); }
.ow-empty-note{ font-size:11px; color:var(--red); }
.ow-empty-note[hidden]{ display:none; }
.ow-row.deleted .ow-gone{ text-decoration:line-through; color:var(--dim); overflow-wrap:anywhere; align-self:center; }
.ow-locked{ overflow-wrap:anywhere; }
.ow-note{ font-size:11.5px; color:var(--dim); overflow-wrap:anywhere; text-transform:none; letter-spacing:0; }
.ow-note.warn{ color:var(--orange); }
.ow-owner .tb-btn{ max-width:100%; white-space:normal; text-align:left; overflow-wrap:anywhere; }
.ow-dec-row{ display:flex; flex-wrap:wrap; gap:6px; }
.ow-dec{ font-size:12px; }
.ow-dec-our.on{ border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.10); }
.ow-dec-other.on, .ow-dec-gone.on{ border-color:var(--orange); color:var(--orange); background:var(--orange-dim); }
.ow-own-now{ font-size:12px; color:var(--dim); overflow-wrap:anywhere; text-transform:none; letter-spacing:0; }
.ow-own-now b{ color:var(--text); font-weight:600; }
.ow-own-edit{ text-transform:none; letter-spacing:0; background:none; border:none; padding:0 2px; color:var(--accent); text-decoration:underline; cursor:pointer; font:inherit; }
.ow-owner .ow-own-note{ font-size:13px; padding:7px 10px; box-sizing:border-box; width:100%; }
.ow-own-will{ font-size:11.5px; color:var(--dim); overflow-wrap:anywhere; }
.ow-own-will:empty{ display:none; }
.ow-files{ display:flex; flex-wrap:wrap; gap:8px; }
.ow-file{ position:relative; width:84px; height:84px; flex:none; }
.ow-file .prj-thumb, .ow-file .ow-voice, .ow-file > img{ width:100%; height:100%; box-sizing:border-box; }
.ow-file > img{ object-fit:cover; display:block; border:1px solid var(--line); }
.ow-file-x{ position:absolute; top:2px; right:2px; z-index:1; width:22px; height:22px; padding:0; border:none; border-radius:50%; background:rgba(0,0,0,.65); color:#fff; font-size:15px; line-height:22px; cursor:pointer; }
.ow-voice{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; border:1px solid var(--line); border-radius:0; background:var(--panel2); color:var(--text); font:inherit; font-size:11px; cursor:pointer; }
.ow-voice-ico, .ow-voice .prj-voice-ico{ font-size:22px; }
.ow-wait{ display:flex; align-items:center; justify-content:center; width:100%; height:100%; border:1px solid var(--line); background:var(--panel2); color:var(--dim); }
.ow-file.removed{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; border:1px dashed var(--line); font-size:11px; color:var(--dim); }
.ow-file.removed .tb-btn{ padding:2px 6px; font-size:11px; }
.ow-doc{ padding:4px; text-align:center; overflow-wrap:anywhere; }
.ow-file-btns{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.ow-file-pick{ cursor:pointer; }
.ow-fmsg:empty{ display:none; }
.ow-addbox{ display:flex; flex-direction:column; align-items:flex-start; gap:8px; }
.ow-addpanel{ width:100%; box-sizing:border-box; border:1px solid var(--line); background:var(--panel2); padding:8px; display:flex; flex-direction:column; gap:6px; }
.ow-addpanel[hidden]{ display:none; }
.ow-addpanel .tb-input{ font-size:13px; padding:8px 10px; box-sizing:border-box; width:100%; }
.ow-sub{ font-size:10.5px; letter-spacing:.5px; text-transform:uppercase; color:var(--dim); }
.ow-freq, .ow-found{ display:flex; flex-direction:column; max-height:220px; overflow:auto; }
.ow-below{ border-top:1px solid var(--line); padding-top:10px; gap:10px; }
.ow-links{ display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px; }
.ow-links .tb-btn{ text-decoration:none; }
/* Карточка существующего объекта (§78): фото сверху, поля текстом, ✎ у каждого */
.ow-hero{ position:relative; display:flex; flex-direction:column; flex:1 1 100%; gap:6px; min-width:0; }
.ow-hero-img{ display:flex; align-items:center; justify-content:center; min-height:120px; background:var(--panel2); border:1px solid var(--line); overflow:hidden; }
.ow-hero-img .prj-thumb{ display:flex; align-items:center; justify-content:center; width:100%; height:auto; min-height:120px; padding:0; background:none; border:none; cursor:zoom-in; }
.ow-hero-img .prj-thumb img, .ow-hero-img .prj-thumb video{ display:block; width:100%; height:auto; max-height:min(52vh, 440px); object-fit:contain; }
.ow-hero-step{ position:absolute; top:calc(50% - 28px); z-index:1; width:40px; height:40px; padding:0; border:none; border-radius:50%; background:rgba(0,0,0,.55); color:#fff; font-size:24px; line-height:40px; cursor:pointer; }
.ow-hero-step.prev{ left:6px; }
.ow-hero-step.next{ right:6px; }
.ow-hero-bar{ display:flex; align-items:center; justify-content:space-between; gap:8px; font-size:12px; color:var(--dim); }
.ow-hero-x{ background:none; border:1px solid var(--line); color:var(--dim); font:inherit; font-size:11.5px; padding:2px 8px; cursor:pointer; }
.ow-hero-x:hover{ color:var(--red); border-color:var(--red); }
.ow-strip{ flex:1 1 100%; margin-top:2px; }
.ow-main-star{ position:absolute; top:6px; left:6px; z-index:1; min-width:22px; height:22px; padding:0 4px; box-sizing:border-box; display:flex; align-items:center; justify-content:center; border-radius:11px; background:rgba(0,0,0,.55); color:#ffd54a; font-size:14px; line-height:1; pointer-events:none; }
.ow-hist-old{ display:block; font-size:12px; color:var(--dim); margin-top:2px; }
.ow-row.hist-old{ display:block; }
.ow-hist-note{ font-size:11.5px; margin-top:2px; }
.ow-name-main, .ow-cat-add{ background:none; border:1px solid var(--line); color:var(--dim); font:inherit; font-size:11.5px; padding:2px 8px; margin-left:6px; cursor:pointer; text-transform:none; letter-spacing:0; }
.ow-cat-block{ display:flex; flex-direction:column; gap:4px; min-width:0; }
.ow-cat-addrow{ margin:0; }
.ow-cat-add{ display:inline-block; margin:0; }
.ow-name-main:hover, .ow-name-main:focus-visible, .ow-cat-add:hover, .ow-cat-add:focus-visible{ color:var(--accent); border-color:var(--accent); }
.ow-cat-x{ background:none; border:1px solid var(--line); color:var(--dim); font:inherit; font-size:14px; line-height:1; width:24px; height:24px; padding:0; margin-left:6px; cursor:pointer; vertical-align:middle; }
.ow-cat-x:hover, .ow-cat-x:focus-visible{ color:var(--red); border-color:var(--red); }
.ow-rvs.multi .ow-rv.ow-cat-extra{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 6px; }
.ow-cat-extra .ow-rv-text{ flex:1 1 100%; }
.ow-cat-extra .ow-name-main, .ow-cat-extra .ow-cat-x{ margin-left:0; }
.ow-cat-tag{ font-size:10.5px; letter-spacing:.5px; text-transform:uppercase; color:var(--accent); margin-left:4px; }
.ow-card-line{ display:flex; align-items:flex-start; gap:8px; min-width:0; }
.ow-card-main{ flex:1 1 0; min-width:0; font-size:14px; line-height:1.45; overflow-wrap:anywhere; }
.ow-rl{ color:var(--dim); }
.ow-rv{ white-space:pre-wrap; overflow-wrap:anywhere; }
.ow-rvs.multi .ow-rv{ display:block; }
.ow-rv-none{ color:var(--dim); }
.ow-read .ow-when{ margin-left:4px; }
.ow-read.imp-miss .ow-rl{ color:var(--danger); }
.ow-pencil, .ow-ok, .ow-cancel{ flex:none; width:28px; height:28px; padding:0; background:none; border:1px solid var(--line); color:var(--dim); font:inherit; font-size:15px; line-height:1; cursor:pointer; text-transform:none; letter-spacing:0; }
.ow-pencil:hover, .ow-pencil:focus-visible{ color:var(--accent); border-color:var(--accent); }
.ow-ok{ color:var(--green); border-color:var(--green); }
.ow-ok:disabled{ opacity:.4; cursor:default; }
.ow-cancel:hover{ color:var(--red); border-color:var(--red); }
.ow-edit-btns{ margin-left:auto; display:inline-flex; gap:6px; }
/* мышь: ✎ появляется при наведении на поле (место под него занято, строки не прыгают); сенсорный экран - ✎ всегда; открытое поле - ✓ и ✕ всегда */
@media (hover: hover) and (pointer: fine){
  .ow-read .ow-pencil{ opacity:0; }
  .ow-read:hover .ow-pencil, .ow-read:focus-within .ow-pencil, .ow-pencil:focus-visible{ opacity:1; }
}
.ow-field.editing{ padding-left:8px; box-shadow:inset 3px 0 0 var(--accent); }
.ow-small{ font-size:11px; padding:2px 8px; opacity:.8; }
@media (min-width:700px){
  .ow-head{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
  .ow-head .ow-cat{ grid-column:1 / -1; }
}
@media (max-width:640px){
  .ow-backdrop{ padding:0; }
  .ow-dialog{ width:100%; margin:0; border-radius:0; border-left:none; border-right:none; padding:0 12px 16px; min-height:calc(100vh / var(--ui-zoom)); min-height:calc(100dvh / var(--ui-zoom)); }
  /* 14px при общем зуме 1.2 - больше 16: меньше этого Safari зумит страницу при фокусе */
  .ow-dialog .tb-input{ font-size:14px; }
}
/* Поле 209 «Объект проекта» (objlink.js): плитки в окне проекта, выбор объекта, раздел «Проекты» в окне «Объект» */
.ol-row{ align-items:stretch; }
.ol-tile{ flex:1; min-width:0; display:flex; align-items:flex-start; gap:10px; padding:6px 8px; box-sizing:border-box; text-align:left; font:inherit; color:var(--text); background:var(--panel2); border:1px solid var(--line); border-radius:6px; }
button.ol-tile{ cursor:pointer; }
button.ol-tile:hover{ border-color:var(--accent-dim); }
.ol-tile.is-cat{ border-style:dashed; }
.ol-thumb{ flex:none; width:56px; height:56px; border:1px solid var(--line); border-radius:4px; overflow:hidden; background:var(--panel); }
.ol-thumb img{ display:block; width:100%; height:100%; object-fit:cover; }
.ol-info{ flex:1; min-width:0; display:flex; flex-direction:column; gap:1px; }
.ol-name{ font-size:13px; line-height:1.35; overflow-wrap:anywhere; }
.ol-sub{ font-size:11px; line-height:1.35; overflow-wrap:anywhere; }
.ol-pick{ width:min(640px, 100%); }
.ol-pick .ol-list{ max-height:55vh; overflow-y:auto; display:flex; flex-direction:column; gap:2px; min-width:0; margin-top:8px; }
.ol-node{ padding-left:calc(var(--d, 0) * 12px); min-width:0; }
.ol-node-body{ display:flex; flex-direction:column; gap:2px; padding:2px 0 6px 12px; border-left:1px solid var(--line-soft); }
.ol-cat-btn{ display:flex; align-items:center; gap:6px; width:100%; padding:7px 6px; box-sizing:border-box; text-align:left; font:inherit; color:var(--text); background:none; border:none; border-radius:4px; cursor:pointer; }
.ol-cat-btn:hover{ background:rgba(127,127,127,0.12); }
.ol-caret{ flex:none; width:14px; color:var(--dim); }
.ol-cat-name{ flex:1; min-width:0; overflow-wrap:anywhere; }
.ol-pick-cat{ align-self:flex-start; max-width:100%; white-space:normal; text-align:left; font-size:12px; margin:2px 0 4px; }
.ol-found-cat{ display:flex; flex-direction:column; gap:2px; padding:6px 6px 8px; border-bottom:1px solid var(--line-soft); }
.ol-found-name{ overflow-wrap:anywhere; }
/* объект в выборе - строка «Имущества» (property.js), как во вкладке */
.ol-obj{ display:block; width:100%; box-sizing:border-box; min-width:0; }
.ol-obj.used{ opacity:.5; filter:grayscale(1); }
/* множественный выбор (§88): галочка слева от строки, отмеченная строка с рамкой */
.ol-multi-bar{ display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; }
.ol-obj.multi{ display:flex; align-items:flex-start; gap:8px; border:1px solid transparent; border-radius:6px; cursor:pointer; }
.ol-obj.multi.picked{ border-color:var(--accent); background:rgba(127,127,127,0.08); }
.ol-obj-row{ flex:1 1 0; min-width:0; }
.ol-check{ flex:none; display:inline-flex; align-items:center; justify-content:center; width:22px; height:22px; margin-top:8px; box-sizing:border-box; border:1px solid var(--dim); border-radius:4px; font-size:14px; line-height:1; color:var(--accent); }
.ol-obj.picked .ol-check{ border-color:var(--accent); }
.ol-obj.used .ol-check{ border-style:dashed; }
.ol-multi-msg{ flex:1 1 auto; min-width:0; font-size:12px; overflow-wrap:anywhere; }
.ol-busy .ol-list, .ol-busy .ol-multi-bar, .ol-busy .map-picker-search{ pointer-events:none; opacity:.6; }
.ol-obj.used .prop-row{ cursor:default; }
.ol-obj .ol-sub{ display:block; padding:0 4px 8px; }
.ol-wait{ padding:6px; }
.ol-more{ padding:6px; }
.ol-projects{ display:flex; flex-direction:column; gap:8px; min-width:0; margin-bottom:12px; }
.ol-head{ display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px; }
.ol-btns{ display:flex; align-items:center; flex-wrap:wrap; gap:6px; min-width:0; }
.ol-proj{ display:flex; align-items:center; flex-wrap:wrap; gap:8px; padding:6px 8px; border:1px solid var(--line); border-radius:6px; min-width:0; }
.ol-proj-main{ flex:1 1 200px; min-width:0; display:flex; flex-direction:column; gap:1px; }
.ol-proj-name{ align-self:flex-start; max-width:100%; padding:0; text-align:left; font:inherit; font-size:13px; color:var(--accent); background:none; border:none; cursor:pointer; overflow-wrap:anywhere; }
.ol-proj-go{ flex:none; }
.ol-msg:empty{ display:none; }
@media (max-width:640px){
  .ol-pick .ol-list{ max-height:60vh; }
  .ol-proj-go{ flex:1 1 auto; }
}
/* ---------- ВХОДЯЩИЕ ФАЙЛЫ (share.js): «Поделиться» из галереи Android ----------
   Диалог на компьютере, на весь экран на телефоне (как окно «Объект»). Файлы прокручиваются в своей области, поиск
   получает остальное место, «Добавить» всегда внизу. Высота делится на --ui-zoom: страница увеличена. */
.sh-backdrop{ padding:16px; }
.sh-dialog{ width:min(720px, 100%); box-sizing:border-box; padding:0 16px; min-width:0; display:flex; flex-direction:column; overflow:hidden;
  max-height:calc(100vh / var(--ui-zoom) - 32px); max-height:calc(100dvh / var(--ui-zoom) - 32px); }
.sh-bar{ flex:none; background:var(--panel); padding:12px 0 8px; display:flex; align-items:center; gap:8px; border-bottom:1px solid var(--line-soft); }
.sh-title{ flex:1 1 0; min-width:0; font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sh-tools{ flex:none; display:flex; align-items:center; justify-content:space-between; gap:8px; margin-top:10px; }
.sh-tools:empty{ display:none; }
.sh-scroll{ flex:0 1 auto; min-height:80px; margin-top:6px; overflow-y:auto; overscroll-behavior:contain; }
.sh-notes{ margin-top:8px; display:flex; flex-direction:column; align-items:flex-start; gap:6px; }
.sh-notes.hidden{ display:none; }
.sh-note{ max-width:100%; box-sizing:border-box; padding:6px 8px; border:1px solid var(--line); border-radius:6px; background:var(--panel2); overflow-wrap:anywhere; }
.sh-note a{ color:var(--accent); }
.sh-files{ display:flex; flex-direction:column; gap:6px; }
.sh-empty{ padding:8px 0; }
.sh-file{ display:flex; align-items:center; gap:8px; padding:6px; box-sizing:border-box; border:1px solid var(--line); border-radius:6px; background:var(--panel2); opacity:.7; }
.sh-file.on{ opacity:1; }
.sh-file.fail{ border-color:var(--red-dim); }
.sh-file.busy{ border-color:var(--accent); }
.sh-pick{ display:flex; align-items:center; gap:6px; flex:none; cursor:pointer; }
.sh-pick input{ width:18px; height:18px; margin:0; }
.sh-thumb{ position:relative; width:52px; height:52px; flex:none; border-radius:4px; overflow:hidden; background:var(--bg); border:1px solid var(--line-soft); display:flex; align-items:center; justify-content:center; }
.sh-thumb img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.sh-ico{ font-size:22px; line-height:1; }
.sh-file-info{ flex:1; min-width:0; display:flex; flex-direction:column; gap:1px; }
.sh-file-name{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.sh-file-meta{ font-size:10.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.sh-geo{ flex:none; margin-top:8px; padding:6px 8px; border:1px solid var(--orange); border-radius:6px; color:var(--orange); font-size:12px; overflow-wrap:anywhere; }
.sh-geo.hidden{ display:none; }
.sh-geo-tag{ display:inline-block; margin-top:2px; padding:0 6px; border:1px solid var(--orange); border-radius:8px; color:var(--orange); font-size:10.5px; white-space:nowrap; }
.sh-file-status{ font-size:11px; color:var(--accent); overflow-wrap:anywhere; }
.sh-file-status:empty{ display:none; }
.sh-file-status.err{ color:var(--red); }
.sh-file-btns{ flex:none; display:flex; flex-direction:column; gap:4px; }
.sh-file-btns .tb-btn{ font-size:11px; padding:4px 8px; }
.sh-where{ flex:0 1 auto; min-height:0; margin-top:10px; padding-top:10px; border-top:1px solid var(--line-soft); display:flex; flex-direction:column; gap:8px; }
.sh-where.searching{ flex:1 1 auto; min-height:210px; }
.sh-where.searching > [data-role="target"]{ flex:1; min-height:0; display:flex; flex-direction:column; gap:8px; }
.sh-label{ font-size:11px; color:var(--dim); }
.sh-q{ flex:none; width:100%; box-sizing:border-box; font-size:13px; padding:8px 10px; }
/* Переключатель видов, результаты и выбранное - строки самих вкладок (.prj-row, .prop-item): свои стили у них, здесь только раскладка */
.sh-modes{ flex:none; flex-wrap:nowrap; gap:4px; }
.sh-modes .tb-btn{ flex:1 1 auto; min-width:0; padding:6px 4px; font-size:11px; letter-spacing:0; }
.sh-hits{ flex:1 1 auto; min-height:60px; display:flex; flex-direction:column; gap:4px; overflow-y:auto; overscroll-behavior:contain; }
.sh-sec{ flex:none; min-width:0; }
.sh-sec-title{ font-size:11px; color:var(--dim); padding:6px 0 2px; }
.sh-list{ min-width:0; }
.sh-chosen{ display:flex; align-items:flex-start; gap:8px; padding:6px 8px; box-sizing:border-box; width:100%; min-width:0; background:var(--panel2); border:1px solid var(--line); border-radius:6px; }
.sh-chosen-row{ flex:1; min-width:0; max-height:42vh; overflow-y:auto; overscroll-behavior:contain; }
.sh-chosen .prj-row, .sh-chosen .prop-item{ border-bottom:none; width:100%; box-sizing:border-box; }
.sh-chosen .tb-btn{ flex:none; }
.sh-kind{ flex:none; font-size:10px; padding:1px 6px; border-radius:8px; border:1px solid var(--line); color:var(--dim); margin-top:10px; }
.sh-kind-prj{ color:var(--accent); border-color:var(--accent-dim); }
.sh-kind-obj{ color:var(--green); border-color:var(--green-dim); }
.sh-kind-ctc{ color:var(--orange); border-color:var(--orange); }
.sh-hint{ flex:none; padding:2px 0; }
.sh-new{ flex:none; display:flex; flex-wrap:wrap; gap:6px; }
.sh-newbtn{ flex:0 1 auto; max-width:100%; white-space:normal; text-align:left; font-size:11px; padding:6px 8px; }
.sh-result{ display:flex; align-items:center; justify-content:space-between; gap:8px; padding:8px; border:1px solid var(--green-dim); border-radius:6px; color:var(--green); }
.sh-result.hidden{ display:none; }
.sh-result.none{ border-color:var(--red-dim); color:var(--text); }
.sh-bad{ color:var(--red); }
.sh-foot{ flex:none; background:var(--panel); padding:10px 0 12px; margin-top:10px; display:flex; align-items:center; gap:8px; border-top:1px solid var(--line-soft); }
.sh-msg{ flex:1; min-width:0; overflow-wrap:anywhere; }
.sh-foot .tb-btn{ flex:none; }
.sh-foot .tb-btn:disabled{ opacity:.45; }
.sh-new-note{ padding:6px 8px; border:1px solid var(--accent-dim); border-radius:6px; color:var(--accent); font-size:11.5px; }
@media (max-width:640px){
  .sh-backdrop{ padding:0; }
  .sh-dialog{ width:100%; margin:0; border-radius:0; border-left:none; border-right:none; padding:0 12px; height:calc(100vh / var(--ui-zoom)); height:calc(100dvh / var(--ui-zoom)); max-height:none; }
  .sh-scroll{ max-height:42%; }
  .sh-dialog .tb-input{ font-size:14px; }
}
/* ---------- УТОЧНЕНИЯ И ЗАМЕТКИ (§98): параметр внутри параметра ----------
   В карточках - в скобках серым после значения (.prj-q); в списках - значки ⓘN и 📝 (.prj-qb); по ✎ - отдельными строками. */
.prj-q{ color:var(--dim); text-transform:none; letter-spacing:0; font-weight:400; font-style:normal; }
.prj-q .prj-q-item{ overflow-wrap:anywhere; }
.prj-q-cut, .prj-q-full{ font:inherit; color:inherit; }
.prj-q-cut{ background:none; border:0; padding:0; margin:0; text-align:left; cursor:pointer; text-decoration:underline dotted; text-underline-offset:2px; white-space:normal; }
.prj-q-cut:hover, .prj-q-cut:focus-visible{ color:var(--accent); }
.prj-q a, .prj-q .prm-link{ color:inherit; }
.prj-qb{ display:inline-block; vertical-align:middle; margin-left:4px; padding:1px 5px; border:1px solid var(--line); border-radius:8px; font-size:10.5px; line-height:1.3; color:var(--dim); white-space:nowrap; text-transform:none; letter-spacing:0; font-weight:400; cursor:help; }
.prm-name .prj-q{ font-size:11px; }
.prm-cap{ font-size:11px; line-height:1.3; max-width:160px; overflow-wrap:anywhere; white-space:normal; padding-top:2px; }
.prm-qrow{ align-items:flex-start; flex-wrap:wrap; }
.prm-qrow .prm-qlabel{ color:var(--dim); font-size:11.5px; }
.prm-group.qedit{ box-shadow:inset 3px 0 0 var(--accent); padding-left:8px; }
.ow-q{ margin-left:calc(var(--qd, 1) * 12px); padding-left:8px; border-left:2px solid var(--line-soft); display:flex; flex-direction:column; gap:3px; margin-top:6px; min-width:0; }
.ow-ql{ font-size:10.5px; letter-spacing:.3px; color:var(--dim); overflow-wrap:anywhere; }
.ow-qadd-row{ margin-top:4px; }
.ow-qadd{ background:none; border:1px dashed var(--line); color:var(--dim); font:inherit; font-size:12px; line-height:1.2; padding:3px 8px; cursor:pointer; text-transform:none; letter-spacing:0; }
.ow-qadd:hover, .ow-qadd:focus-visible{ color:var(--accent); border-color:var(--accent); }
.ow-notes{ margin-top:8px; display:flex; flex-direction:column; gap:3px; min-width:0; }
.ow-hero-cap{ font-size:12px; line-height:1.35; text-align:center; overflow-wrap:anywhere; margin-top:2px; }
/* Перетаскивание файлов в «Альбом» (§100) */
.drop-overlay{ zoom:calc(1 / var(--ui-zoom)); position:fixed; z-index:10050; pointer-events:none; box-sizing:border-box; display:flex; align-items:center; justify-content:center; padding:12px; text-align:center; border:3px dashed var(--accent); background:color-mix(in srgb, var(--panel) 75%, transparent); color:var(--text); font-size:16px; font-weight:600; overflow:hidden; }
.drop-overlay[hidden]{ display:none; }
.drop-toast{ position:fixed; z-index:10050; left:50%; bottom:16px; transform:translateX(-50%); max-width:calc(100vw - 32px); padding:8px 14px; background:var(--panel); color:var(--text); border:1px solid var(--line); font-size:13px; overflow-wrap:anywhere; }
.drop-toast[hidden]{ display:none; }
/* §113: ход проверки на дубли вне окна «Файлы» - «Проверяю файлы 3 из 12» и «Отмена» */
.dg-prog{ position:fixed; z-index:10080; left:50%; bottom:16px; transform:translateX(-50%); max-width:calc(100vw - 32px); box-sizing:border-box; display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:8px 14px; background:var(--panel); color:var(--text); border:1px solid var(--line); font-size:13px; overflow-wrap:anywhere; }
.dg-prog .tb-btn{ text-transform:none; letter-spacing:0; font-size:13px; padding:5px 10px; }
.dg-modal{ z-index:10075; }
/* Комментарии к фото, дата снимка и «О файле» (§102, filemeta.js) */
.prj-viewer-fm{ flex:none; max-height:34vh; overflow-y:auto; color:rgb(219, 230, 239); text-align:center; padding:0 6px; }
.fm-host{ font-size:13px; line-height:1.35; min-width:0; }
.fm-host .fm-date{ display:flex; justify-content:center; align-items:center; flex-wrap:wrap; gap:2px 6px; }
.fm-date-text{ overflow-wrap:anywhere; }
.fm-btn{ background:none; border:0; color:inherit; font:inherit; cursor:pointer; padding:4px 8px; min-width:32px; min-height:32px; line-height:1; opacity:.85; }
.fm-btn:hover, .fm-btn:focus-visible{ opacity:1; color:var(--accent); }
.fm-rows{ display:flex; flex-direction:column; align-items:center; gap:1px; margin-top:2px; }
.fm-q{ display:flex; align-items:center; justify-content:center; gap:0; max-width:100%; }
.fm-q-text{ overflow-wrap:anywhere; min-width:0; }
.fm-actions{ margin-top:4px; }
.fm-add{ background:none; border:1px dashed currentColor; color:inherit; font:inherit; font-size:12px; line-height:1.2; padding:5px 10px; cursor:pointer; opacity:.85; }
.fm-add:hover, .fm-add:focus-visible{ color:var(--accent); border-color:var(--accent); opacity:1; }
.fm-edit{ display:flex; flex-direction:column; align-items:stretch; gap:6px; margin:6px auto 0; max-width:520px; text-align:left; }
.fm-edit .tb-input{ width:100%; box-sizing:border-box; font-size:16px; }
.fm-edit-label{ font-size:12px; opacity:.8; }
.fm-edit-btns{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.fm-link{ background:none; border:0; padding:2px 0; color:var(--accent); font:inherit; font-size:12px; text-decoration:underline; cursor:pointer; }
.fm-msg{ margin-top:4px; font-size:12px; overflow-wrap:anywhere; }
.fm-msg:empty{ display:none; }
.ow-hero.fixed .ow-hero-img{ height:min(52vh, 440px); }
.ow-hero.fixed .ow-hero-img .prj-thumb{ height:100%; }
.ow-hero.fixed .ow-hero-img .prj-thumb img, .ow-hero.fixed .ow-hero-img .prj-thumb video{ height:100%; max-height:none; }
.ow-thumbs{ display:flex; gap:6px; flex:1 1 100%; min-width:0; max-width:100%; overflow-x:auto; overflow-y:hidden; padding:3px 1px; -webkit-overflow-scrolling:touch; scrollbar-width:thin; box-sizing:border-box; }
.ow-th{ position:relative; flex:none; width:80px; height:80px; padding:0; box-sizing:border-box; display:flex; align-items:center; justify-content:center; overflow:hidden; border:2px solid transparent; background:var(--panel2); color:var(--dim); font-size:22px; cursor:pointer; opacity:.8; }
.ow-th img{ width:100%; height:100%; object-fit:cover; display:block; }
.ow-th.cur{ border-color:var(--accent); opacity:1; }
@media (max-width:640px){ .ow-th{ width:56px; height:56px; font-size:18px; } }
.ow-mk{ position:absolute; left:2px; bottom:2px; z-index:1; font-size:13px; line-height:1; padding:2px 3px; border-radius:3px; background:var(--panel); color:var(--text); border:1px solid var(--line); pointer-events:none; }
.ow-mk.none{ opacity:.85; }
.ow-mark-bar{ flex:1 1 100%; margin-bottom:6px; }
.ow-mark-btn{ min-height:40px; }
.fm-mark{ margin-top:4px; }
.fm-mark-cap{ font-size:12px; opacity:.8; margin-bottom:3px; }
.fm-mark-ro .fm-mark-cap{ display:inline; margin:0; }
.fm-chips{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; margin-top:3px; }
.fm-chip{ background:none; border:1px solid var(--line); color:inherit; font:inherit; font-size:13px; line-height:1.2; padding:8px 12px; min-height:40px; box-sizing:border-box; cursor:pointer; border-radius:16px; max-width:100%; }
.fm-chip:hover, .fm-chip:focus-visible{ border-color:var(--accent); }
.fm-chip.on{ background:var(--accent); border-color:var(--accent); color:var(--bg); }
.fm-chip:disabled{ opacity:.6; cursor:default; }
.fm-more{ background:none; border:0; color:inherit; font:inherit; font-size:11px; padding:8px 6px; min-height:40px; opacity:.75; cursor:pointer; }
.fm-more:hover, .fm-more:focus-visible{ color:var(--accent); opacity:1; }
.ow-hero-fm{ color:var(--dim); text-align:center; margin-top:2px; align-self:stretch; width:100%; box-sizing:border-box; }
.fm-info{ position:fixed; inset:0; z-index:10060; background:rgba(0,0,0,0.6); zoom:calc(1 / var(--ui-zoom)); display:flex; align-items:center; justify-content:center; padding:10px; box-sizing:border-box; }
.fm-info-box{ position:relative; background:var(--panel); color:var(--text); border:1px solid var(--line); width:100%; max-width:600px; max-height:100%; overflow-y:auto; padding:12px; box-sizing:border-box; font-size:14px; }
.fm-info-head{ display:flex; align-items:center; justify-content:space-between; gap:8px; position:sticky; top:-12px; margin:-12px -12px 6px; padding:12px 12px 6px; background:var(--panel); z-index:1; }
.fm-info-head h3{ margin:0; font-size:16px; }
.fm-info-x{ width:40px; height:40px; padding:0; font-size:18px; flex:none; }
.fm-table{ width:100%; border-collapse:collapse; table-layout:fixed; }
.fm-table th, .fm-table td{ text-align:left; vertical-align:top; padding:3px 6px 3px 0; border-bottom:1px solid var(--line); overflow-wrap:anywhere; word-break:break-word; }
.fm-table th{ width:38%; font-weight:600; color:var(--dim); }
.fm-info-none{ color:var(--dim); padding:8px 0; overflow-wrap:anywhere; }
.fm-info-foot{ margin-top:10px; display:flex; justify-content:center; }
.fm-all-head{ margin:10px 0 4px; }
.fm-block{ margin-top:10px; }
.fm-block h4{ margin:0 0 4px; font-size:13px; text-transform:none; }
.fm-block-n{ color:var(--dim); font-weight:400; }
.prj-viewer ~ .map-picker-backdrop{ z-index:10070; }
/* ===== Заметки (notes.js): список, экран заметки, просмотр с комментариями к снимку, очередь отправки (outbox.js), «В новую заметку» из «Поделиться» ===== */
.nt-wrap{ display:flex; flex-direction:column; gap:10px; max-width:760px; margin:0 auto; padding:10px 12px calc(76px + env(safe-area-inset-bottom)); box-sizing:border-box; width:100%; min-width:0; }
.nt-head{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.nt-new{ font-size:15px; padding:10px 16px; }
.nt-seg{ display:flex; gap:0; margin-left:auto; }
.nt-seg .tb-btn{ border-radius:0; }
.nt-seg .tb-btn.on{ border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.10); font-weight:600; }
.nt-queue{ display:block; width:100%; text-align:left; padding:10px 12px; background:var(--orange-dim); border:1px solid var(--orange); color:var(--orange); font:inherit; font-size:13.5px; cursor:pointer; }
.nt-queue.bad{ background:var(--red-dim); border-color:var(--red); color:var(--red); }
.nt-msg{ min-height:0; font-size:12.5px; line-height:1.4; color:var(--dim); }
.nt-msg:empty{ display:none; }
.nt-bad{ color:var(--red); font-size:13px; line-height:1.4; }
.nt-empty{ color:var(--dim); font-size:13.5px; padding:18px 4px; line-height:1.5; }
.nt-list{ display:flex; flex-direction:column; gap:8px; }
.nt-row{ display:flex; flex-direction:column; align-items:stretch; gap:6px; text-align:left; width:100%; padding:10px 12px; background:var(--panel2); border:1px solid var(--line); color:var(--text); font:inherit; cursor:pointer; min-width:0; }
.nt-row.nt-all-done{ opacity:.6; }
.nt-rh{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 10px; font-size:13.5px; }
.nt-who{ color:var(--dim); font-size:12.5px; }
.nt-clock{ margin-left:auto; }
.nt-lts{ display:flex; gap:6px; overflow:hidden; }
.nt-lt{ width:56px; height:56px; flex:none; display:flex; align-items:center; justify-content:center; overflow:hidden; background:var(--bg); border:1px solid var(--line); font-size:20px; }
.nt-lt img{ width:100%; height:100%; object-fit:cover; display:block; }
.nt-first{ font-size:14px; line-height:1.4; overflow-wrap:anywhere; }
.nt-prog{ font-size:12px; color:var(--dim); }
.nt-more{ align-self:center; }
.nt-top{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.nt-sp{ flex:1; }
.nt-top .nt-queue{ width:auto; padding:6px 10px; }
.nt-prev{ display:block; width:100%; text-align:left; padding:10px 12px; background:rgba(52,213,255,0.08); border:1px solid var(--accent); color:var(--accent); font:inherit; font-size:14px; cursor:pointer; }
.nt-prev[hidden]{ display:none; }
.nt-feed{ display:flex; flex-direction:column; gap:8px; min-width:0; }
.nt-piece{ background:var(--panel2); border:1px solid var(--line); padding:8px 10px; display:flex; flex-direction:column; gap:6px; min-width:0; }
.nt-piece.nt-done{ opacity:.55; }
.nt-piece.st-err{ border-color:var(--red); }
.nt-pmeta{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 10px; font-size:12.5px; color:var(--dim); }
.nt-st{ font-size:14px; }
.nt-geo{ font-size:11.5px; }
.nt-badge{ padding:0 6px; background:var(--bg); border:1px solid var(--line); font-size:12px; color:var(--text); }
.nt-retry{ font-size:12px; padding:4px 8px; }
.nt-chk{ width:22px; height:22px; flex:none; }
.nt-ptext{ font-size:15px; line-height:1.45; white-space:pre-wrap; overflow-wrap:anywhere; }
.nt-pbody{ display:flex; flex-wrap:wrap; gap:6px; min-width:0; }
.nt-tile{ width:120px; height:120px; display:flex; align-items:center; justify-content:center; overflow:hidden; padding:0; background:var(--bg); border:1px solid var(--line); color:var(--dim); font:inherit; font-size:12px; cursor:zoom-in; position:relative; }
.nt-tile img, .nt-tile video{ width:100%; height:100%; object-fit:cover; display:block; }
.nt-tile.nt-file{ width:auto; max-width:100%; min-height:44px; height:auto; padding:6px 10px; cursor:default; }
.nt-pcomm{ display:flex; flex-direction:column; gap:4px; padding-left:10px; border-left:2px solid var(--line); }
.nt-comm{ font-size:13.5px; line-height:1.4; display:flex; flex-wrap:wrap; align-items:center; gap:4px 8px; overflow-wrap:anywhere; }
.nt-comm time{ font-size:11.5px; color:var(--dim); }
.nt-target{ display:flex; align-items:center; gap:6px; }
.nt-tlink{ background:none; border:0; padding:4px 0; color:var(--accent); font:inherit; font-size:13px; cursor:pointer; text-align:left; overflow-wrap:anywhere; }
.nt-tx{ flex:none; width:32px; height:32px; padding:0; background:none; border:1px solid var(--line); color:var(--dim); cursor:pointer; }
.nt-input{ display:flex; flex-direction:column; gap:8px; }
/* кнопки и поле остаются у нижнего края, пока лента длинная (над нижней панелью приложения); на низком экране (телефон лёжа) - обычным блоком */
@media (min-height:640px){
  .nt-screen .nt-input{ position:sticky; bottom:calc(54px + env(safe-area-inset-bottom)); z-index:2; background:var(--bg); padding:8px 0 4px; border-top:1px solid var(--line-soft); }
}
.nt-input[hidden], .nt-parsebar[hidden]{ display:none; }
.nt-btns{ display:grid; grid-template-columns:repeat(3, 1fr); gap:8px; }
.nt-fbtn{ display:flex; align-items:center; justify-content:center; min-height:48px; font-size:14px; cursor:pointer; text-align:center; }
.nt-voice{ min-height:60px; font-size:20px; }
.nt-text{ width:100%; box-sizing:border-box; resize:vertical; font-size:16px; }
.nt-save{ min-height:48px; font-size:16px; }
.nt-parsebar{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.nt-parse-go{ min-height:44px; }
.nt-need{ font-size:12.5px; color:var(--dim); }
.nt-parse-n{ font-size:13px; color:var(--dim); }
.nt-vbar{ flex:none; display:flex; flex-direction:column; gap:6px; max-height:44vh; overflow-y:auto; color:var(--text); }
.nt-vbar .nt-comm{ justify-content:center; }
.nt-vbar .prj-thumb{ width:64px; height:64px; }
.nt-vbtns{ display:flex; justify-content:center; gap:8px; }
.nt-vbtns .tb-btn{ min-height:44px; padding:8px 16px; }
.nt-vedit{ display:flex; flex-direction:column; gap:6px; }
.nt-vedit textarea{ width:100%; box-sizing:border-box; font-size:16px; }
.nt-vedit .tb-btn{ min-height:40px; }
.nt-qback{ z-index:10080; }
.nt-qdlg{ max-height:86vh; display:flex; flex-direction:column; gap:8px; }
.nt-qinfo{ font-size:12.5px; color:var(--dim); line-height:1.4; }
.nt-qlist{ overflow-y:auto; display:flex; flex-direction:column; gap:6px; min-height:0; }
.nt-qop{ display:flex; align-items:center; justify-content:space-between; gap:8px; padding:6px 8px; border:1px solid var(--line); font-size:13px; }
.nt-qop.bad{ border-color:var(--red); }
.nt-qop small{ color:var(--dim); overflow-wrap:anywhere; }
.sh-tonote{ flex:none; margin-top:10px; padding-top:10px; border-top:1px solid var(--line-soft); display:flex; flex-direction:column; gap:6px; }
.sh-note-btn{ min-height:48px; font-size:15px; }
.sh-note-hint{ font-size:12px; line-height:1.4; }
.sh-or{ flex:none; margin-top:12px; font-size:12.5px; color:var(--dim); }
@media (max-width:640px){
  .nt-tile{ width:calc(50% - 4px); height:auto; aspect-ratio:1; }
  .nt-btns .nt-fbtn{ padding:6px 4px; font-size:13px; }
}
/* «Продажи»: воронка подготовки товара (журнал §106) - лента шагов, «Что сделать», дни на шаге, «Фильтры (N)» */
.prop-steps{ display:flex; gap:6px; overflow-x:auto; max-width:100%; padding-bottom:4px; -webkit-overflow-scrolling:touch; }
.prop-steps[hidden]{ display:none; }
.prop-step{ flex:0 0 auto; white-space:nowrap; font-size:12.5px; padding:6px 10px; }
.prop-step.on{ border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.10); font-weight:600; }
.prop-step-n{ display:inline-block; min-width:16px; padding:0 3px; border-radius:8px; background:var(--panel2); color:var(--dim); font-size:11px; line-height:16px; text-align:center; font-weight:600; }
.prop-step.on .prop-step-n{ background:var(--accent); color:var(--bg); }
.sf-head{ display:flex; flex-wrap:wrap; align-items:center; gap:2px 8px; font-size:12px; margin-top:2px; }
.sf-step{ font-weight:600; color:var(--accent); }
.sf-days{ color:var(--dim); }
.sf-days.late{ color:var(--red); font-weight:600; }
.sf-head .sf-also{ margin-left:0; color:var(--green); border-color:var(--green); }
.sf-todo{ display:block; font-size:15px; line-height:1.35; margin:4px 0 2px; overflow-wrap:anywhere; }
.sf-todo b{ font-weight:700; }
.sf-actions .prop-ed-v{ display:flex; flex-wrap:wrap; gap:6px; }
.prop-fbtn{ font-size:12px; padding:5px 10px; }
.prop-factive, .prop-fpanel{ flex:1 0 100%; display:flex; flex-wrap:wrap; gap:6px; min-width:0; }
.prop-fon{ border-color:var(--accent); color:var(--accent); background:rgba(52,213,255,0.08); max-width:100%; white-space:normal; text-align:left; overflow-wrap:anywhere; }
.prop-fpanel{ padding:8px; border:1px solid var(--line); background:var(--panel); align-items:center; }
@media (min-width:900px){ .prop-steps{ flex-wrap:wrap; overflow-x:visible; } }

/* ---------- Файлы списком (files.js) ----------
   Окно поверх окна «Объект»: поиск, кнопки действий, таблица с выбираемыми колонками, выделение строк, итог внизу.
   Таблица (компьютер): сетка из колонок --fl-grid (ширины задаёт files.js), шапка прилипает сверху, прокручивается вся область.
   Телефон (< 700px): карточка строки - миниатюра слева, имя крупно, под ним мелкой строкой остальные включённые колонки. */
.ow-title-line{ display:flex; align-items:center; justify-content:space-between; gap:8px; }
.ow-title-line .ow-files-list{ text-transform:none; letter-spacing:0; font-size:13px; margin-left:auto; }
.ow-files-list[hidden]{ display:none; }
.fl-back{ position:fixed; inset:0; z-index:10040; background:rgba(0,0,0,0.6); zoom:calc(1 / var(--ui-zoom)); display:flex; align-items:center; justify-content:center; padding:10px; box-sizing:border-box; }
.fl-back ~ .prj-viewer{ z-index:10045; }   /* просмотр из окна файлов - поверх него */
.fl-box{ background:var(--panel); color:var(--text); border:1px solid var(--line); width:100%; max-width:1200px; max-height:100%; height:min(760px, 100%); display:flex; flex-direction:column; padding:12px; box-sizing:border-box; font-size:14px; min-width:0; }
.fl-head{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:8px; }
.fl-head h3{ margin:0; font-size:15px; }
.fl-bar{ display:flex; align-items:center; gap:10px; margin-bottom:6px; min-width:0; }
.fl-search{ position:relative; flex:1 1 auto; max-width:420px; min-width:0; }
.fl-q{ width:100%; box-sizing:border-box; background:var(--panel2); border:1px solid var(--line); color:var(--text); font-family:inherit; font-size:14px; padding:6px 30px 6px 8px; }
.fl-qx{ position:absolute; right:2px; top:50%; transform:translateY(-50%); padding:3px 7px; }
.fl-qx[hidden]{ display:none; }
.fl-shown{ color:var(--dim); font-size:13px; white-space:nowrap; }
.fl-acts{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-bottom:6px; }
.fl-acts .tb-btn, .fl-chips .tb-btn, .fl-pop .tb-btn, .fl-task .tb-btn, .fl-msg .tb-btn{ text-transform:none; letter-spacing:0; font-size:13px; padding:5px 10px; }
.fl-acts .tb-btn:disabled{ opacity:.45; cursor:default; }
.fl-acts .tb-btn:disabled:hover{ border-color:var(--line); color:var(--dim); }
.fl-pop-wrap{ position:relative; display:inline-block; }
.fl-pop{ position:absolute; z-index:6; top:calc(100% + 2px); right:0; min-width:220px; max-width:min(340px, calc(100vw - 24px)); max-height:min(420px, 60vh); overflow-y:auto; background:var(--panel); border:1px solid var(--line); box-shadow:0 6px 18px rgba(0,0,0,.45); padding:6px 8px; box-sizing:border-box; }
.fl-pop[hidden]{ display:none; }
.fl-pop-h{ font-size:11px; letter-spacing:.5px; text-transform:uppercase; color:var(--dim); margin:6px 0 2px; }
.fl-pop-i{ display:flex; align-items:center; gap:6px; padding:3px 0; font-size:14px; cursor:pointer; }
.fl-sortrow{ justify-content:space-between; cursor:default; }
.fl-reset{ margin-top:8px; }
.fl-only-narrow{ display:none; }
.fl-chips{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:6px; }
.fl-chips[hidden], .fl-msg[hidden]{ display:none; }
.fl-chip b{ color:var(--text); margin-left:2px; }
.fl-chip.active b{ color:var(--accent); }
.fl-tasks:empty{ display:none; }
.fl-task{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; font-size:13px; color:var(--dim); margin-bottom:4px; }
.fl-msg{ display:flex; align-items:flex-start; justify-content:space-between; gap:8px; font-size:13px; border:1px solid var(--line); background:var(--panel2); padding:6px 8px; margin-bottom:6px; overflow-wrap:anywhere; max-height:30vh; overflow-y:auto; }
.fl-scroll{ flex:1 1 auto; min-height:0; overflow:auto; border-top:1px solid var(--line-soft); }
.fl-inner{ min-width:var(--fl-min, 0); }
.fl-cols, .fl-row{ display:grid; grid-template-columns:var(--fl-grid, 140px minmax(0, 1fr) 70px 90px); gap:0 10px; align-items:center; padding:4px 8px; box-sizing:border-box; }
.fl-cols{ position:sticky; top:0; z-index:3; background:var(--panel); font-size:11px; letter-spacing:.5px; text-transform:uppercase; color:var(--dim); border-bottom:1px solid var(--line-soft); }
.fl-hc{ position:relative; display:flex; align-items:center; gap:3px; min-width:0; padding:3px 0; cursor:pointer; -webkit-user-select:none; user-select:none; outline:none; }
.fl-hc:hover, .fl-hc:focus-visible{ color:var(--accent); }
.fl-hc[data-fixed]{ cursor:default; }
.fl-hc.r{ justify-content:flex-end; }
.fl-ht{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.fl-ar{ color:var(--accent); white-space:nowrap; flex:none; }
.fl-ar sub{ font-size:9px; }
.fl-rs{ position:absolute; right:-7px; top:0; bottom:0; width:10px; cursor:col-resize; z-index:1; }
.fl-rs:hover{ background:linear-gradient(to right, transparent 4px, var(--accent) 4px, var(--accent) 6px, transparent 6px); }
.fl-hc-drag{ opacity:.5; }
.fl-drop-b{ box-shadow:-3px 0 0 var(--accent); }
.fl-drop-a{ box-shadow:3px 0 0 var(--accent); }
.fl-list{ outline:none; -webkit-user-select:none; user-select:none; }
.fl-row{ cursor:default; border-bottom:1px solid var(--line-soft); min-height:30px; }
.fl-row.fl-dir{ background:rgba(128,128,128,.13); color:var(--dim); }
.fl-row.sel{ background:rgba(80,140,255,.28); }
.fl-c{ min-width:0; }
.fl-name{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.fl-comment, .fl-cam, .fl-lens, .fl-by, .fl-field, .fl-gps, .fl-md5, .fl-cmp, .fl-shot{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.fl-gray{ color:var(--dim); }
.fl-date, .fl-type, .fl-size, .fl-mod, .fl-shot, .fl-id, .fl-iso{ white-space:nowrap; font-variant-numeric:tabular-nums; }
.fl-size, .fl-id, .fl-iso{ text-align:right; }
.fl-md5{ font-family:ui-monospace, Menlo, Consolas, monospace; font-size:12px; }
.fl-cmp-have{ color:var(--green); }
.fl-cmp-like{ color:var(--orange); }
.fl-cmp-fresh{ color:var(--accent); }
.fl-cmp-gone{ color:var(--pink); }
.fl-thumb{ display:flex; }
.fl-th{ width:48px; height:36px; display:flex; align-items:center; justify-content:center; background:var(--panel2); overflow:hidden; flex:none; }
.fl-th img{ width:100%; height:100%; object-fit:cover; display:block; }
.fl-ico{ font-size:11px; font-weight:700; color:var(--dim); letter-spacing:.3px; }
.fl-ico-v{ font-size:18px; }
.fl-foot{ margin-top:8px; font-size:13px; }
.fl-types{ color:var(--dim); font-size:12px; margin-top:2px; overflow-wrap:anywhere; }
.fl-types:empty{ display:none; }
.fl-note{ color:var(--dim); font-size:12px; margin-top:2px; }
.fl-note:empty{ display:none; }
.fl-acts .tb-btn[hidden]{ display:none; }
.fl-fails{ border-color:var(--red-dim); }
/* §110: окна поверх окна файлов - вопрос, выбор объекта для переноса, совпадения при добавлении */
.fl-back ~ .map-picker-backdrop{ z-index:10055; }
.fl-back ~ .map-picker-backdrop .prj-ask-text{ white-space:pre-line; max-height:55vh; overflow:auto; }
.fl-dlg{ width:min(780px, 100%); box-sizing:border-box; display:flex; flex-direction:column; max-height:calc(100vh - 32px); font-family:inherit; font-size:14px; }
.fl-dlg-bar{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:8px; }
.fl-dlg .tb-btn{ text-transform:none; letter-spacing:0; font-size:13px; padding:5px 10px; }
.fl-dlg-note{ font-size:12px; margin-bottom:8px; }
.fl-dups-list{ flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain; display:flex; flex-direction:column; gap:8px; }
.fl-dup{ border:1px solid var(--line); background:var(--panel2); padding:8px; display:flex; flex-direction:column; gap:6px; }
.fl-dup.done{ opacity:.6; }
.fl-dup-st{ font-size:12px; font-weight:700; }
.fl-dup-same{ color:var(--red); }
.fl-dup-like{ color:var(--orange); }
.fl-dup-pair{ display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); gap:8px; }
.fl-dup-side{ min-width:0; }
.fl-dup-h{ font-size:11px; color:var(--dim); text-transform:uppercase; letter-spacing:.4px; margin-bottom:2px; }
.fl-dup-body{ display:flex; gap:8px; align-items:flex-start; }
.fl-dup-body .fl-th{ width:56px; height:42px; }
.fl-dup-txt{ min-width:0; }
.fl-dup-name{ overflow-wrap:anywhere; }
.fl-dup-meta{ font-size:12px; color:var(--dim); overflow-wrap:anywhere; }
.fl-dup-btns{ display:flex; flex-wrap:wrap; gap:6px; }
.fl-dup-res{ font-size:13px; color:var(--dim); }
.fl-dlg-foot{ display:flex; flex-wrap:wrap; gap:8px; justify-content:flex-end; margin-top:10px; padding-top:8px; border-top:1px solid var(--line-soft); }
.fl-pick .sh-where{ border-top:none; margin-top:0; padding-top:0; min-height:260px; }
.fl-pick .sh-hits{ max-height:55vh; }
@media (max-width:699px){
  .fl-back{ padding:0; }
  .fl-box{ height:100%; max-width:none; border-left:none; border-right:none; }
  .fl-only-narrow{ display:inline-block; }
  .fl-bar{ flex-wrap:wrap; gap:4px 10px; }
  .fl-search{ max-width:none; flex:1 1 100%; }
  .fl-inner{ min-width:0; }
  .fl-scroll{ overflow-x:hidden; }
  .fl-cols{ display:none; }
  .fl-row{ display:flex; align-items:flex-start; gap:8px; padding:8px; }
  .fl-row .fl-thumb{ flex:none; }
  .fl-main{ flex:1 1 auto; min-width:0; }
  .fl-row .fl-name{ display:block; font-size:15px; white-space:normal; overflow-wrap:anywhere; }   /* имя целиком: при сверке с папкой важен конец имени */
  .fl-row .fl-cmp{ display:inline-block; font-size:12px; font-weight:700; margin-bottom:2px; }
  .fl-sub{ display:flex; flex-wrap:wrap; gap:2px 10px; margin-top:2px; font-size:12px; color:var(--dim); }
  .fl-sub .fl-c{ min-width:0; white-space:normal; overflow-wrap:anywhere; text-align:left; }
  .fl-sub i{ font-style:normal; opacity:.75; }
  .fl-acts{ position:relative; }
  .fl-pop-wrap{ position:static; }
  .fl-pop{ left:0; right:0; max-width:none; }   /* списки колонок и сортировки - во всю ширину под кнопками */
  .fl-dup-pair{ grid-template-columns:minmax(0, 1fr); }
  .fl-back ~ .map-picker-backdrop{ padding:8px; }
  .fl-dlg{ max-height:calc(100vh - 16px); }
}

/* ---------- ВКЛАДКА «МЕСТА» (places.js) ----------
   На компьютере слева дерево, справа панель места; на телефоне (и в разделённом экране) - что-то одно: дерево, а после нажатия на место - его панель с «‹ Назад». */
#places-wrap{ gap:12px; max-width:1200px; width:100%; margin:0 auto; box-sizing:border-box; }
.pl-wrap{ display:flex; flex-direction:column; gap:10px; min-width:0; }
.pl-bar{ display:flex; flex-wrap:wrap; gap:8px; }
.pl-bar .tb-input{ flex:1 1 140px; width:auto; min-width:0; font-size:13px; padding:8px 10px; box-sizing:border-box; }
.pl-msg{ min-height:14px; overflow-wrap:anywhere; }
.pl-cols{ display:flex; flex-direction:column; gap:12px; min-width:0; }
.pl-treebox, .pl-panel{ border:1px solid var(--line); background:var(--panel); min-width:0; box-sizing:border-box; }
.pl-treebox{ padding:4px 0 8px; }
.pl-wrap.has-sel .pl-treebox{ display:none; }
.pl-wrap:not(.has-sel) .pl-panel{ display:none; }
.pl-node{ display:flex; align-items:stretch; padding-left:calc(var(--d) * 14px); }
.pl-node.sel{ background:var(--panel2); box-shadow:inset 2px 0 0 var(--accent); }
.pl-node.hit .pl-node-name{ color:var(--accent); }
.pl-node.dragging{ opacity:0.45; }
.pl-node.pl-drop{ outline:2px dashed var(--accent); outline-offset:-2px; background:var(--panel2); }
.pl-caret{ flex:none; width:32px; background:none; border:none; color:var(--dim); font-family:inherit; font-size:12px; cursor:pointer; padding:0; }
span.pl-caret{ cursor:default; }
.pl-node-btn{ flex:1; min-width:0; display:flex; flex-direction:column; align-items:stretch; gap:2px; text-align:left; background:none; border:none; color:var(--text); font-family:inherit; font-size:13px; padding:9px 10px 9px 0; min-height:36px; cursor:pointer; box-sizing:border-box; }
.pl-node-btn:hover{ color:var(--accent); }
.pl-line{ display:flex; flex-wrap:wrap; align-items:baseline; gap:2px 8px; min-width:0; }
.pl-node-name{ min-width:0; overflow-wrap:anywhere; }
.pl-count{ margin-left:auto; flex:none; font-size:11px; color:var(--dim); }
.pl-warn{ font-size:11px; color:var(--orange); }
.pl-in{ font-size:11px; color:var(--dim); }
.pl-path{ font-size:11px; color:var(--dim); overflow-wrap:anywhere; }
.pl-group{ display:flex; align-items:center; gap:8px; width:100%; box-sizing:border-box; margin-top:6px; padding:10px 12px; background:none; border:none; border-top:1px solid var(--line-soft); color:var(--dim); font-family:inherit; font-size:13px; text-align:left; cursor:pointer; }
.pl-group:hover{ color:var(--accent); }
.pl-panel-in{ display:flex; flex-direction:column; gap:12px; padding:12px; }
.pl-empty{ padding:24px 12px; }
.pl-back{ align-self:flex-start; }
.pl-crumbs{ font-size:14px; overflow-wrap:anywhere; line-height:1.5; }
.pl-crumb{ background:none; border:none; padding:0; color:var(--dim); font-family:inherit; font-size:inherit; cursor:pointer; }
.pl-crumb:hover{ color:var(--accent); }
.pl-sep{ color:var(--dim); white-space:pre-wrap; }
.pl-crumb-self{ color:var(--text); }
.pl-note{ font-size:12px; color:var(--dim); overflow-wrap:anywhere; }
.pl-note.warn{ color:var(--orange); }
.pl-note.warn:empty{ display:none; }
.pl-field{ display:flex; flex-direction:column; gap:4px; min-width:0; }
.pl-flabel{ font-size:10px; letter-spacing:0.5px; color:var(--dim); text-transform:uppercase; }
.pl-fval{ font-size:13px; overflow-wrap:anywhere; min-width:0; }
.pl-pen{ padding:2px 8px; }
.pl-edit{ display:flex; flex-wrap:wrap; gap:8px; }
.pl-edit .tb-input{ flex:1 1 200px; width:auto; min-width:0; font-size:13px; padding:8px 10px; box-sizing:border-box; }
.pl-kids{ display:flex; flex-direction:column; border:1px solid var(--line-soft); }
.pl-kid{ display:flex; flex-wrap:wrap; align-items:baseline; gap:2px 8px; text-align:left; background:none; border:none; border-bottom:1px solid var(--line-soft); color:var(--text); font-family:inherit; font-size:13px; padding:9px 10px; min-height:36px; cursor:pointer; }
.pl-kid:last-child{ border-bottom:none; }
.pl-kid:hover{ color:var(--accent); }
.pl-btns{ display:flex; flex-wrap:wrap; gap:8px; }
.pl-chip{ display:inline-flex; align-items:center; gap:6px; max-width:100%; box-sizing:border-box; border:1px solid var(--accent-dim); color:var(--text); }
.pl-chip-t{ min-width:0; overflow-wrap:anywhere; }
.pl-chip-note{ flex:1 1 100%; font-size:12px; overflow-wrap:anywhere; }
.pl-chip-x{ background:none; border:none; color:var(--dim); font-family:inherit; font-size:13px; cursor:pointer; padding:2px 4px; }
.pl-chip-x:hover{ color:var(--red); }
.pl-pick-dlg{ max-height:calc(100vh / var(--ui-zoom) - 32px); display:flex; flex-direction:column; }
.pl-pick-dlg .prj-dialog-body{ min-height:0; flex:1; }
.pl-pick{ overflow:auto; max-height:55vh; border:1px solid var(--line-soft); }
.pl-pick-row{ display:flex; align-items:stretch; padding-left:calc(var(--d) * 14px); }
.pl-pick-btn{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; text-align:left; background:none; border:none; color:var(--text); font-family:inherit; font-size:13px; padding:9px 10px 9px 0; min-height:36px; cursor:pointer; }
.pl-pick-btn:hover:not(:disabled){ color:var(--accent); }
.pl-pick-row.blocked .pl-pick-btn{ color:var(--dim2); cursor:not-allowed; }
@media (min-width:900px){
  body:not(.split-on) .pl-cols{ display:grid; grid-template-columns:minmax(280px, 380px) minmax(0, 1fr); align-items:start; gap:16px; }
  body:not(.split-on) .pl-wrap.has-sel .pl-treebox, body:not(.split-on) .pl-wrap:not(.has-sel) .pl-panel{ display:block; }
  body:not(.split-on) .pl-treebox{ position:sticky; top:8px; max-height:calc(100vh / var(--ui-zoom) - 24px); overflow:auto; }
  body:not(.split-on) .pl-back{ display:none; }
}
@media (max-width:640px){
  #places-wrap{ padding:12px 10px; }
}
/* ===== Места: вид «Карта» (placemap.js) ===== */
.pl-views, .pm-seg{ display:flex; flex:none; }
.pl-views .tb-btn, .pm-seg .tb-btn{ border-radius:0; }
.pl-views .tb-btn + .tb-btn, .pm-seg .tb-btn + .tb-btn{ margin-left:-1px; }
.pl-views .tb-btn[aria-pressed="true"], .pm-seg .tb-btn[aria-pressed="true"]{ background:var(--accent-dim); border-color:var(--accent); color:var(--text); position:relative; }
.pm-box{ display:none; min-width:0; flex-direction:column; gap:8px; }
.pl-view-map .pm-box{ display:flex; }
.pl-view-map .pl-treebox{ display:none !important; }
.pl-view-map #pl-search{ display:none; }
.pm-top{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.pm-floors{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; min-width:0; }
.pm-floors:empty{ display:none; }
.pm-floors-t{ font-size:10px; letter-spacing:0.5px; color:var(--dim); text-transform:uppercase; }
.pm-floor.active, .pm-floor[aria-pressed="true"]{ background:var(--accent-dim); border-color:var(--accent); }
.pm-desk{ display:none; }
.pm-shape-btns{ flex-wrap:wrap; gap:8px; margin-top:8px; }
@media (min-width:900px){
  .pm-desk{ display:inline-block; }
  .pm-shape-btns.pm-desk{ display:flex; }
}
.pm-libs{ border:1px solid var(--orange-dim); color:var(--orange); padding:10px 12px; font-size:13px; display:flex; flex-wrap:wrap; align-items:center; gap:8px; overflow-wrap:anywhere; }
.pm-libs[hidden], .pm-mapwrap[hidden], .pm-tools[hidden]{ display:none; }
.pl-wrap.pm-ses .pl-panel{ display:none !important; }
.pm-mapwrap{ position:relative; border:1px solid var(--line); min-width:0; background:var(--pm-bg); }
.pm-map{ height:calc(68vh / var(--ui-zoom)); min-height:300px; width:100%; background:var(--pm-bg); }
.pm-map.pm-crosshair, .pm-crosshair .leaflet-grab{ cursor:crosshair; }
@media (max-width:640px){ .pm-map{ height:calc(54vh / var(--ui-zoom)); } }
.pm-tools{ border:1px solid var(--accent-dim); background:var(--panel); padding:10px 12px; display:flex; flex-direction:column; gap:8px; min-width:0; }
.pm-tools-row{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:8px; }
.pm-tools-title{ font-weight:600; font-size:13px; overflow-wrap:anywhere; }
.pm-tool-btns, .pm-actions{ display:flex; flex-wrap:wrap; gap:6px; }
.pm-hud{ font-size:13px; line-height:1.5; overflow-wrap:anywhere; }
.pm-guide-t{ color:var(--orange); }
.pm-num-row{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; font-size:13px; }
.pm-num-row[hidden]{ display:none; }
.pm-num-row .tb-input{ width:110px; font-size:13px; padding:6px 8px; box-sizing:border-box; }
.pm-errs{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:3px; font-size:12px; overflow-wrap:anywhere; }
.pm-errs:empty{ display:none; }
.pm-errs .bad{ color:var(--red); }
.pm-errs .bad::before{ content:'✖ '; }
.pm-errs .note{ color:var(--orange); }
.pm-label-wrap{ background:none; border:none; }
.pm-label{ position:absolute; left:0; top:0; transform:translate(-50%, 0); white-space:nowrap; text-align:center; font-size:12px; line-height:1.25; color:var(--lb-ink, var(--pm-ink)); pointer-events:none;
  text-shadow:0 0 3px var(--lb-halo, var(--pm-halo)), 0 0 3px var(--lb-halo, var(--pm-halo)), 0 0 2px var(--lb-halo, var(--pm-halo)), 0 0 6px var(--lb-halo, var(--pm-halo)); }
.pm-label b{ display:block; font-weight:600; }
.pm-label-wrap.pm-label-off{ display:none; }
.pm-unpainted{ border:1px solid var(--line); background:var(--panel); min-width:0; }
.pm-unpainted > summary{ padding:9px 12px; cursor:pointer; font-size:13px; }
.pm-un-opt{ display:flex; align-items:center; gap:8px; padding:8px 12px; font-size:13px; border-top:1px solid var(--line-soft); cursor:pointer; }
.pm-un-grp > summary{ padding:7px 12px; font-size:12px; cursor:pointer; background:var(--panel2); border-bottom:1px solid var(--line-soft); }
.pm-un-empty{ padding:10px 12px; font-size:13px; }
.pm-un-list{ max-height:240px; overflow:auto; display:flex; flex-direction:column; border-top:1px solid var(--line-soft); }
.pm-un{ display:flex; flex-wrap:wrap; align-items:baseline; gap:2px 8px; text-align:left; background:none; border:none; border-bottom:1px solid var(--line-soft); color:var(--text); font-family:inherit; font-size:13px; padding:9px 12px; min-height:36px; cursor:pointer; }
.pm-un:last-child{ border-bottom:none; }
.pm-un:hover{ color:var(--accent); }
.pm-un.sel{ background:var(--panel2); box-shadow:inset 2px 0 0 var(--accent); }
.pm-photos{ min-width:0; }
.pm-car-main{ position:relative; background:var(--panel2); height:200px; overflow:hidden; }
.pm-car-main:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px; }
.pm-car-slide{ display:block; width:100%; height:100%; }
.pm-car-slide .prj-thumb{ width:100%; height:100%; border:none; cursor:zoom-in; }
.pm-car-slide .prj-thumb img{ object-fit:contain; }
.pm-car-arrow{ position:absolute; top:50%; transform:translateY(-50%); width:34px; height:46px; background:rgba(0,0,0,0.5); color:var(--pm-halo); border:none; font-size:24px; line-height:1; cursor:pointer; }
.pm-car-arrow.prev{ left:0; }
.pm-car-arrow.next{ right:0; }
.pm-car-arrow[hidden]{ display:none; }
.pm-car-pos{ position:absolute; right:6px; bottom:5px; padding:1px 6px; font-size:11px; color:var(--pm-halo); background:rgba(0,0,0,0.55); }
.pm-color{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.pm-color input[type=color]{ width:44px; height:30px; padding:0; border:1px solid var(--line); background:none; cursor:pointer; }
.pm-level{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.pm-level .tb-input{ width:110px; font-size:13px; padding:6px 8px; box-sizing:border-box; }
.pm-other{ display:flex; flex-direction:column; gap:12px; }
.pm-other:empty{ display:none; }
.pm-defs{ position:absolute; width:0; height:0; overflow:hidden; }
.pm-top{ position:relative; }
.pm-free-info{ font-size:12px; min-width:0; overflow-wrap:anywhere; }
.pm-free-info:empty{ display:none; }
.pm-free{ fill:url(#pm-hatch); fill-opacity:1; }
.pm-hatch-line{ stroke:var(--orange); stroke-width:2.5; }
.pm-rest-btn{ flex-wrap:wrap; gap:8px; margin-top:8px; }
@media (min-width:900px){ .pm-rest-btn.pm-desk{ display:flex; } }
.pq-wrap > summary{ list-style:none; cursor:pointer; user-select:none; }
.pq-wrap > summary::-webkit-details-marker{ display:none; }
.pq-wrap[open] > summary{ background:var(--accent-dim); border-color:var(--accent); }
.pq-list{ position:absolute; z-index:1200; left:0; top:calc(100% + 4px); width:min(560px, 100%); max-height:60vh; overflow:auto; box-sizing:border-box; background:var(--panel); border:1px solid var(--line); box-shadow:0 6px 20px rgba(0,0,0,0.35); }
.pq-wrap:not([open]) .pq-list{ display:none; }
.pq-empty{ padding:10px 12px; font-size:13px; }
.pq-row{ display:flex; flex-wrap:wrap; align-items:center; gap:6px 8px; padding:8px 10px; border-bottom:1px solid var(--line-soft); }
.pq-row:last-child{ border-bottom:none; }
.pq-row.binding{ box-shadow:inset 3px 0 0 var(--accent); }
.pq-eye{ padding:4px 8px; min-width:36px; min-height:32px; }
.pq-eye[aria-pressed="false"]{ opacity:0.55; text-decoration:line-through; }
.pq-name{ flex:1 1 160px; min-width:0; text-align:left; background:none; border:none; color:var(--text); font-family:inherit; font-size:13px; padding:4px 2px; cursor:pointer; overflow-wrap:anywhere; }
.pq-name:hover{ color:var(--accent); }
.pq-op{ display:flex; align-items:center; gap:6px; flex:0 1 150px; min-width:0; }
.pq-op input[type=range]{ flex:1; min-width:70px; }
.pq-pct{ font-size:11px; color:var(--dim); width:34px; text-align:right; }
.pq-acts{ gap:6px; }
.pq-prows{ display:flex; flex-direction:column; gap:6px; }
.pq-prow{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:6px 8px; }
.pq-pname{ min-width:0; overflow-wrap:anywhere; }
.pq-add{ margin-top:8px; }
.pq-oprow{ display:flex; align-items:center; gap:8px; font-size:13px; }
.pq-oprow input[type=range]{ flex:1; min-width:80px; }
.pq-ok{ color:var(--green); }
.pq-coord-row label{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.pq-coord-row .tb-input{ width:190px; max-width:100%; }
.pq-coord-hud{ position:absolute; left:8px; bottom:8px; z-index:1000; padding:3px 8px; font-size:12px; font-family:ui-monospace, Menlo, Consolas, monospace; color:var(--pm-halo); background:rgba(0,0,0,0.65); pointer-events:none; max-width:calc(100% - 16px); overflow-wrap:anywhere; }
.pq-coord-hud[hidden]{ display:none; }
.pm-calque-img{ position:absolute; left:0; top:0; user-select:none; -webkit-user-drag:none; pointer-events:none; }
.pq-handle{ background:none; border:none; }
.pq-corner{ box-sizing:border-box; background:var(--pm-halo); border:2px solid var(--accent); cursor:nwse-resize; }
.pq-rot{ display:flex; align-items:center; justify-content:center; box-sizing:border-box; background:var(--accent); color:var(--pm-halo); border-radius:50%; font-size:14px; line-height:1; cursor:grab; }
.leaflet-container .pq-quad{ cursor:move; }
.pq-tools[hidden]{ display:none; }
.leaflet-container{ font-family:inherit; }
.prj-sim:empty{ display:none; }
.prj-sim{ display:flex; flex-direction:column; align-items:stretch; gap:6px; min-width:0; padding-bottom:8px; }
.prj-sim-head{ font-size:13px; padding-top:6px; border-top:1px solid var(--line); }
.prj-sim-toggle{ display:flex; align-items:baseline; gap:8px; max-width:100%; padding:6px 2px; background:none; border:none; color:var(--text); font:inherit; font-size:13px; text-align:left; cursor:pointer; }
.prj-sim-body{ display:flex; flex-direction:column; align-items:stretch; min-width:0; }
.prj-why{ display:flex; flex-direction:column; gap:2px; font-size:11px; color:var(--dim); min-width:0; overflow-wrap:anywhere; }
.prj-why-l{ color:var(--text); }
.prj-row mark, .prj-why mark{ background:var(--auto-bg); color:var(--text); border-bottom:1px solid var(--auto); padding:0 1px; }
.prj-why-tag{ font-size:11px; color:var(--orange); border:1px solid var(--orange-dim); padding:0 4px; white-space:nowrap; }

/* ---------- ИСТОРИЯ ОБЪЕКТА (objhist.js, §118) ----------
   Окно поверх окна «Объект»; на телефоне (< 700px) - на весь экран. Только чтение. */
.oh-back{ position:fixed; inset:0; z-index:10040; background:rgba(0,0,0,0.6); zoom:calc(1 / var(--ui-zoom)); display:flex; align-items:center; justify-content:center; padding:10px; box-sizing:border-box; }
.oh-back ~ .prj-viewer{ z-index:10045; }
.oh-box{ background:var(--panel); color:var(--text); border:1px solid var(--line); width:100%; max-width:900px; max-height:100%; height:min(760px, 100%); display:flex; flex-direction:column; padding:12px; box-sizing:border-box; font-size:14px; min-width:0; }
.oh-head{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:8px; min-width:0; }
.oh-head h3{ margin:0; font-size:15px; min-width:0; overflow-wrap:anywhere; }
.oh-tabs{ display:flex; gap:6px; margin-bottom:8px; }
.oh-tabs .tb-btn.active{ border-color:var(--accent); font-weight:700; }
.oh-tools{ display:flex; flex-wrap:wrap; align-items:center; gap:8px 14px; margin-bottom:6px; min-width:0; }
.oh-tools:empty{ display:none; }
.oh-chk{ display:inline-flex; align-items:center; gap:6px; font-size:13px; }
.oh-flt{ display:inline-flex; align-items:center; gap:6px; font-size:13px; min-width:0; max-width:100%; }
.oh-flt select{ min-width:0; max-width:100%; background:var(--panel2); border:1px solid var(--line); color:var(--text); font-family:inherit; font-size:13px; padding:4px 6px; }
.oh-note{ font-size:12px; color:var(--orange); margin-bottom:6px; }
.oh-body{ flex:1 1 auto; min-height:0; overflow-y:auto; overflow-x:hidden; overflow-wrap:anywhere; }
.oh-empty{ padding:12px 0; }
.oh-error{ padding:12px; border:1px solid var(--line); display:flex; flex-direction:column; align-items:flex-start; gap:8px; color:var(--orange); }
.oh-field{ padding:8px 0; border-bottom:1px solid var(--line-soft); min-width:0; }
.oh-fname{ font-size:11px; letter-spacing:.5px; text-transform:uppercase; color:var(--dim); margin-bottom:3px; }
.oh-row{ margin:2px 0 4px; min-width:0; }
.oh-row.sub{ margin-left:16px; padding-left:8px; border-left:2px solid var(--line-soft); }
.oh-val{ min-width:0; }
.oh-ql{ color:var(--dim); font-size:13px; }
.oh-meta{ font-size:12px; color:var(--dim); }
.oh-unk{ color:var(--orange); }
.oh-old{ margin-top:6px; padding-left:10px; border-left:2px solid var(--line); }
.oh-old-h{ font-size:11px; color:var(--dim); text-transform:uppercase; letter-spacing:.5px; }
.oh-row.del > .oh-val{ opacity:.75; }
.oh-file{ display:inline-flex; align-items:center; gap:8px; max-width:100%; }
.oh-file .prj-thumb{ width:56px; height:56px; flex:none; }
.oh-flname{ min-width:0; font-size:13px; }
.oh-more{ border:none; background:none; color:var(--accent); cursor:pointer; padding:0; font:inherit; text-decoration:underline; }
.oh-group{ padding:8px 0; border-bottom:1px solid var(--line-soft); min-width:0; }
.oh-g-h{ display:flex; flex-wrap:wrap; align-items:baseline; gap:2px 8px; font-size:13px; }
.oh-g-time{ color:var(--dim); }
.oh-g-cl{ font-size:12px; }
.oh-src{ font-size:11px; color:var(--dim); }
.oh-acts{ margin:4px 0 0; padding-left:18px; }
.oh-acts li{ margin:2px 0; min-width:0; }
@media (max-width:699px){
  .oh-back{ padding:0; }
  .oh-box{ height:100%; max-width:none; border-left:none; border-right:none; }
  .oh-file .prj-thumb{ width:48px; height:48px; }
}

/* ===== Просмотр мест (placeview.js): эскиз «Где это» в окне «Объект» и просмотр на весь экран ===== */
.pv-where{ min-width:0; }
.pv-where[hidden]{ display:none; }
.pv-path{ display:flex; flex-wrap:wrap; align-items:center; gap:2px 0; font-size:13px; min-width:0; }
.pv-crumb{ background:none; border:none; padding:6px 4px; min-height:32px; box-sizing:border-box; color:var(--accent); font-family:inherit; font-size:13px; cursor:pointer; overflow-wrap:anywhere; text-align:left; }
.pv-crumb:hover{ text-decoration:underline; }
.pv-crumb-self{ padding:6px 4px; overflow-wrap:anywhere; }
.pv-mini-wrap{ position:relative; margin-top:8px; width:100%; max-width:520px; min-width:0; }
.pv-mini{ display:block; width:100%; max-height:240px; padding:0; border:1px solid var(--line); background:var(--pm-bg); cursor:pointer; overflow:hidden; box-sizing:border-box; }
.pv-mini:hover{ border-color:var(--accent); }
.pv-mini .pv-svg{ display:block; width:100%; height:100%; }
.pv-floor-badge{ position:absolute; left:6px; top:6px; padding:1px 7px; border-radius:9px; background:var(--pm-halo); color:var(--pm-ink); border:1px solid var(--pm-ink); font-size:12px; pointer-events:none; max-width:70%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pv-north-wrap{ position:absolute; right:6px; top:6px; pointer-events:none; line-height:0; }
.pv-exact{ margin-top:6px; font-size:12.5px; color:var(--dim); overflow-wrap:anywhere; }
.pv-svg{ -webkit-user-select:none; user-select:none; }
.pv-s{ vector-effect:non-scaling-stroke; stroke-linejoin:round; }
.pv-grey{ fill:none; stroke:var(--pv-grey-line); stroke-width:1; }
.pv-plate{ fill:none; pointer-events:all; stroke:var(--c); stroke-width:1; stroke-dasharray:4 3; }
.pv-anc{ fill:none; stroke:var(--pv-dark); stroke-width:1.6; }
.pv-item{ fill:none; pointer-events:all; stroke:var(--c); stroke-width:1.8; }   /* места - только линиями: без заливки; pointer-events:all - нажатие внутри контура по-прежнему выбирает место */
.pv-item.pv-click{ cursor:pointer; }
.pv-item.pv-click:hover{ stroke-opacity:.7; }
.pv-rest{ stroke-dasharray:6 4; }
/* толщина линии по вложенности (pmDepth): территория - средняя, второй уровень (здания, дворы) - толстая тёмная, глубже - тонкая; серый фон не трогаем */
.pv-item.pv-d0, .pv-anc.pv-d0, .pv-plate.pv-d0{ stroke-width:2.2; }
.pv-item.pv-d1, .pv-anc.pv-d1, .pv-plate.pv-d1{ stroke-width:3.6; stroke:var(--pv-dark); }
.pv-item.pv-d2, .pv-anc.pv-d2, .pv-plate.pv-d2{ stroke-width:1.2; }
.pv-d1.pv-man{ stroke:var(--c); }   /* место второго уровня с цветом, заданным вручную (225 есть), - толстая линия своим цветом; без цвета - тёмная */
.pv-s.pv-man{ fill:var(--c); fill-opacity:.12; }   /* и слабая заливка этим цветом: так владелец сам отмечает строения; остальные места - только линиями */
/* рисунок по «Виду места» (232, §162; placekind.js: pzKindKey, вид не задан - угадан по родителю): Территория - жирный контур без заливки; Здание - жирный тёмный + заливка (цвет 225, иначе светло-серая);
   Помещение, Этаж, Стеллаж, Полка - тонкий сплошной; Зона - тонкий пунктир без заливки (225 - бледнее); препятствие - штриховка (pv-obst). Вида нет - толщина по глубине (pv-d0..d2) */
.pv-item.pv-k-terr, .pv-anc.pv-k-terr, .pv-plate.pv-k-terr{ stroke-width:3; stroke:var(--c); fill:none; }
.pv-item.pv-k-bld, .pv-anc.pv-k-bld, .pv-plate.pv-k-bld{ stroke-width:2.5; stroke:var(--pv-dark); fill:var(--pv-grey); fill-opacity:.16; }
.pv-item.pv-k-bld.pv-man, .pv-anc.pv-k-bld.pv-man, .pv-plate.pv-k-bld.pv-man{ fill:var(--c); fill-opacity:.2; }
.pv-item.pv-k-room, .pv-anc.pv-k-room, .pv-plate.pv-k-room, .pv-item.pv-k-floor, .pv-anc.pv-k-floor, .pv-plate.pv-k-floor,
.pv-item.pv-k-rack, .pv-anc.pv-k-rack, .pv-plate.pv-k-rack, .pv-item.pv-k-shelf, .pv-anc.pv-k-shelf, .pv-plate.pv-k-shelf{ stroke-width:1; fill:none; }
.pv-item.pv-k-zone, .pv-anc.pv-k-zone, .pv-plate.pv-k-zone{ stroke-width:1; stroke-dasharray:3 3; fill:none; }
.pv-item.pv-k-zone.pv-man, .pv-anc.pv-k-zone.pv-man, .pv-plate.pv-k-zone.pv-man{ stroke-opacity:.6; }
.pv-item.pv-floorpl{ stroke-dasharray:4 3; }   /* этаж с комнатами (выбор тапом): подложка пунктиром */
/* выделенное (красным): толстая линия и лёгкая заливка - единственная залитая фигура; блок второго уровня, где оно лежит, - тоже цветом выделения */
.pv-s.pv-mark{ fill:var(--pv-red); fill-opacity:.14; pointer-events:all; stroke:var(--pv-red); stroke-width:4.4; stroke-dasharray:none; }
.pv-s.pv-blk{ stroke:var(--pv-red); stroke-width:3.6; }
.pv-mark.pv-click{ cursor:pointer; }
.pv-label{ fill:var(--lb-ink, var(--pm-ink)); stroke:var(--lb-halo, var(--pm-halo)); paint-order:stroke; stroke-linejoin:round; font-family:inherit; font-weight:600; pointer-events:none; }
.pv-label-off{ display:none; }
.pv-north path{ fill:var(--pv-dark); }
.pv-north text{ font-size:9px; fill:var(--pm-ink); font-family:inherit; }
.pv-backdrop{ position:fixed; inset:0; z-index:10010; background:rgba(0,0,0,.55); display:flex; align-items:center; justify-content:center; padding:16px; box-sizing:border-box; zoom:calc(1 / var(--ui-zoom)); }
.pv-dlg{ display:flex; flex-direction:column; width:min(1100px, 100%); height:min(860px, 100%); background:var(--panel); border:1px solid var(--line); box-sizing:border-box; min-width:0; }
.pv-bar{ display:flex; align-items:center; gap:8px; padding:8px 10px; border-bottom:1px solid var(--line-soft); min-width:0; }
.pv-crumbs{ flex:1; min-width:0; display:flex; flex-wrap:wrap; align-items:center; font-size:13px; }
.pv-x{ flex:none; }
.pv-body{ flex:1; min-height:0; display:flex; flex-direction:column; gap:8px; padding:8px 10px 10px; overflow:auto; min-width:0; }
.pv-floors:empty{ display:none; }
.pv-stage{ position:relative; flex:1 1 auto; min-height:260px; background:var(--pm-bg); border:1px solid var(--line); touch-action:none; overflow:hidden; min-width:0; }
.pv-svgbox{ position:absolute; inset:0; }
.pv-svgbox .pv-svg{ display:block; width:100%; height:100%; }
.pv-svgbox .map-empty{ color:var(--pv-dark); }
.pv-north-slot{ position:absolute; left:8px; top:8px; pointer-events:none; line-height:0; }
.pv-zoom{ position:absolute; right:8px; bottom:8px; display:flex; flex-direction:column; gap:4px; }
.pv-zoom .tb-btn{ width:36px; height:36px; padding:0; font-size:18px; line-height:1; background:var(--pm-halo); color:var(--pm-ink); border-color:rgba(0, 0, 0, 0.12); border-radius:50%; box-shadow:0 2px 6px rgba(0, 0, 0, 0.45); }
.pv-info{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; font-size:13px; min-width:0; }
.pv-list{ display:flex; flex-direction:column; gap:6px; min-width:0; max-height:32vh; overflow:auto; }
.pv-kids{ display:flex; flex-wrap:wrap; gap:6px; }
.pv-kid{ display:inline-flex; align-items:baseline; gap:8px; max-width:100%; box-sizing:border-box; min-height:36px; padding:6px 10px; background:var(--panel2); border:1px solid var(--line); color:var(--text); font-family:inherit; font-size:13px; cursor:pointer; overflow-wrap:anywhere; text-align:left; }
.pv-kid:hover{ border-color:var(--accent); color:var(--accent); }
.pv-unp{ font-size:13px; }
.pv-unp > summary{ cursor:pointer; list-style:none; min-height:32px; display:flex; align-items:center; }
.pv-unp > summary::-webkit-details-marker{ display:none; }
.pv-unp[open] > summary{ margin-bottom:6px; }
.pv-unp-list{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.pv-foot{ flex:none; display:flex; gap:8px; padding:8px 10px calc(8px + env(safe-area-inset-bottom)); border-top:1px solid var(--line); }
.pv-foot .tb-btn{ min-height:40px; }
.pv-where-t{ justify-content:flex-start; }
.pv-where-line{ margin-top:6px; font-size:13px; overflow-wrap:anywhere; }
.pv-where-line.pv-system{ font-size:18px; font-weight:600; }
.pv-where-line.pv-none{ color:var(--dim); }
.pv-note{ margin-top:6px; font-size:12.5px; overflow-wrap:anywhere; }
.pv-where.imp-miss .pv-where-line{ color:var(--orange); }
@media (max-width:640px){
  .pv-backdrop{ padding:0; }
  .pv-dlg{ width:100%; height:100%; border-left:none; border-right:none; border-top:none; border-bottom:none; }
  .pv-stage{ min-height:240px; }
  .pv-bar{ flex-wrap:wrap; }
  .pv-crumbs{ order:3; flex:1 0 100%; }
}

/* ===== Выбор места: окно «Куда переместить» (placepick.js) =====
   Поверх окна «Объект»; на телефоне (< 641px) - на весь экран: эскиз сверху, полоса подтверждения снизу закреплена. */
.pp-back{ position:fixed; inset:0; z-index:10010; background:rgba(0,0,0,.55); display:flex; align-items:center; justify-content:center; padding:16px; box-sizing:border-box; zoom:calc(1 / var(--ui-zoom)); }
.pp-back ~ .map-picker-backdrop{ z-index:10055; }
.pp-dlg{ display:flex; flex-direction:column; width:min(980px, 100%); height:min(860px, 100%); background:var(--panel); color:var(--text); border:1px solid var(--line); box-sizing:border-box; min-width:0; font-size:13px; }
.pp-bar{ display:flex; align-items:center; gap:8px; padding:8px 10px; border-bottom:1px solid var(--line-soft); min-width:0; }
.pp-title{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; font-size:15px; }
.pp-obj{ font-size:12px; overflow-wrap:anywhere; }
.pp-x{ flex:none; }
.pp-body{ flex:1; min-height:0; display:flex; flex-wrap:wrap; align-content:flex-start; gap:8px; padding:8px 10px; overflow-y:auto; overflow-x:hidden; min-width:0; }
.pp-body > *{ flex:1 1 100%; min-width:0; }
.pp-body > .pp-crumbs{ flex:1 1 340px; order:0; }
.pp-body > .pp-search{ flex:1 1 260px; order:0; }
.pp-body > .pp-recent{ order:1; }
.pp-body > .pp-stagewrap{ order:2; }
.pp-body > .pp-actions{ order:3; }
.pp-body > .pp-inside{ order:4; }
.pp-body > .pp-quick{ order:5; }
.pp-crumbs{ display:flex; flex-wrap:wrap; align-items:center; font-size:13px; }
.pp-search .tb-input{ width:100%; box-sizing:border-box; }
.pp-results{ margin-top:4px; max-height:34vh; overflow-y:auto; border:1px solid var(--line); background:var(--panel2); }
.pp-results[hidden], .pp-recent[hidden], .pp-inside[hidden]{ display:none; }
.pp-res{ display:flex; flex-direction:column; align-items:flex-start; gap:1px; width:100%; min-height:40px; padding:6px 10px; box-sizing:border-box; background:none; border:none; border-bottom:1px solid var(--line-soft); color:var(--text); font-family:inherit; font-size:13px; text-align:left; cursor:pointer; overflow-wrap:anywhere; }
.pp-res:hover{ background:var(--panel); color:var(--accent); }
.pp-res-p{ font-size:12px; }
.pp-res-empty{ padding:8px 10px; }
.pp-recent{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.pp-chip{ min-height:32px; max-width:100%; box-sizing:border-box; padding:4px 11px; border:1px solid var(--line); border-radius:16px; background:var(--panel2); color:var(--text); font-family:inherit; font-size:13px; cursor:pointer; overflow-wrap:anywhere; }
.pp-chip:hover{ border-color:var(--accent); color:var(--accent); }
.pp-stage{ position:relative; height:clamp(240px, 52vh, 560px); background:var(--pm-bg); border:1px solid var(--line); touch-action:none; overflow:hidden; min-width:0; }
.pp-stage .pv-svgbox .pv-svg{ display:block; width:100%; height:100%; }
.pp-stage .map-empty{ color:var(--pv-dark); }
.pp-floors{ position:absolute; right:8px; top:8px; z-index:2; display:flex; flex-direction:column; gap:4px; max-height:calc(100% - 64px); overflow-y:auto; }
.pp-floors:empty{ display:none; }
.pp-floor{ flex:none; min-width:40px; height:40px; padding:0 6px; box-sizing:border-box; background:var(--pm-halo); color:var(--pm-ink); border-color:var(--line); font-size:14px; font-weight:600; }
.pp-floor.active{ background:var(--pm-halo); color:var(--pm-ink); border-color:var(--accent); box-shadow:0 0 0 2px var(--accent) inset; }
.pp-floor.picked, .pp-floor.active.picked{ background:var(--accent); color:var(--pm-halo); }
.pv-s.pp-now{ fill:none; stroke:var(--pv-red); stroke-width:3; stroke-dasharray:none; }
.pv-s.pp-sel{ fill:none; stroke:var(--accent); stroke-width:4.4; stroke-dasharray:none; }
.pv-s.pp-blk{ stroke:var(--accent); stroke-width:3.6; stroke-dasharray:none; }   /* выбор тапом: блок второго уровня, где лежит выбранное */
.pp-tap .pv-s.pp-sel{ fill:var(--accent); fill-opacity:.16; stroke-width:5; }   /* выбор тапом: выбранное - единственная залитая фигура */
.pv-s.pv-dim:not(.pp-now){ stroke-opacity:.28; fill-opacity:.05; }   /* встроенная карта окна станка: места вне пути выбранного - бледные (нажимаются как прежде) */
.pv-label.pv-label-dim{ opacity:.45; }   /* и их подписи */
.pp-northup{ position:absolute; z-index:2; left:40px; top:6px; min-width:40px; height:36px; padding:0 8px; box-sizing:border-box; background:var(--pm-halo); color:var(--pm-ink); border-color:var(--line); font-size:15px; font-weight:700; }   /* «С↑» - север вверх, пока вид повёрнут (двумя пальцами или компасом) */
.pp-northup[hidden]{ display:none; }
.rc-compass .rc-cn{ display:none; }   /* «С↑» теперь на самой карте (.pp-northup) и работает при любом повороте, в том числе пальцами; прежняя кнопка рядом с 🧭 не нужна */
.pp-actions{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.pp-actions .tb-btn{ min-height:38px; }
.pp-legend{ margin-left:auto; display:inline-flex; flex-wrap:wrap; align-items:center; gap:4px 10px; font-size:12px; color:var(--dim); }
.pp-key{ display:inline-block; width:12px; height:12px; box-sizing:border-box; margin-right:4px; vertical-align:-1px; }
.pp-key-now{ background:none; border:3px solid var(--pv-red); }
.pp-key-sel{ background:none; border:3px solid var(--accent); }
.pp-inside{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; max-height:26vh; overflow-y:auto; }
.pp-un{ display:inline-flex; align-items:stretch; max-width:100%; border:1px solid var(--line); background:var(--panel2); }
.pp-un-b{ min-height:38px; padding:6px 10px; background:none; border:none; color:var(--text); font-family:inherit; font-size:13px; text-align:left; cursor:pointer; overflow-wrap:anywhere; min-width:0; }
.pp-un-b:hover{ color:var(--accent); }
.pp-un-par{ color:var(--dim); }
.pp-un-tag{ font-size:11px; color:var(--pv-red); }
.pp-un-more{ color:var(--accent); font-size:16px; }
.pp-searchrow{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 12px; }
.pp-searchrow .tb-input{ flex:1 1 220px; min-width:0; width:auto; }
.pp-link{ flex:none; background:none; border:none; padding:6px 2px; min-height:32px; color:var(--accent); font-family:inherit; font-size:12.5px; cursor:pointer; text-decoration:underline; }
.pp-fpick{ position:absolute; z-index:3; transform:translate(-50%, -50%); display:flex; flex-direction:column; gap:4px; width:max-content; max-width:min(72%, 260px); max-height:calc(100% - 12px); overflow-y:auto; padding:6px; box-sizing:border-box; background:var(--pm-halo); border:1px solid var(--line); }
.pp-fpick[hidden]{ display:none; }
.pp-fp{ min-height:38px; background:var(--pm-halo); color:var(--pm-ink); border-color:var(--accent); font-weight:600; overflow-wrap:anywhere; }
.pp-fp-all{ min-height:34px; background:none; color:var(--dim); border-color:var(--line); overflow-wrap:anywhere; }
.pp-fp-cap{ width:0; min-width:100%; font-size:11.5px; color:var(--dim); overflow-wrap:anywhere; }
.pv-s.pp-pend{ stroke:var(--accent); stroke-width:3; stroke-dasharray:6 4; }
.pv-grey.pp-clk{ cursor:pointer; pointer-events:all; }
.pp-un.has-sel{ border:1px dashed var(--accent); }
.pp-un.sel{ border-color:var(--accent); box-shadow:0 0 0 2px var(--accent); }
.pp-un.now, .pp-un.has-now{ border-left:4px solid var(--pv-red); }
.pp-quick{ display:flex; flex-wrap:wrap; gap:8px; }
.pp-quick .tb-btn{ min-height:38px; }
.pp-strip{ flex:none; display:flex; flex-direction:column; gap:6px; padding:8px 10px calc(8px + env(safe-area-inset-bottom)); border-top:1px solid var(--line); background:var(--panel); min-width:0; }
.pp-line{ overflow-wrap:anywhere; }
.pp-k{ color:var(--dim); }
.pp-same{ color:var(--orange); }
.pp-cmt{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 8px; }
.pp-cmt .tb-input{ flex:1 1 220px; min-width:0; box-sizing:border-box; }
.pp-chk{ display:flex; align-items:flex-start; gap:6px; overflow-wrap:anywhere; }
.pp-chk input{ margin-top:2px; flex:none; }
.pp-btns{ display:flex; flex-wrap:wrap; gap:8px; }
.pp-btns .tb-btn{ min-height:40px; }
.pp-msg{ font-size:12px; color:var(--orange); overflow-wrap:anywhere; }
.pp-msg.empty{ display:none; }
@media (max-width:640px){
  .pp-back{ padding:0; }
  .pp-dlg{ width:100%; height:100%; border:none; }
  .pp-body > .pp-stagewrap{ order:1; }
  .pp-body > .pp-actions{ order:2; }
  .pp-body > .pp-inside{ order:3; }
  .pp-body > .pp-search{ order:4; }
  .pp-body > .pp-recent{ order:5; }
  .pp-body > .pp-quick{ order:6; }
  .pp-stage{ height:clamp(220px, 40vh, 400px); }
  .pp-legend{ margin-left:0; flex-basis:100%; }
}

/* ===== Вещи на карте (placething.js, placethingform.js) =====
   Фигуры вещей поверх мест на эскизах (SVG) и на карте Leaflet; блок в «Где»; список «Проверить привязку»; окно «Поставить на карту» (на телефоне - на весь экран). */
.pt-g, .pt-labels{ pointer-events:none; }
.pt-fig{ fill:var(--pt-fig); fill-opacity:.45; stroke:var(--pt-fig); stroke-width:1.4; vector-effect:non-scaling-stroke; stroke-linejoin:round; }
.pt-pt{ fill-opacity:.9; }
.pt-fig.pt-check{ fill:var(--pt-check); stroke:var(--pt-check); stroke-dasharray:4 3; }
.pt-fig.pt-own{ fill:var(--pv-red); stroke:var(--pv-red); fill-opacity:.55; stroke-width:2.2; stroke-dasharray:none; }
.pt-label{ fill:var(--pt-ink); stroke:var(--pt-halo); paint-order:stroke; stroke-linejoin:round; font-family:inherit; font-weight:600; }
.pt-label-own{ font-weight:700; }
.pt-map-label-wrap{ background:none; border:none; }
.pt-map-label{ display:none; position:absolute; left:0; top:0; transform:translate(-50%, 8px); white-space:nowrap; font-size:11px; font-weight:600; color:var(--pt-ink); text-shadow:0 0 2px var(--pt-halo), 0 0 2px var(--pt-halo), 0 0 3px var(--pt-halo); pointer-events:none; }
.pt-labels-on .pt-map-label{ display:block; }
.pt-toggle[aria-pressed="true"]{ background:var(--accent-dim); border-color:var(--accent); color:var(--text); }
.pt-pop{ display:flex; flex-direction:column; gap:4px; min-width:160px; }
.pt-pop .tb-btn{ align-self:flex-start; margin-top:4px; }
.pt-warn{ color:var(--orange); overflow-wrap:anywhere; }
/* карточка-превью вещи (§162; placething.js: ptCardHtml): фото слева, название и «Открыть карточку» справа */
.pt-card{ display:flex; gap:8px; align-items:center; min-width:0; }
.ptc-photo{ flex:none; }
.ptc-photo .prj-row-media{ margin:0; }
.ptc-photo .prj-row-thumb{ width:72px; height:72px; flex:none; position:relative; cursor:zoom-in; }
.ptc-body{ display:flex; flex-direction:column; gap:4px; min-width:0; align-items:flex-start; }
.ptc-title{ overflow-wrap:anywhere; line-height:1.25; font-size:15px; }
.ptc-open{ min-height:40px; text-transform:none; letter-spacing:0; }
.pp-thingcard{ position:absolute; left:8px; bottom:8px; z-index:12; max-width:calc(100% - 84px); min-width:200px; box-sizing:border-box; padding:8px; background:var(--panel); border:1px solid var(--line); border-radius:10px; box-shadow:0 3px 12px rgba(0,0,0,.28); pointer-events:auto; }
.pp-thingcard[hidden]{ display:none; }
.pt-check{ border:1px solid var(--line); background:var(--panel); min-width:0; }
.pt-check[hidden]{ display:none; }
.pt-check > summary{ padding:9px 12px; cursor:pointer; font-size:13px; }
.pt-check-list{ display:flex; flex-direction:column; gap:6px; padding:0 12px 10px; }
.pt-check-row{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:6px 10px; min-width:0; }
.pt-check-n{ flex:1 1 220px; min-width:0; overflow-wrap:anywhere; }
.pt-where{ display:flex; flex-direction:column; gap:6px; margin-top:8px; min-width:0; }
.pt-line{ font-size:13px; overflow-wrap:anywhere; }
.pt-k{ color:var(--dim); }
.pt-btns{ display:flex; flex-wrap:wrap; gap:8px; }
.pt-btns .tb-btn{ min-height:40px; }
.pt-hint{ color:var(--text); }
.pt-back{ position:fixed; inset:0; z-index:10010; background:rgba(0,0,0,.55); display:flex; align-items:center; justify-content:center; padding:16px; box-sizing:border-box; zoom:calc(1 / var(--ui-zoom)); }
.pt-dlg{ display:flex; flex-direction:column; width:min(980px, 100%); height:min(860px, 100%); background:var(--panel); color:var(--text); border:1px solid var(--line); box-sizing:border-box; min-width:0; font-size:13px; }
.pt-bar{ display:flex; align-items:center; gap:8px; padding:8px 10px; border-bottom:1px solid var(--line-soft); min-width:0; }
.pt-title{ flex:1; min-width:0; font-size:15px; }
.pt-x{ flex:none; }
.pt-body{ flex:1; min-height:0; display:flex; flex-direction:column; padding:8px 10px; min-width:0; }
.pt-stage{ position:relative; flex:1 1 auto; min-height:220px; background:var(--pm-bg); border:1px solid var(--line); touch-action:none; overflow:hidden; min-width:0; }
.pt-svgbox{ position:absolute; inset:0; }
.pt-svgbox .pv-svg{ display:block; width:100%; height:100%; }
.pt-svgbox .map-empty{ color:var(--pv-dark); }
.pt-wall{ fill:none; stroke:var(--pt-halo); stroke-opacity:0; stroke-width:16px; vector-effect:non-scaling-stroke; pointer-events:none; }
.pt-stage[data-pick="1"] .pt-wall{ pointer-events:stroke; cursor:pointer; }
.pt-wall-on{ fill:none; stroke:var(--pt-w1); stroke-width:4px; vector-effect:non-scaling-stroke; pointer-events:none; stroke-linecap:round; }
.pt-wall-on.pt-w2{ stroke:var(--pt-w2); }
.pt-prev-fig{ fill:var(--pt-w1); fill-opacity:.4; stroke:var(--pt-w1); stroke-width:2.2px; vector-effect:non-scaling-stroke; cursor:grab; touch-action:none; }
.pt-stage[data-step="fin"] .pt-prev-fig{ pointer-events:all; }
.pt-strip{ flex:none; display:flex; flex-direction:column; gap:6px; max-height:46vh; overflow-y:auto; padding:8px 10px calc(8px + env(safe-area-inset-bottom)); border-top:1px solid var(--line); background:var(--panel); min-width:0; }
.pt-fld{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 8px; }
.pt-fld .tb-input{ flex:1 1 120px; min-width:0; max-width:220px; box-sizing:border-box; font-size:14px; padding:8px 10px; }
.pt-seg{ display:flex; gap:6px; }
.pt-seg .tb-btn{ min-height:38px; }
.pt-seg .tb-btn[aria-pressed="true"]{ background:var(--accent-dim); border-color:var(--accent); color:var(--text); }
.pt-rot{ display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; }
.pt-rot .tb-btn{ min-height:38px; }
.pt-what{ color:var(--text); }
.pt-msg{ font-size:12px; color:var(--orange); overflow-wrap:anywhere; }
.pt-msg.empty{ display:none; }
.pt-cancel{ margin-top:2px; }
@media (max-width:640px){
  .pt-back{ padding:0; }
  .pt-dlg{ width:100%; height:100%; border:none; }
  .pt-stage{ min-height:200px; }
  .pt-strip{ max-height:50vh; }
}

.pk-tools[hidden]{ display:none; }
.pk-side{ border-top:1px dashed var(--line); padding-top:6px; }
.pk-side .prj-muted{ flex-basis:100%; font-size:12px; }
.pk-side label, .pk-xf-row label{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.pk-side .tb-input, .pk-xf-row .tb-input{ width:96px; }
.pk-chk{ display:flex; align-items:center; gap:6px; font-size:13px; }
.pk-chg:empty{ display:none; }
.pk-chg{ font-size:12px; }
.pk-chg-t{ font-size:13px; }
.pk-chg-l{ margin:2px 0 0; padding:0 0 0 18px; max-height:120px; overflow:auto; overflow-wrap:anywhere; }
.pk-chg-l .bad{ color:var(--red); }
/* Размеры, закрепления, выравнивание (placedim.js) */
.pd-bar{ border-top:1px dashed var(--line); padding-top:6px; display:flex; flex-direction:column; gap:6px; min-width:0; }
.pd-bar[hidden]{ display:none; }
.pd-btns{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.pd-sep{ flex:none; width:8px; }
.pd-hud{ font-size:12px; line-height:1.45; color:var(--muted, inherit); overflow-wrap:anywhere; }
.pd-kind{ display:inline-flex; gap:0; }
.pd-kind .tb-btn{ margin:0; }
.pd-kind .tb-btn[aria-pressed=true], .pd-pop [data-pd="flip"][aria-pressed=true]{ background:var(--accent-dim); border-color:var(--accent); }
.pd-msg:empty{ display:none; }
/* Окошко у места на карте (pmPop, §170): рядом с точкой / размером, не вылезает за край карты */
.pm-pop{ position:absolute; z-index:1250; left:0; top:0; box-sizing:border-box; max-width:min(340px, calc(100% - 12px)); max-height:calc(100% - 12px); overflow:auto; background:var(--panel); color:var(--text); border:1px solid var(--accent); border-radius:8px; padding:8px 10px; box-shadow:0 6px 24px rgba(0,0,0,.35); font-size:13px; line-height:1.35; display:flex; flex-direction:column; gap:6px; }
.pd-pop-t{ font-size:13px; overflow-wrap:anywhere; }
.pd-pop-st{ font-size:12px; color:var(--muted, inherit); overflow-wrap:anywhere; }
.pd-pop-row{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.pd-pop-row:empty{ display:none; }
.pd-pop-in{ display:inline-flex; align-items:center; gap:4px; }
.pd-pop-in .tb-input{ width:7em; font-size:16px; }
.pd-pop .pm-errs{ margin:0; }
.pd-pop-list, .pd-pop-dims{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px; }
.pd-pop-list .pd-hit{ width:100%; text-align:left; background:none; border:1px solid transparent; border-radius:4px; color:inherit; font:inherit; padding:6px 8px; cursor:pointer; }
.pd-pop-list .pd-hit:hover, .pd-pop-list .pd-hit:focus{ border-color:var(--accent); background:var(--accent-dim); outline:none; }
.pd-dimrow{ font-size:12px; padding:3px 6px; border-left:3px solid var(--pd-line); cursor:default; overflow-wrap:anywhere; }
.pd-dimrow:hover, .pd-dimrow:focus{ background:var(--accent-dim); outline:none; }
.pd-pop-msg:empty{ display:none; }
.pd-legend{ display:flex; flex-wrap:wrap; gap:4px 12px; font-size:11px; color:var(--muted, inherit); }
.pd-legend > span{ display:inline-flex; align-items:center; gap:4px; }
.pd-dot{ display:inline-block; width:9px; height:9px; border-radius:50%; border:2px solid var(--pd-pt-ring); box-shadow:0 0 0 1px var(--pd-pt-edge); }
.pd-dot.free{ background:var(--pd-pt-ring); border-color:var(--pd-pt-free); box-shadow:none; }
.pd-dot.one{ background:var(--pd-pt-one); }
.pd-dot.full{ background:var(--pd-pt-full); }
.pd-lock-s{ font-size:10px; }
.pm-map.pd-can{ cursor:pointer; }
.pd-label-wrap, .pd-lock-wrap{ background:none; border:none; }
.pd-label{ position:absolute; left:0; top:0; transform:translate(-50%, -50%); white-space:nowrap; font-size:12px; font-weight:600; line-height:1.2; padding:1px 5px; color:var(--pd-ink); background:rgba(255,255,255,.85); border:1px solid var(--pd-line); pointer-events:none; }
.pd-label.ref{ font-weight:500; border-style:dashed; }
.pd-label.bad{ color:var(--pd-bad-ink); border-color:var(--pd-bad-line); background:var(--pd-bad-bg); }
.pd-label.ruler{ color:var(--pd-ruler-ink); border-color:var(--pd-ruler-line); }
.pd-lock{ position:absolute; left:0; top:0; transform:translate(calc(-50% + 9px), calc(-50% - 10px)); font-size:10px; line-height:1; pointer-events:none; text-shadow:0 0 3px var(--pm-halo), 0 0 3px var(--pm-halo); }
.pd-angle{ position:absolute; left:0; top:0; transform:translate(10px, -130%); white-space:nowrap; font-size:12px; font-weight:600; padding:1px 5px; color:var(--pm-ink); background:rgba(255,255,255,.92); border:1px solid var(--pd-angle-line); pointer-events:none; }
.pd-angle.right{ color:var(--pd-ok-ink); border-color:var(--pd-ok-line); background:var(--pd-ok-bg); }
.leaflet-container{ font-family:inherit; }
/* ===== Переучёт места (recount.js): экран места и окно станка; телефон - главное, кнопки не меньше 56 px (перчатки) ===== */
.rc-bb{ min-height:56px; box-sizing:border-box; font-size:14px; text-transform:none; letter-spacing:0; padding:10px 14px; display:inline-flex; align-items:center; justify-content:center; gap:6px; text-align:center; max-width:100%; overflow-wrap:anywhere; }
.rc-bb:disabled{ opacity:.45; cursor:default; }
/* §155: переучёт внутри «Обзора»: полоса сверху, список - сам «Обзор», главная кнопка в нижней панели */
.prop-main.rc-on > .prop-switches, .prop-main.rc-on > .prop-tools, .prop-main.rc-on > .prop-active, .prop-main.rc-on > .prop-mig, .prop-main.rc-on > .prop-scrap, .prop-main.rc-on > .prop-steps, .prop-main.rc-on > .prop-chips, .prop-main.rc-on > .prop-review{ display:none !important; }
.rc-host[hidden]{ display:none; }
.rc-host:not([hidden]){ position:sticky; top:41px; z-index:6; background:var(--bg, var(--panel)); }   /* полоса переучёта остаётся сверху при прокрутке списка */
.rc-strip{ display:flex; flex-direction:column; gap:6px; padding:6px 0 4px; min-width:0; }
.rc-srow{ display:flex; align-items:center; gap:8px; min-width:0; }
.rc-sprog{ flex:none; font-size:20px; font-weight:700; white-space:nowrap; }
.rc-sb{ flex:none; min-height:48px; padding:0 12px; font-size:15px; text-transform:none; letter-spacing:0; }
.rc-sfind{ flex:1 1 auto; min-width:0; }
.rc-smore{ font-size:22px; min-width:48px; }
.rc-sbar{ height:4px; background:var(--panel2); border:1px solid var(--line-soft); }
.rc-sbar i{ display:block; height:100%; background:var(--green); }
.rc-menu{ display:flex; flex-direction:column; gap:6px; padding:8px; border:1px solid var(--line); background:var(--panel); box-shadow:0 4px 16px rgba(0, 0, 0, .4); }
.rc-near{ font-size:12px; }
.rc-ml{ display:block; }
.rc-minfo{ font-size:12.5px; overflow-wrap:anywhere; }
.rc-mi{ min-height:52px; text-transform:none; letter-spacing:0; font-size:16px; justify-content:flex-start; }
.rc-note{ display:flex; align-items:center; justify-content:space-between; gap:8px; padding:6px 10px; margin:4px 0; border:1px solid var(--accent); font-size:14px; }
.rc-note .rc-x{ flex:none; min-height:40px; min-width:40px; }
.rc-doneblock{ display:flex; flex-direction:column; gap:6px; min-width:0; margin-top:8px; }
.rc-doneblock[hidden]{ display:none; }
.rc-donebtn{ min-height:52px; text-align:left; background:var(--panel2); border:1px dashed var(--line); color:var(--text); font-family:inherit; font-size:15px; padding:8px 12px; cursor:pointer; }
.rc-donelist .prop-item, .prop-item.rc-chk{ opacity:.55; }
.rc-mainslot{ display:flex; flex:none; margin-left:8px; }
.rc-mainslot .rc-mainbtn{ min-height:56px; padding:0 18px; font-size:17px; text-transform:none; letter-spacing:0; white-space:nowrap; }
@media (max-width:699px){
  .appbar-actions:has(.rc-mainslot){ flex-wrap:wrap; }
  .rc-mainslot{ order:-1; flex:1 1 100%; margin-left:0; }
  .rc-mainslot .rc-mainbtn{ flex:1; justify-content:center; }
}
.pp-btns .tb-btn.pp-skip{ min-height:52px; font-size:16px; text-transform:none; letter-spacing:0; }
.rc-pass-btns{ justify-content:stretch; }
.rc-pass-btns .tb-btn{ flex:1 1 100%; min-height:48px; text-transform:none; letter-spacing:0; }
.rc-pass-ask .prj-ask-text{ white-space:pre-line; }

.rc-msg{ font-size:13px; color:var(--accent); overflow-wrap:anywhere; }
.rc-msg.empty{ display:none; }
.rc-upbar{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; font-size:12.5px; padding:6px 8px; border:1px dashed var(--line); background:var(--panel2); }
.rc-up-bad{ color:var(--red); }
.rc-sk-box{ display:flex; flex-direction:column; gap:6px; min-width:0; }
.rc-sk{ width:100%; max-height:260px; background:var(--panel2); border:1px solid var(--line); box-sizing:border-box; overflow:hidden; }
.rc-sk .pv-svg{ width:100%; height:100%; display:block; }
.rc-dot{ fill:var(--dim); stroke:var(--panel); stroke-width:.25; cursor:pointer; }
.rc-dot.ok{ fill:var(--green); }
.rc-dot.gone{ fill:var(--red); }
.rc-dot.cur{ stroke:var(--accent); stroke-width:.6; }
.rc-title{ font-size:14px; font-weight:600; overflow-wrap:anywhere; }
.rc-model, .rc-art{ font-size:12px; color:var(--dim); }
.rc-nest{ font-size:12px; color:var(--dim); overflow-wrap:anywhere; }
.rc-mark{ font-size:12.5px; font-weight:600; white-space:nowrap; }
.rc-mark.ok{ color:var(--green); }
.rc-mark.gone{ color:var(--red); }
/* окно станка */
.rc-back{ position:fixed; inset:0; z-index:9990; background:rgba(0,0,0,.55); display:flex; align-items:center; justify-content:center; padding:16px; box-sizing:border-box; zoom:calc(1 / var(--ui-zoom)); }
.rc-win{ display:flex; flex-direction:column; width:min(760px, 100%); height:min(900px, 100%); background:var(--panel); color:var(--text); border:1px solid var(--line); box-sizing:border-box; min-width:0; font-size:13px; }
.rc-wbar{ flex:none; display:flex; align-items:center; gap:8px; padding:8px 10px; border-bottom:1px solid var(--line-soft); min-width:0; }
.rc-nav{ min-height:48px; min-width:84px; text-transform:none; letter-spacing:0; font-size:14px; }
.rc-npos{ flex:1; text-align:center; color:var(--dim); font-size:13px; }
.rc-ftitle{ flex:1; font-size:15px; }
.rc-x{ flex:none; min-width:48px; min-height:48px; font-size:18px; padding:0; }
.rc-wbody{ flex:1; min-height:0; overflow-y:auto; overflow-x:hidden; display:flex; flex-direction:column; gap:10px; padding:10px; min-width:0; }
.rc-wbody.busy{ opacity:.7; }
.rc-wtitle{ margin:0; font-size:18px; line-height:1.25; overflow-wrap:anywhere; }
.rc-wsub{ display:flex; flex-wrap:wrap; align-items:center; gap:4px 10px; margin-top:4px; }
.rc-ab{ font-size:12.5px; margin-top:4px; overflow-wrap:anywhere; }
.rc-sech{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.rc-sect{ flex:1; font-weight:700; }
.rc-note{ font-size:12.5px; overflow-wrap:anywhere; }
.rc-noteedit{ display:flex; flex-wrap:wrap; gap:6px; }
.rc-noteedit .tb-input{ flex:1 1 200px; min-height:44px; box-sizing:border-box; }
.rc-noteedit .tb-btn{ min-height:44px; text-transform:none; letter-spacing:0; }
.rc-bigs{ display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.rc-bigs .rc-bb{ cursor:pointer; }
.rc-rec{ min-height:0; }
.rc-rec:empty{ display:none; }
.rc-comp{ display:flex; flex-direction:column; gap:8px; }
.rc-comp[hidden]{ display:none; }
.rc-ta{ width:100%; box-sizing:border-box; min-height:84px; font-size:15px; font-family:inherit; }
.rc-compb{ display:flex; gap:8px; }
.rc-compb .rc-bb{ flex:1; }
.rc-done{ display:flex; flex-direction:column; gap:6px; border-top:1px dashed var(--line); padding-top:8px; }
.rc-done[hidden]{ display:none; }
.rc-doneh{ font-size:12px; color:var(--dim); }
.rc-media .prj-row-media{ display:flex; flex-wrap:wrap; gap:4px; }
.rc-cmt{ font-size:13px; overflow-wrap:anywhere; }
.rc-upl{ font-size:12.5px; display:flex; flex-wrap:wrap; align-items:center; gap:6px; overflow-wrap:anywhere; }
.rc-wstrip{ flex:none; display:flex; flex-direction:column; gap:6px; padding:8px 10px calc(8px + env(safe-area-inset-bottom)); border-top:1px solid var(--line); background:var(--panel); min-width:0; }
.rc-wstate{ font-size:13px; color:var(--dim); }
.rc-wstate.ok{ color:var(--green); }
.rc-wstate.gone{ color:var(--red); }
.rc-wmsg{ font-size:12.5px; color:var(--accent); overflow-wrap:anywhere; }
.rc-wmsg.empty{ display:none; }
.rc-wacts{ display:flex; gap:8px; }
.rc-wacts .rc-bb{ flex:1; }
.rc-wacts .rc-bb[hidden]{ display:none; }
.rc-fq{ width:100%; box-sizing:border-box; min-height:48px; font-size:15px; }
.rc-fres{ display:flex; flex-direction:column; gap:4px; }
.rc-fhit{ display:flex; flex-direction:column; align-items:flex-start; gap:2px; min-height:56px; text-align:left; background:var(--panel2); border:1px solid var(--line); color:var(--text); font-family:inherit; padding:8px 10px; cursor:pointer; }
.rc-fhit:hover{ border-color:var(--accent); }
.rc-fsum{ font-size:15px; font-weight:600; }
/* Переучёт-2: окно станка */
.rc-emo{ min-width:56px; padding:6px; font-size:26px; line-height:1; cursor:pointer; }
.rc-params{ display:flex; flex-direction:column; gap:8px; min-width:0; }
.rc-pf{ display:flex; flex-direction:column; gap:4px; border:1px solid var(--line-soft); padding:6px 8px; min-width:0; }
.rc-pk{ font-size:12.5px; color:var(--dim); overflow-wrap:anywhere; }
.rc-prow{ display:flex; gap:6px; min-width:0; }
.rc-pin{ flex:1 1 auto; min-width:0; min-height:48px; box-sizing:border-box; font-size:15px; }
.rc-psave{ flex:none; min-height:48px; text-transform:none; letter-spacing:0; font-size:13px; }
.rc-px{ flex:none; min-width:48px; min-height:48px; padding:0; font-size:16px; }
.rc-pmsg{ font-size:12.5px; color:var(--accent); overflow-wrap:anywhere; }
.rc-pmsg.empty{ display:none; }
.rc-padd{ min-height:48px; text-transform:none; letter-spacing:0; font-size:14px; }
.rc-ppick{ display:flex; flex-direction:column; gap:6px; border:1px solid var(--line); padding:8px; min-width:0; }
.rc-pq{ width:100%; box-sizing:border-box; min-height:48px; font-size:15px; }
.rc-pgrp{ font-size:12px; margin-top:2px; }
.rc-plist{ display:flex; flex-direction:column; gap:4px; max-height:30vh; overflow-y:auto; }
.rc-pitem{ display:flex; align-items:center; justify-content:space-between; gap:8px; min-height:44px; text-align:left; background:var(--panel2); border:1px solid var(--line); color:var(--text); font-family:inherit; font-size:14px; padding:6px 10px; cursor:pointer; }
.rc-pitem:hover{ border-color:var(--accent); }
.rc-pitem-n{ overflow-wrap:anywhere; min-width:0; }
.rc-pitem-c{ flex:none; font-size:12px; color:var(--dim); }
.pp-thing-hit{ fill:transparent; stroke:none; pointer-events:all; cursor:grab; touch-action:none; }
@media (max-width:699px){
  .rc-back{ padding:0; }
  .rc-win{ width:100%; height:100%; border:none; }
  .rc-sk{ max-height:200px; }
}
.prj-ask-text{ white-space:pre-line; }

/* ===== Окно станка заново: что ищу → где → записать (recount.js, placepick.js - встроенная карта) ===== */
/* Окно над нижней панелью приложения (она видна всегда и поверх фона; в ней ‹ 3 / 17 › ➕ ✕); внутри одна прокрутка */
.rc-thing-back{ bottom:calc(var(--appbar-h, 58px) * var(--ui-zoom)); }
body.rc-win-on .appbar{ z-index:10020; }
body.rc-win-on .drawer-overlay{ z-index:10025; }
body.rc-win-on .drawer{ z-index:10030; }
.appbar.rc-bar-on .appbar-actions > :not(.rc-appbar){ display:none; }
.appbar.rc-bar-on .appbar-split{ display:none; }
.rc-appbar{ flex:1; min-width:0; display:flex; align-items:center; justify-content:center; gap:6px; }
.rc-appbar .rc-npos{ flex:1 1 auto; min-width:56px; max-width:120px; text-align:center; white-space:nowrap; color:var(--text); font-size:15px; font-weight:600; }
.rc-pbtn{ flex:none; min-width:48px; min-height:48px; padding:0 8px; font-size:22px; line-height:1; text-transform:none; letter-spacing:0; }
.rc-pbtn:disabled{ opacity:.4; cursor:default; }
.rc-thing-back .rc-win{ width:100%; height:100%; position:relative; }
.rc-thing-back .rc-wbody{ gap:0; padding:0; }
.rc-s{ display:flex; flex-direction:column; gap:8px; padding:10px; min-width:0; }
.rc-s + .rc-s{ border-top:1px solid var(--line); }
.rc-wtitle{ font-size:22px; line-height:1.2; }
.rc-wsub{ display:flex; flex-wrap:wrap; align-items:baseline; gap:2px 12px; margin-top:0; font-size:14px; color:var(--dim); }
.rc-pathbox{ display:flex; flex-wrap:wrap; align-items:center; gap:2px 10px; }
.rc-wpath{ font-size:14px; overflow-wrap:anywhere; }
.rc-wpath.changed{ color:var(--accent); font-weight:700; }
.rc-crumb{ font:inherit; font-weight:inherit; color:inherit; background:none; border:0; padding:2px 0; margin:0; cursor:pointer; text-decoration:underline; text-decoration-style:dotted; text-underline-offset:3px; min-height:32px; }   /* звенья пути - нажимаемые (§162) */
.rc-crumb-top::after{ content:' ▾'; text-decoration:none; display:inline-block; }
.rc-pathbox{ position:relative; }
.rc-terrmenu{ position:absolute; left:10px; top:100%; z-index:30; display:flex; flex-direction:column; min-width:180px; max-width:calc(100% - 20px); max-height:50vh; overflow-y:auto; background:var(--panel); border:1px solid var(--line); border-radius:8px; box-shadow:0 4px 14px rgba(0,0,0,.25); padding:4px; gap:2px; }
.rc-terr{ justify-content:flex-start; text-align:left; min-height:44px; text-transform:none; letter-spacing:0; }
.rc-terr.on{ border-color:var(--accent); font-weight:700; }
.rc-revert{ font-size:12.5px; }
.rc-wnote{ min-width:0; }
.rc-off{ visibility:hidden; }
.rc-upind{ flex:none; display:flex; align-items:center; gap:6px; }
.rc-upq{ display:inline-flex; align-items:center; gap:4px; font-size:13px; color:var(--dim); }
.rc-upq b{ color:var(--text); font-weight:700; }
.rc-spin{ width:16px; height:16px; box-sizing:border-box; border:2px solid var(--line); border-top-color:var(--accent); border-radius:50%; animation:rc-spin .8s linear infinite; }
@keyframes rc-spin{ to{ transform:rotate(360deg); } }

/* «Ожидание в окне» (core.js: wtMount / wtDialog, архитектура §6.2): колёсико и подпись по центру окна, ошибка и «Повторить» / «Отмена» там же */
.wt-box{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px; min-height:140px; padding:28px 12px; text-align:center; }
.wt-spin{ width:38px; height:38px; border-width:3px; }
.wt-text{ font-size:15px; color:var(--text); }
.wt-err{ font-size:14px; color:var(--red); max-width:32ch; overflow-wrap:anywhere; }
.wt-btns{ display:flex; gap:10px; justify-content:center; flex-wrap:wrap; }
.wt-dialog{ width:min(360px, 92vw); }
.wt-back{ z-index:10080; cursor:progress; }
.wt-loading .map-picker-search, .wt-loading .prj-pick-create{ display:none; }
.wt-loading .map-picker-list{ max-height:none; }
.wt-back ~ .map-picker-backdrop{ z-index:10090; }
.rc-kindnote{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:8px 12px; margin:0 0 6px; border:1px solid var(--accent-dim); border-radius:8px; font-size:14px; color:var(--text); }.rc-upbad{ min-height:40px; min-width:40px; padding:0 8px; font-size:13px; color:var(--red); border-color:var(--red); text-transform:none; letter-spacing:0; white-space:nowrap; }
.rc-uperr .rc-upl{ padding:6px 0; border-bottom:1px solid var(--line-soft); }
.rc-remind-chk{ display:flex; align-items:center; gap:8px; margin:10px 0 4px; }
.rc-mapbox{ position:relative; margin:0 -10px; }
.rc-map .pp-stage{ height:45vh; min-height:260px; border-left:none; border-right:none; }
.rc-map .pp-actions{ padding:4px 10px 0; min-height:0; }
.rc-map .pp-actions:empty{ display:none; }
.rc-map .pp-legend{ margin-left:0; }
.rc-gone{ position:absolute; left:0; right:0; top:0; bottom:0; z-index:4; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; pointer-events:none; background:rgba(0,0,0,.2); }
.rc-gone[hidden]{ display:none; }
.rc-compass[hidden]{ display:none; }
.rc-cbtn{ width:40px; height:40px; padding:0; font-size:20px; line-height:1; background:var(--pm-halo); color:var(--pm-ink); border-color:var(--line); }
.rc-cbtn[hidden]{ display:none; }
.rc-cn{ font-size:13px; font-weight:700; }
.rc-gone b{ font-size:96px; line-height:1; color:var(--red); text-shadow:0 0 6px var(--pm-halo); }
.rc-gone span{ padding:2px 12px; font-size:24px; font-weight:700; color:var(--pm-ink); background:var(--pm-halo); border:2px solid var(--red); }
.rc-ops{ display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:8px; }
.rc-op{ min-height:56px; padding:6px 4px; font-size:14px; text-transform:none; letter-spacing:0; line-height:1.2; display:flex; align-items:center; justify-content:center; text-align:center; overflow-wrap:anywhere; }
.rc-op:disabled{ opacity:.45; cursor:default; }
.rc-op.rc-ok.on{ border-color:var(--green); background:var(--green-dim); color:var(--green); font-weight:700; }
.rc-op.rc-no.on{ border-color:var(--red); background:var(--red-dim); color:var(--red); font-weight:700; }
.rc-op.rc-opundo:disabled{ color:var(--dim2); border-color:var(--line); }
.rc-state{ min-height:1.5em; font-size:13px; line-height:1.5; color:var(--dim); overflow-wrap:anywhere; }
.rc-state.ok{ color:var(--green); }
.rc-state.gone{ color:var(--red); }
.rc-state.warn, .rc-state.msg{ color:var(--accent); }
.rc-bigs{ display:grid; grid-template-columns:repeat(5, minmax(0, 1fr)); gap:8px; }
.rc-bigs .rc-emo{ min-width:0; }
.rc-card{ text-align:right; }
.rc-sheet{ position:absolute; left:0; right:0; top:0; bottom:0; z-index:6; display:flex; flex-direction:column; justify-content:flex-end; background:rgba(0,0,0,.45); overflow-y:auto; }
.rc-sheet[hidden]{ display:none; }
.rc-sheet .rc-ppick{ max-height:75%; overflow-y:auto; background:var(--panel); border-width:1px 0 0; }
.rc-sheet .rc-plist{ max-height:none; overflow:visible; }
/* встроенная карта: над ней название места крупно и этажи чипами в один ряд (вопроса поверх карты и кнопок 1 / 2 / 3 справа нет), ручка поворота на фигуре */
.pp-embed .pp-floors, .pp-embed .pp-fpick{ display:none !important; }
/* Переучёт-6: замеры рулеткой на встроенной карте и карта на весь экран */
.pp-ml{ pointer-events:none; }   /* §156: линии и цифры замеров нажатий не ловят - палец всегда тянет карту; цифру находит конец нажатия (placepick.js: ppMeasLabelAt) */
.pp-ml-l{ fill:none; vector-effect:non-scaling-stroke; pointer-events:none; }
.pp-ml.est .pp-ml-l{ stroke:var(--pm-ink); stroke-width:1.2; stroke-dasharray:5 4; opacity:.5; }
.pp-ml.set .pp-ml-l{ stroke:var(--pm-ink); stroke-width:2.6; }
.pp-ml-t{ fill:var(--pm-ink); stroke:var(--pm-halo); paint-order:stroke; stroke-linejoin:round; font-weight:700; user-select:none; pointer-events:none; }
.pp-ml.est .pp-ml-t{ font-weight:400; fill-opacity:.7; }
.pp-ml.chk .pp-ml-t{ fill:var(--pt-check); }
.pp-meas{ position:absolute; z-index:7; left:56px; right:8px; top:8px; pointer-events:none; }
.pp-meas[hidden]{ display:none; }
.pp-meas > *{ pointer-events:auto; }
.pp-meas-box{ background:var(--panel); color:var(--text); border:2px solid var(--accent); padding:8px; display:flex; flex-direction:column; gap:6px; }
.pp-meas-t{ font-size:14px; line-height:1.3; }
.pp-meas-row{ display:flex; gap:6px; }
.pp-meas-in{ flex:1 1 auto; min-width:0; min-height:52px; font-size:26px; text-align:center; }
.pp-meas-b{ flex:none; min-width:52px; min-height:52px; padding:0 8px; font-size:20px; text-transform:none; letter-spacing:0; }
.pp-meas-err{ min-height:1.2em; font-size:13px; color:var(--red); }
.pp-meas-note{ background:var(--panel); color:var(--text); border:1px solid var(--line); padding:6px 8px; font-size:13px; line-height:1.35; }

/* ===== Переучёт-7а: окно станка по шагам (recountstep.js) ===== */
.rc-appbar{ justify-content:flex-start; gap:2px; }
.rc-appbar .rc-pbtn{ min-width:40px; padding:0 3px; }
.rc-appbar .rc-nav{ flex:none; display:inline-flex; align-items:center; }
.rc-appbar .rc-npos{ flex:0 1 auto; min-width:44px; max-width:64px; font-size:14px; }
@media (max-width:430px){
  .rc-appbar{ gap:0; }
  .rc-appbar .rc-pbtn{ min-width:34px; padding:0 2px; }
  .rc-appbar .rc-npos{ min-width:34px; font-size:13px; }
}
.rc-thing-back .rc-wbody{ position:relative; }
.rcs-top{ flex:none; display:flex; align-items:center; gap:6px; padding:2px 10px; min-width:0; }
.rcs-head{ flex:1; min-width:0; }
.rcs-head .rc-wtitle{ margin:0; font-size:17px; line-height:1.25; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rcs-head .rc-wsub{ flex-wrap:nowrap; margin:0; font-size:12.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rcs-head .rc-ab{ margin:0; font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rcs-i{ flex:none; min-width:44px; min-height:44px; padding:0; font-size:20px; text-transform:none; letter-spacing:0; }
.rcs-i[hidden]{ display:none; }
.rcs-wmsg{ flex:none; padding:2px 10px; font-size:13px; color:var(--accent); overflow-wrap:anywhere; }
.rcs-wmsg[hidden]{ display:none; }
.rcs-p[hidden]{ display:none; }
.rcs-p.rcs-off{ position:absolute; left:-200vw; top:0; width:100%; visibility:hidden; pointer-events:none; }
.rcs-big{ min-height:60px; font-size:18px; text-transform:none; letter-spacing:0; width:100%; }
.rcs-addpar{ width:100%; min-height:52px; font-size:16px; text-transform:none; letter-spacing:0; border-style:dashed; }
.rcs-big[hidden]{ display:none; }
/* шаг «Найдите» (§164): один экран, без вертикальной прокрутки - большое фото забирает всю свободную высоту, под ним «Признаки:» и «Местоположение:» */
.rc-win[data-step="find"] .rc-wbody{ overflow:hidden; }
.rcs-find{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; gap:6px; padding:4px 10px 8px; overflow:hidden; }
.rcs-fd{ flex:1 1 0; min-height:0; display:flex; flex-direction:column; gap:6px; }
.rcs-hero{ position:relative; flex:1 1 0; min-height:120px; display:flex; flex-direction:column; border:1px solid var(--line); background:var(--panel2); overflow:hidden; }
.rcs-hero0{ align-items:center; justify-content:center; }
.rcs-hs{ flex:1 1 0; min-height:0; display:flex; overflow-x:auto; overflow-y:hidden; scroll-snap-type:x mandatory; touch-action:pan-x; -webkit-overflow-scrolling:touch; scrollbar-width:none; }
.rcs-hs::-webkit-scrollbar{ display:none; }
.rcs-sl{ position:relative; flex:0 0 100%; min-width:0; height:100%; scroll-snap-align:center; scroll-snap-stop:always; cursor:pointer; outline:none; }
.rcs-sl:focus-visible{ box-shadow:inset 0 0 0 2px var(--accent); }
.rcs-sl .rcs-img{ inset:0; }
.rcs-dots{ position:absolute; left:0; right:0; bottom:6px; display:flex; justify-content:center; align-items:center; gap:6px; pointer-events:none; }
.rcs-dot{ width:8px; height:8px; border-radius:50%; background:rgba(255, 255, 255, .55); box-shadow:0 0 0 1px rgba(0, 0, 0, .45); }
.rcs-dot.on{ background:rgb(255, 255, 255); width:10px; height:10px; box-shadow:0 0 0 1.5px rgba(0, 0, 0, .6); }
.rcs-dtext{ padding:1px 8px; font-size:12px; background:rgba(0, 0, 0, .6); color:rgb(255, 255, 255); border-radius:10px; }
.rcs-sec{ flex:none; min-width:0; display:flex; flex-direction:column; gap:3px; }
.rcs-sh{ display:flex; flex-wrap:wrap; align-items:baseline; gap:0 8px; min-width:0; font-size:13px; line-height:1.3; }
.rcs-sh > b{ flex:none; font-size:13.5px; }
.rcs-lpath{ min-width:0; flex:1 1 0; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; overflow:hidden; overflow-wrap:anywhere; color:var(--text); }
.rcs-mic{ display:flex; align-items:center; gap:5px; min-width:0; min-height:44px; overflow-x:auto; overflow-y:hidden; touch-action:pan-x; -webkit-overflow-scrolling:touch; scrollbar-width:none; }
.rcs-mic::-webkit-scrollbar{ display:none; }
.rcs-mi{ position:relative; flex:none; width:44px; height:44px; padding:0; border:1px solid var(--line); background:var(--panel2); color:var(--text); font-family:inherit; overflow:hidden; cursor:pointer; box-sizing:border-box; }
.rcs-mi:hover, .rcs-mi:focus-visible{ border-color:var(--accent); outline:none; }
.rcs-mi .rcs-img, .rcs-mi .rcs-ph{ position:absolute; inset:0; }
.rcs-mi .rcs-ph img, .rcs-mi .rcs-ph video{ object-fit:cover; }
.rcs-mi .rcs-bd{ font-size:10px; padding:0 2px; }
.rcs-mi-t{ font-size:22px; line-height:1; display:flex; align-items:center; justify-content:center; }
.rcs-lrow{ display:flex; align-items:center; gap:8px; min-width:0; }
.rcs-lrow .rcs-mic{ flex:1 1 0; }
.rcs-nums{ flex:1 1 0; display:flex; flex-direction:column; align-items:flex-start; gap:0; min-width:0; font-size:13px; line-height:1.2; }   /* артикул и серийный номер - каждый в своей строке (длинные подписи из базы) */
.rcs-nums .rcs-nsep{ display:none; }
.rcs-num{ display:inline-flex; align-items:center; min-width:0; max-width:100%; gap:3px; }
.rcs-num.editing{ flex:1 1 100%; }
.rcs-nk{ flex:none; color:var(--dim); }
.rcs-nv{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:600; }
.rcs-nsep{ color:var(--dim); }
.rcs-npen{ flex:none; min-width:34px; min-height:34px; padding:0; font-size:15px; text-decoration:none; }
.rcs-nin{ flex:1 1 auto; min-width:0; min-height:36px; font-size:15px; }
.rcs-nb{ flex:none; min-width:36px; min-height:36px; padding:0; font-size:16px; }
.rcs-img{ position:absolute; inset:3px; display:flex; align-items:center; justify-content:center; overflow:hidden; }
.rcs-ph{ position:relative; display:flex; align-items:center; justify-content:center; width:100%; height:100%; pointer-events:none; overflow:hidden; }
.rcs-ph img, .rcs-ph video{ width:100%; height:100%; object-fit:contain; display:block; }
.rcs-ph .prj-thumb-text{ font-size:11px; color:var(--dim); }
.rcs-zsvg{ width:100%; height:100%; display:block; }
.rcs-zfr{ fill:none; stroke:var(--accent); stroke-width:2px; vector-effect:non-scaling-stroke; }
.rcs-none{ font-size:12.5px; color:var(--dim); text-align:center; padding:4px; }
.rcs-bd{ position:absolute; z-index:2; font-size:10.5px; line-height:1.2; padding:1px 4px; background:rgba(0,0,0,.6); color:rgb(255, 255, 255); pointer-events:none; white-space:nowrap; }
.rcs-bd-tl{ left:3px; top:3px; font-size:13px; }
.rcs-bd-tr{ right:3px; top:3px; font-size:12px; }
.rcs-bd-bl{ left:3px; bottom:3px; max-width:70%; overflow:hidden; text-overflow:ellipsis; }
.rcs-bd-br{ right:3px; bottom:3px; font-weight:700; }
.rcs-mini{ position:relative; flex:none; display:flex; flex-direction:column; width:72px; height:72px; padding:0; border:1px solid var(--line); background:var(--panel2); color:var(--text); font-family:inherit; cursor:pointer; overflow:hidden; text-align:left; box-sizing:border-box; }
.rcs-mini:hover, .rcs-mini:focus-visible{ border-color:var(--accent); outline:none; }
.rcs-msk{ flex:1 1 auto; min-height:0; display:flex; align-items:center; justify-content:center; overflow:hidden; pointer-events:none; }
.rcs-msk svg{ width:100%; height:100%; display:block; }
.rcs-ans:disabled{ opacity:.45; cursor:default; }
.rcs-ans.on.rcs-here{ border-color:var(--green); color:var(--green); background:var(--green-dim); }
.rcs-ans.on.rcs-lost{ border-color:var(--red); color:var(--red); background:var(--red-dim); }
@media (max-height:520px){
  .rcs-bar, .rcs-top{ padding-top:0; padding-bottom:0; }
  .rcs-i{ min-height:36px; height:36px; }
  .rcs-ans{ min-height:44px; }
  .rcs-hero{ min-height:80px; }
}
/* шаг 2: габариты */
/* шаг 2 «Габариты» = лист редактора силуэта (silhouette.js): на весь шаг, без вертикальной прокрутки; цвета - токены Админки */
.rc-win[data-step="dimsstep"] .rc-wbody{ overflow:hidden; }
.rcs-dimsec{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
.sl-none{ padding:12px 10px; font-size:14px; }
.sl-wrap{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
.sl-hintrow{ flex:none; padding:6px 12px; font-size:clamp(11px, 3.4vw, 14px); line-height:1.3; letter-spacing:0; text-transform:none; color:var(--dim); text-align:center; white-space:nowrap; }   /* одна строка над листом (на 390 и 360 px помещается) */
.sl-hintrow[hidden]{ display:none; }
.sl-sheet{ position:relative; flex:1 1 0; min-height:0; overflow:hidden; background:var(--panel2); }
.sl-board{ position:absolute; left:0; top:0; width:100%; height:100%; touch-action:none; user-select:none; -webkit-user-select:none; cursor:grab; display:block; }
.sl-grid{ stroke:var(--line-soft); stroke-width:1; fill:none; }
.sl-grid.sl-major{ stroke:var(--line); }
.sl-shape{ fill:var(--accent); fill-opacity:.16; stroke:var(--accent); stroke-width:2.5; stroke-linejoin:round; }
.sl-shape.sl-locked{ stroke:var(--dim); fill:var(--dim); fill-opacity:.14; stroke-dasharray:6 4; }
.sl-hl{ stroke:var(--orange); stroke-width:5; stroke-linecap:round; }
.sl-dot{ fill:var(--panel); stroke:var(--accent); stroke-width:2; }
.sl-dot.on, .sl-pdot{ stroke:var(--orange); }
.sl-piece{ fill:var(--accent); fill-opacity:.16; stroke:var(--orange); stroke-width:2.5; stroke-dasharray:7 5; }
.sl-piece.ok{ stroke:var(--green); }
.sl-ptext{ font:600 12px var(--mono); fill:var(--orange); }
.sl-dimln{ stroke:var(--dim); stroke-width:1; fill:none; }
.sl-lab{ cursor:pointer; }
.sl-lab rect{ fill:var(--panel); stroke:var(--line); }
.sl-lab rect.hit{ fill:transparent; stroke:none; }
.sl-lab.total rect{ stroke:var(--accent); }
.sl-lab.total rect.hit{ stroke:none; }
.sl-lab.live rect{ stroke:var(--orange); }
.sl-lab.live rect.hit{ stroke:none; }
.sl-lab text{ font:600 12px var(--mono); fill:var(--text); }
.sl-lab.live text{ fill:var(--orange); }
.sl-tools{ position:absolute; right:8px; bottom:30%; z-index:2; display:flex; flex-direction:column; gap:8px; }   /* §154: все кнопки столбиком справа (и на 1280), 🗑 сверху, ＋□ самая нижняя - на ~30% высоты листа от низа */
.sl-tool{ width:48px; height:48px; padding:0; display:flex; align-items:center; justify-content:center; border:1px solid var(--line); border-radius:50%; background:var(--panel); color:var(--text); box-shadow:0 2px 8px rgba(0,0,0,.35); cursor:pointer; touch-action:manipulation; }
.sl-tool[hidden]{ display:none; }
.sl-tool:hover, .sl-tool:focus-visible{ border-color:var(--accent); outline:none; }
.sl-tool:disabled{ opacity:.4; cursor:default; box-shadow:none; color:var(--dim); }
.sl-tool svg{ display:block; pointer-events:none; }
.sl-scale{ position:absolute; left:8px; bottom:8px; display:flex; flex-direction:column; gap:3px; font:500 11px var(--mono); color:var(--dim); pointer-events:none; }
.sl-scale i{ display:block; height:4px; border:1px solid var(--dim); border-top:0; }
.sl-lock{ position:absolute; left:0; right:64px; padding:0 24px; text-align:center; color:var(--dim); font-size:14px; line-height:1.5; pointer-events:none; }
.sl-lock{ bottom:28px; }
.sl-edit{ display:flex; flex-direction:column; gap:12px; }
.sl-et{ font-size:16px; }
.sl-erow{ display:flex; align-items:center; gap:8px; }
.sl-num{ flex:1 1 auto; min-width:0; min-height:56px; font:600 24px var(--mono); }
.sl-unit{ font:600 20px var(--mono); color:var(--dim); }
.sl-note{ color:var(--dim); font-size:13px; }
.sl-del{ border-color:var(--red); color:var(--red); }
/* шаг 4 / «Что это»: три блока */
.rcs-blocks{ display:flex; flex-direction:column; gap:10px; }
.rcs-blk{ display:flex; flex-direction:column; gap:8px; padding:10px; border:1px solid var(--line); background:var(--panel2); min-width:0; }
.rcs-bh{ display:flex; align-items:center; gap:8px; }
.rcs-bt{ flex:1; min-width:0; font-size:16px; line-height:1.25; }
.rcs-q{ flex:none; width:36px; height:36px; padding:0; border:0; border-radius:50%; background:none; color:var(--dim); font:700 18px/1 var(--mono); cursor:pointer; filter:grayscale(1); }
.rcs-q:hover, .rcs-q:focus-visible{ border-color:var(--accent); color:var(--accent); outline:none; }
.rcs-brow{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.rcs-bbtn, .rcs-th{ display:contents; }
.rcs-cam{ flex:none; width:44px; min-width:44px; height:44px; min-height:44px; padding:0; display:flex; align-items:center; justify-content:center; font-size:22px; line-height:1; cursor:pointer; }
.rcs-rt{ position:relative; flex:none; width:44px; height:44px; padding:0; border:1px solid var(--line); background:var(--panel); overflow:hidden; display:flex; align-items:center; justify-content:center; }
button.rcs-rt{ cursor:pointer; }
.rcs-rt .rcs-ph{ pointer-events:none; }
.rcs-rt img{ width:100%; height:100%; object-fit:cover; display:block; }
.rcs-rt.pend{ opacity:.8; }
.rcs-rt.voice{ width:auto; min-width:44px; padding:0 6px; }
.rcs-rt .rcs-bd-tl{ left:1px; top:1px; font-size:10px; padding:0 2px; }
.rcs-pi{ font-size:22px; }
.rcs-ring{ position:absolute; left:50%; top:50%; margin:-12px 0 0 -12px; width:24px; height:24px; background:rgba(0,0,0,.35); }
.rcs-dblink{ text-align:center; }
.rcs-dblink[hidden]{ display:none; }
.rcs-dblink .pp-link{ font-size:12.5px; opacity:.8; }
/* просмотр группы на весь экран */
.rcs-view{ position:fixed; inset:0; z-index:10040; background:rgb(0, 0, 0); color:rgb(219, 230, 239); zoom:calc(1 / var(--ui-zoom)); display:flex; flex-direction:column; box-sizing:border-box; overflow:hidden; font-size:14px; }
.rcs-view ~ .map-picker-backdrop{ z-index:10070; }
.rcs-vtop{ flex:none; display:flex; align-items:center; gap:10px; padding:calc(6px + env(safe-area-inset-top)) 10px 6px; }
.rcs-vtitle{ flex:1; min-width:0; font-weight:700; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rcs-vpos{ flex:none; color:var(--dim); }
.rcs-vx{ flex:none; width:44px; height:44px; padding:0; font-size:18px; background:rgba(0,0,0,.55); }
.rcs-vstage{ position:relative; flex:1 1 0; min-height:0; display:flex; align-items:center; justify-content:center; overflow:hidden; touch-action:none; }
.rcs-vstage.zoomed{ cursor:grab; }
.rcs-wrap{ position:absolute; inset:0; margin:auto; will-change:transform; transform-origin:50% 50%; user-select:none; -webkit-user-select:none; }
.rcs-im{ width:100%; height:100%; object-fit:contain; display:block; -webkit-user-drag:none; }
.rcs-ov{ position:absolute; inset:0; pointer-events:none; }
.rcs-vvideo{ max-width:100%; max-height:100%; }
.rcs-vnote{ color:rgb(219, 230, 239); text-align:center; padding:12px; }
.rcs-vnav{ position:absolute; top:50%; z-index:3; width:48px; height:64px; margin-top:-32px; padding:0; font-size:28px; background:rgba(0,0,0,.45); }
.rcs-vnav[hidden]{ display:none; }
.rcs-vprev{ left:4px; }
.rcs-vnext{ right:4px; }
.rcs-vstar{ font-size:34px; line-height:1; color:rgb(255, 200, 61); text-align:center; padding:2px 0; }
.rcs-vbot{ flex:none; max-height:44%; overflow-y:auto; padding:6px 10px calc(8px + env(safe-area-inset-bottom)); text-align:center; }
.rcs-vfm[hidden]{ display:none; }
.rcs-vmsg{ min-height:0; margin-top:4px; font-size:12.5px; color:var(--accent); overflow-wrap:anywhere; }
.rcs-vmsg:empty{ display:none; }
.rcs-vextra{ margin-top:6px; }
.rcs-vbtns{ display:flex; flex-wrap:wrap; justify-content:center; gap:8px; }
.rcs-vbtn{ min-height:52px; padding:4px 14px; font-size:15px; text-transform:none; letter-spacing:0; }
.rcs-vhint{ font-size:12px; margin-bottom:4px; }
.rcs-fr{ position:absolute; box-sizing:border-box; pointer-events:none; }
.rcs-fr.mine{ border:1.5px solid var(--accent); }
.rcs-fr.mine.edit{ border-width:2px; }
.rcs-fr.other{ border:1.5px solid rgba(190,190,190,.85); }
.rcs-frl{ position:absolute; left:0; top:-1.35em; max-width:160%; font-size:11px; line-height:1.2; padding:0 3px; background:rgba(0,0,0,.6); color:rgb(208, 208, 208); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rcs-fh{ position:absolute; width:14px; height:14px; margin:-7px; background:var(--accent); border:2px solid rgb(0, 0, 0); box-sizing:border-box; }
.rcs-fh-nw{ left:0; top:0; }
.rcs-fh-ne{ left:100%; top:0; }
.rcs-fh-sw{ left:0; top:100%; }
.rcs-fh-se{ left:100%; top:100%; }

/* ===== Места: карта на весь экран, окна и шторка, кнопки в нижней панели, удаление места (placewin.js, placedel.js; журнал §143) ===== */
#places-wrap.pw-full{ max-width:none; margin:0; padding:0; gap:0; width:100%; box-sizing:border-box; flex:none; min-height:0; overflow:hidden;
  height:calc(100vh / var(--ui-zoom) - var(--appbar-h, 58px) - var(--topbar-h, 44px)); height:calc(100dvh / var(--ui-zoom) - var(--appbar-h, 58px) - var(--topbar-h, 44px)); }
body.split-on #places-wrap.pw-full{ height:auto; flex:1; }
.pl-wrap.pl-view-map{ flex:1; min-height:0; gap:0; position:relative; }
.pl-wrap.pl-view-map .pl-bar{ display:none; }
.pl-wrap.pl-view-map .pl-cols{ display:flex; flex-direction:column; align-items:stretch; flex:1; min-height:0; gap:0; }
.pl-wrap.pl-view-map .pm-box{ flex:1; min-height:0; gap:0; position:relative; }
.pl-wrap.pl-view-map .pm-stage{ position:relative; flex:1 1 auto; min-height:0; min-width:0; overflow:hidden; }
.pl-wrap.pl-view-map .pm-mapwrap{ position:absolute; inset:0; border:none; }
.pl-wrap.pl-view-map .pm-map{ height:100%; min-height:0; }
.pl-wrap.pl-view-map .pm-libs{ flex:none; border-width:0 0 1px; }
.pl-wrap.pl-view-map .pm-floors{ position:absolute; z-index:1090; left:10px; top:84px; display:flex; flex-direction:column; align-items:stretch; flex-wrap:nowrap; gap:4px; max-width:120px; }
.pl-wrap.pl-view-map .pm-floors-t{ display:none; }
.pl-wrap.pl-view-map .pm-floor{ padding:5px 8px; font-size:12px; text-align:left; overflow-wrap:anywhere; background:var(--panel); box-shadow:0 1px 4px rgba(0,0,0,0.3); }
.pl-wrap.pl-view-map .pm-floor.active{ background:var(--accent-dim); }
.pl-wrap.pl-view-map .pl-msg{ position:absolute; z-index:1250; top:8px; left:50%; transform:translateX(-50%); margin:0; box-sizing:border-box; max-width:min(560px, calc(100% - 140px)); padding:6px 12px;
  background:var(--panel); border:1px solid var(--line); box-shadow:0 2px 10px rgba(0,0,0,0.3); font-size:12px; pointer-events:none; }
.pl-wrap.pl-view-map .pl-msg:empty, .pl-wrap.pl-view-map .pl-msg.pw-msg-old{ display:none; }
.pw-info{ position:absolute; z-index:1240; top:46px; left:50%; transform:translateX(-50%); box-sizing:border-box; max-width:min(560px, calc(100% - 140px)); padding:5px 12px; font-size:12px; color:var(--text);
  background:var(--panel); border:1px solid var(--accent-dim); box-shadow:0 2px 10px rgba(0,0,0,0.3); pointer-events:none; overflow-wrap:anywhere; }
.pw-info[hidden]{ display:none; }
.pw-layer{ position:absolute; inset:0; z-index:1100; pointer-events:none; }
.pw-sheet-head{ display:none; }
.pw-win{ position:absolute; pointer-events:auto; display:flex; flex-direction:column; width:360px; max-width:calc(100% - 16px); max-height:70%; min-height:0; box-sizing:border-box;
  background:var(--panel); border:1px solid var(--line); box-shadow:0 4px 18px rgba(0,0,0,0.38); }
.pw-win-place{ right:12px; top:12px; }
.pw-win-draw{ right:12px; top:56px; }
.pw-win-un{ left:56px; top:12px; width:320px; }
.pw-win[hidden]{ display:none; }
.pw-win.pw-min{ max-height:none; }
.pw-win.pw-min .pw-body{ display:none; }
.pw-head{ flex:none; display:flex; align-items:center; gap:4px; padding:4px 4px 4px 10px; cursor:grab; touch-action:none; user-select:none; background:var(--panel2); border-bottom:1px solid var(--line-soft); }
.pw-win.pw-min .pw-head{ border-bottom:none; }
.pw-title{ flex:1; min-width:0; font-size:12px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pw-hbtn{ flex:none; width:28px; height:28px; padding:0; background:none; border:1px solid transparent; color:var(--dim); font-family:inherit; font-size:13px; line-height:1; cursor:pointer; }
.pw-hbtn:hover{ color:var(--accent); border-color:var(--accent-dim); }
.pw-body{ flex:1 1 auto; min-height:0; overflow:auto; overscroll-behavior:contain; }
.pw-body .pl-panel{ display:block !important; border:none; background:none; }
.pw-body .pm-tools{ border:none; }
.pw-body .pl-back{ display:none; }
.pw-body .pm-unpainted{ border:none; background:none; }
.pw-body .pm-unpainted > summary{ display:none; }
.pw-body .pm-un-list{ max-height:none; }
.pw-search{ padding:8px; border-bottom:1px solid var(--line-soft); }
.pw-search .tb-input{ width:100%; box-sizing:border-box; font-size:13px; padding:8px 10px; }
.pw-found{ display:flex; flex-direction:column; }
.pw-found[hidden], .pm-unpainted[hidden]{ display:none; }
.pw-more-n{ padding:8px 12px; }
.pw-more{ position:absolute; z-index:1300; right:8px; bottom:8px; width:min(340px, calc(100% - 16px)); max-height:80%; overflow:auto; box-sizing:border-box; display:flex; flex-direction:column; gap:6px; padding:8px;
  background:var(--panel); border:1px solid var(--line); box-shadow:0 4px 18px rgba(0,0,0,0.4); }
.pw-more[hidden]{ display:none; }
.pw-more .pm-top{ position:static; display:flex; flex-direction:column; align-items:stretch; flex-wrap:nowrap; gap:6px; }
.pw-more .pm-top .pm-seg, .pw-more .pm-top #pm-free, .pw-more .pm-top #pm-new, .pw-more .pm-top .pt-toggle, .pw-more .pm-top .pm-free-info{ display:none !important; }
.pw-more .pm-top .pm-top-empty{ display:none; }
.pw-more .pq-list{ position:static; width:auto; max-height:40vh; box-shadow:none; margin-top:6px; }
.pw-more .tb-btn{ text-align:left; }
/* нижняя панель на время вида «Карта» (как .rc-appbar у переучёта): остальные кнопки панели спрятаны, ряд не прыгает */
.appbar.pw-bar-on .appbar-actions > :not(.pw-appbar){ display:none; }
.appbar.pw-bar-on .appbar-split{ display:none; }
.pw-appbar{ flex:1; min-width:0; display:flex; align-items:center; justify-content:flex-start; gap:6px; }
.pw-btn{ flex:0 1 auto; display:inline-flex; align-items:center; justify-content:center; gap:5px; min-height:36px; padding:6px 10px; white-space:nowrap; }
.pw-btn[aria-pressed="true"]{ background:var(--accent-dim); border-color:var(--accent); color:var(--text); }
.pw-btn:disabled{ opacity:0.4; cursor:default; }
.pw-ic{ font-size:15px; line-height:1; }
.pw-b-base{ min-width:140px; }
.pw-b-more{ margin-left:auto; }
.pl-del{ display:flex; justify-content:flex-end; margin-top:4px; padding-top:10px; border-top:1px solid var(--line-soft); }
.pl-del-btn{ font-size:11px; padding:4px 10px; color:var(--red); border-color:var(--line); }
.pl-del-btn:hover{ border-color:var(--red); }
.pel-body{ display:flex; flex-direction:column; gap:10px; }
.pel-why{ font-size:14px; line-height:1.45; overflow-wrap:anywhere; }
.pel-list{ max-height:38vh; overflow:auto; display:flex; flex-direction:column; border:1px solid var(--line-soft); }
.pel-group{ display:flex; flex-direction:column; gap:4px; }
.pel-more{ padding:8px 12px; }
.oh-gone{ color:var(--dim); font-style:italic; }
@media (max-width:899px){
  .pw-tx{ display:none; }
  .pw-appbar{ gap:4px; }
  .pw-btn{ flex:1 1 0; min-width:0; padding:6px 0; }
  .pw-b-base{ min-width:0; }
  .pw-b-more{ margin-left:0; }
  .pw-layer{ top:auto; left:0; right:0; bottom:0; display:flex; flex-direction:column; pointer-events:auto; background:var(--panel); border-top:1px solid var(--line); border-radius:12px 12px 0 0;
    box-shadow:0 -4px 16px rgba(0,0,0,0.38); transition:height 0.16s ease-out; }
  .pw-layer.pw-dragging{ transition:none; }
  .pw-layer[data-sheet="half"]{ height:50%; }
  .pw-layer[data-sheet="full"]{ height:calc(100% - 8px); }
  .pw-sheet-head{ display:block; flex:none; padding:0 8px 6px; touch-action:none; user-select:none; }
  .pw-grip{ width:56px; height:5px; margin:9px auto; background:var(--dim); border-radius:3px; opacity:0.6; position:relative; }
  .pw-grip::before{ content:''; position:absolute; inset:-9px -16px; }
  .pw-tabs{ display:flex; gap:6px; }
  .pw-tab{ flex:1 1 0; min-width:0; min-height:34px; padding:4px 6px; font-family:inherit; font-size:12px; color:var(--dim); background:var(--panel2); border:1px solid var(--line); cursor:pointer; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .pw-tab.active{ color:var(--text); border-color:var(--accent); background:var(--accent-dim); }
  .pw-layer:not(.pw-drawing) .pw-tab[data-pw-tab="draw"], .pw-layer.pw-drawing .pw-tab:not([data-pw-tab="draw"]){ display:none; }
  .pw-win{ position:static; display:none; width:auto; max-width:none; max-height:none; flex:1 1 auto; border:none; box-shadow:none; }
  .pw-layer .pw-win.pw-cur:not([hidden]){ display:flex; }
  .pw-layer[data-sheet="head"] .pw-win{ display:none !important; }
  .pw-head{ display:none; }
  .pw-win.pw-min .pw-body{ display:block; }
  .pl-wrap.pl-view-map .pm-floors{ top:70px; }
  .pw-more{ bottom:8px; }
}
/* ===== Вкладка «Система» ===== */
.sys-wrap{ gap:14px; }
.sys-grid{ display:grid; grid-template-columns:1fr; gap:14px; align-items:start; }
@media (min-width:900px){ .sys-grid{ grid-template-columns:1fr 1fr; } }
.sys-card, .sys-head-card{ display:flex; background:var(--panel); border:1px solid var(--line); border-radius:8px; overflow:hidden; min-width:0; }
.sys-strip{ flex:0 0 6px; background:var(--dim2); }
.sys-ok .sys-strip{ background:var(--green); }
.sys-warn .sys-strip{ background:var(--orange); }
.sys-bad .sys-strip{ background:var(--red); }
.sys-body{ flex:1; min-width:0; padding:12px 14px; overflow-wrap:anywhere; }
.sys-head{ display:flex; justify-content:space-between; gap:8px; margin-bottom:4px; }
.sys-title{ font-size:10px; letter-spacing:1.5px; text-transform:uppercase; color:var(--dim); }
.sys-mark{ font-size:10px; color:var(--dim); }
.sys-ok .sys-mark{ color:var(--green); }
.sys-warn .sys-mark{ color:var(--orange); }
.sys-bad .sys-mark{ color:var(--red); }
.sys-main{ font-size:16px; line-height:1.35; color:var(--text); }
.sys-sub{ font-size:11px; color:var(--dim); margin-top:4px; line-height:1.4; }
.sys-bar{ height:8px; border-radius:4px; background:var(--panel2); border:1px solid var(--line); margin-top:8px; overflow:hidden; }
.sys-bar i{ display:block; height:100%; background:var(--green); }
.sys-warn .sys-bar i{ background:var(--orange); }
.sys-bad .sys-bar i{ background:var(--red); }
.sys-logbtn{ margin-top:8px; }
.sys-log{ margin:8px 0 0; padding:8px; background:var(--panel2); border:1px solid var(--line); border-radius:6px; font-size:11px; white-space:pre-wrap; overflow-wrap:anywhere; }
.sys-log[hidden]{ display:none; }
.sys-err{ font-size:12px; margin-top:6px; line-height:1.4; }
.sys-head-card{ flex-direction:column; padding:12px 14px; gap:6px; border-left-width:6px; }
.sys-head-card.sys-ok{ border-left-color:var(--green); }
.sys-head-card.sys-warn{ border-left-color:var(--orange); }
.sys-head-card.sys-bad{ border-left-color:var(--red); }
.sys-head-main{ font-size:16px; overflow-wrap:anywhere; }
.sys-head-sub{ font-size:11px; color:var(--dim); display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.sys-dot{ display:inline-block; width:9px; height:9px; margin-left:6px; border-radius:50%; background:var(--red); vertical-align:middle; }
.appbar-menu{ position:relative; }
.appbar-menu .sys-dot{ position:absolute; top:-2px; right:-3px; margin:0; border:2px solid var(--panel); box-sizing:content-box; }

/* ===== §148: вид места, препятствия, миниатюра здания на карте окна станка (placekind.js, placepick.js) ===== */
.pl-kind{ flex:none; font-size:11px; font-weight:400; color:var(--dim); }
.pz-opts{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:4px; }
.pz-opt.on{ border-color:var(--accent); color:var(--accent); font-weight:700; }
.pz-warn .pel-list{ margin-top:6px; }
.pv-s.pv-obst{ stroke:var(--pv-grey-line); stroke-width:1.2; stroke-dasharray:none; fill-opacity:1; pointer-events:none; cursor:default; }   /* препятствие: серая косая штриховка (узор - в самом рисунке), линия тонкая, нажатие проходит к месту под ним */
pattern[data-pz-hatch] line, #pm-obst-hatch line{ stroke:var(--pv-grey-line); }
.pm-obst{ fill:url(#pm-obst-hatch); fill-opacity:1; stroke:var(--pv-grey-line); stroke-width:1.2; }
.pp-mini{ position:absolute; z-index:3; left:8px; top:8px; display:flex; align-items:flex-start; pointer-events:none; }   /* вверху слева на белой подложке; только показывает, нажатий не ловит: касания проходят на основную карту (§156); знак севера - внутри */
.pp-mini[hidden]{ display:none; }
.pp-mini-hit{ display:block; flex:none; width:100px; height:100px; margin:0; padding:0; box-sizing:border-box; border:1px solid var(--line); border-radius:6px; background:var(--pm-halo); position:relative; pointer-events:none; }
.pp-mini-svg{ display:block; width:100%; height:100%; overflow:hidden; }
.pp-mini-n{ position:absolute; right:3px; top:3px; line-height:0; pointer-events:none; }
.pp-mini-n .pv-north{ width:18px; height:22px; display:block; }
.pp-hasmini .pp-northup{ left:116px; top:8px; }
.pp-ms{ fill:none; stroke:var(--c); stroke-width:1; stroke-linejoin:round; vector-effect:non-scaling-stroke; pointer-events:none; }
.pp-ms-d1{ stroke:var(--pv-dark); stroke-width:1.8; }
.pp-ms-d2{ stroke-width:.8; }
.pp-ms-man{ fill:var(--c); fill-opacity:.12; }
.pp-ms-rest{ stroke-dasharray:3 2; }
.pp-ms.pp-ms-obst{ stroke:var(--pv-grey-line); stroke-width:.8; stroke-dasharray:none; fill-opacity:1; }
.pp-mini-vp{ fill:none; stroke:var(--accent); stroke-width:1.5; vector-effect:non-scaling-stroke; pointer-events:none; }
.pp-mini-dot{ fill:var(--pv-red); stroke:var(--pm-halo); stroke-width:1; vector-effect:non-scaling-stroke; pointer-events:none; }
@media (min-width:900px){
  .pp-mini-hit{ width:140px; height:140px; }
  .pp-hasmini .pp-northup{ left:156px; }
}
/* ===== Выбор вещи в переучёте: «Обзор» в режиме выбора (recountpick.js, §150) ===== */
.rc-back.rc-pick-off{ visibility:hidden; pointer-events:none; }
.rc-appbar[hidden]{ display:none; }
.rc-pickstrip{ position:sticky; top:0; z-index:30; display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px; padding:8px 10px; background:var(--panel); border:1px solid var(--accent); box-sizing:border-box; min-width:0; }
.rc-pick-t{ flex:1 1 200px; min-width:0; font-size:15px; }
.rc-pick-btns{ display:flex; gap:8px; flex:1 1 280px; min-width:0; justify-content:flex-end; }
.prop-views[hidden]{ display:none; }
.rc-pick-new{ flex:1 1 0; min-width:0; min-height:48px; padding:0 12px; font-size:17px; font-weight:700; text-transform:none; letter-spacing:0; }
.rc-pick-x{ flex:none; min-height:48px; padding:0 14px; font-size:16px; text-transform:none; letter-spacing:0; white-space:nowrap; }
.rc-pick-msg{ flex:1 1 100%; font-size:13px; color:var(--dim); }
.rc-pickbar{ justify-content:flex-start; gap:8px; }
.rc-pickbar .rc-pick-new, .rc-pickbar .rc-pick-x{ min-height:48px; }
.rc-pickbar .rc-pick-new{ flex:1 1 auto; min-width:0; }
.prop-pick-i{ flex:none; align-self:flex-start; width:40px; height:40px; padding:0; border-radius:50%; border:1px solid var(--line); background:var(--panel2); color:var(--text); font-size:20px; line-height:1; cursor:pointer; }
.prop-pick-i:hover, .prop-pick-i:focus-visible{ border-color:var(--accent); outline:none; }
.prop-inlist{ align-self:flex-start; font-size:11px; line-height:16px; padding:0 7px; border:1px solid var(--accent); border-radius:9px; color:var(--accent); }
@media (max-width:430px){
  .rc-pickbar{ gap:6px; }
  .rc-pickbar .rc-pick-new, .rc-pickbar .rc-pick-x, .rc-pickstrip .rc-pick-new, .rc-pickstrip .rc-pick-x{ padding:0 6px; font-size:14px; line-height:1.15; }
}

/* ===== «Обзор» (журнал §152): строка 1 - виды, строка 2 - поиск, 📍, «Фильтры», строка 3 - чипы включённых фильтров; окно «Фильтры»; значки в нижней панели ===== */
.prop-switches{ gap:4px 10px; }
.prop-views .prop-view-btn{ box-sizing:border-box; height:34px; min-height:0; padding:0 12px; line-height:1.2; }
.prop-tools{ flex-wrap:nowrap; align-items:stretch; gap:6px; }
.prop-tools #prop-search{ flex:1 1 auto; min-width:0; }
.prop-placeset{ flex:none; }
.prop-placebtn, .prop-filters-btn{ flex:none; min-width:44px; min-height:40px; padding:0 10px; display:inline-flex; align-items:center; justify-content:center; text-align:center; font-size:18px; position:relative; }
.prop-filters-btn.active, .prop-placebtn.active{ border-color:var(--accent); color:var(--accent); }
.prop-ico{ display:block; }
.prop-fbadge{ position:absolute; top:-7px; right:-7px; min-width:18px; height:18px; box-sizing:border-box; padding:0 4px; border-radius:9px; background:var(--accent); color:#06222b; font-size:11px; font-weight:700; line-height:18px; text-align:center; }
.prop-active{ display:flex; flex-wrap:wrap; gap:6px; min-width:0; }
.prop-active:empty{ display:none; }
.prop-achip{ display:inline-flex; align-items:center; gap:2px; max-width:100%; box-sizing:border-box; padding:2px 2px 2px 10px; border:1px solid var(--accent); color:var(--accent); background:rgba(52,213,255,0.08); }
.prop-achip-t{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.prop-achip .pl-chip-x{ flex:none; min-width:28px; min-height:28px; color:inherit; }
.prop-summary{ font-size:12px; color:var(--dim); min-height:16px; }
.prop-more{ display:flex; justify-content:center; align-items:center; width:100%; padding:16px 0; }
.prop-more .rc-spin{ width:22px; height:22px; }
.prop-branchrow{ display:flex; align-items:center; gap:8px; width:100%; min-height:44px; box-sizing:border-box; padding:6px 12px; background:var(--panel); border:1px solid var(--line); color:var(--text); font-family:inherit; font-size:14px; text-align:left; cursor:pointer; }
.prop-branchrow[hidden]{ display:none; }
.prop-branchrow-t{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.prop-branchrow-c{ flex:none; color:var(--dim); }
.prop-fsheet[hidden]{ display:none; }
.prop-fs-box{ display:flex; flex-direction:column; gap:10px; width:min(520px, 100%); max-height:calc(100% - 8px); box-sizing:border-box; padding:12px; margin:auto; font-family:inherit; font-size:13px; }
.prop-fs-head{ display:flex; align-items:center; gap:8px; }
.prop-fs-head b{ flex:1; font-size:15px; }
.prop-fs-body{ display:flex; flex-direction:column; gap:12px; min-height:0; overflow:auto; }
.prop-fs-sec{ display:flex; flex-direction:column; gap:6px; min-width:0; }
.prop-fs-sec[hidden]{ display:none; }
.prop-fs-h{ font-size:18px; line-height:1; color:var(--dim); }
.prop-fs-chips{ flex-direction:row; flex-wrap:wrap; }
.prop-fs-chips:empty{ display:none; }
.prop-fs-t{ font-size:12px; color:var(--dim); }
.prop-miss-found{ display:flex; flex-direction:column; gap:4px; max-height:30vh; overflow:auto; }
.prop-miss-found .prm-pick{ min-height:40px; text-align:left; }
.ow-file-btns .ow-file-pick{ min-width:48px; justify-content:center; font-size:18px; }
.prop-fs-foot .tb-btn{ width:100%; min-height:44px; }
.prop-fs-box .tb-input{ min-height:40px; }
.prop-fields-pop.up{ position:fixed; z-index:9998; top:auto; left:8px; right:8px; bottom:calc(var(--appbar-h, 58px) + 8px); margin:0; max-width:none; width:auto; }
@media (min-width:640px){ .prop-fields-pop.up{ left:auto; right:16px; width:260px; } }
.prop-bar-grp{ display:inline-flex; align-items:center; gap:8px; margin-left:auto; }
.prop-bar-btn{ width:42px; height:42px; }
.prop-bar-btn.active{ border-color:var(--accent); color:var(--accent); }
.prop-bar-review{ min-height:42px; padding:0 12px; font-size:13px; }
/* ===== «Двигать» прицелом (thingmove.js, журнал §152) ===== */

/* ===== §153: карта «прицел» - шаг «Место» на весь шаг, правый столбик кнопок, ручка поворота под вещью, чипы территорий ===== */
.rc-win[data-step="where"] .rc-wbody{ overflow:hidden; }
.rc-where{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
.rc-where[hidden]{ display:none; }
.rcs-p.rcs-off.rc-where{ height:100%; }
.rc-where .rc-pathbox{ flex:none; padding:4px 10px 0; }
.rc-where .rc-wpath{ font-size:15px; font-weight:700; }
.rc-where .rc-wpath.ask{ color:var(--accent); }
.rc-where .rc-wnote{ flex:none; padding:0 10px; }
.rc-where .rc-mapbox{ flex:1 1 auto; min-height:0; margin:0; display:flex; flex-direction:column; }
.rc-where .rc-map{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
.rc-where .rc-map .pp-stagewrap{ flex:1 1 0; min-height:0; }
.rc-where .rc-map .pp-stagewrap, .rc-where .rc-map .pp-stage{ height:100%; }
.rc-where .rc-map .pp-stage{ min-height:0; }
.rc-where .rc-map .pp-actions{ display:none; }
.rc-where .rc-state{ flex:none; padding:0 10px 2px; }
.pp-embed .pp-floors, .pp-embed .pp-fpick{ display:none !important; }
/* чипы территорий первого уровня и «Все» - над картой */
.pp-terrbar{ flex:none; padding:4px 10px; min-width:0; }
.pp-terrbar[hidden]{ display:none; }
.pz-terr{ display:flex; flex-wrap:nowrap; gap:6px; overflow-x:auto; padding-bottom:2px; min-width:0; }
.pz-terr-b{ flex:none; min-height:40px; padding:0 14px; font-size:14px; }
.pz-terr-b.on{ border-color:var(--accent); color:var(--accent); background:color-mix(in srgb, var(--accent) 14%, var(--panel)); font-weight:700; }
/* «Глубже: Стеллаж 3, Стеллаж 4» - ненарисованные дети выбранного места, мелко */
.pp-deeper{ position:absolute; z-index:4; left:8px; right:72px; bottom:8px; padding:2px 8px; font-size:12px; line-height:1.3; color:var(--pm-ink); background:color-mix(in srgb, var(--pm-halo) 88%, transparent); border-radius:8px; box-shadow:0 1px 4px rgba(0, 0, 0, 0.35); width:fit-content; max-width:calc(100% - 80px); }   /* поверх карты внизу слева: высота карты не прыгает, когда «Глубже» появляется и пропадает (§156) */
.pp-deeper[hidden]{ display:none; }
.pp-deeper-b{ min-height:30px; padding:2px 9px; margin:2px 3px 2px 0; font-size:12.5px; }
/* правый столбик (сверху вниз): этажи, 🔍−, 🔍+, 🧭; «Далее» - в нижней панели справа */
.pp-rcol{ position:absolute; z-index:5; right:8px; bottom:8px; display:flex; flex-direction:column; align-items:flex-end; gap:6px; max-height:calc(100% - 16px); }
.pp-efloors{ position:absolute; z-index:6; right:8px; top:8px; display:flex; flex-direction:column; align-items:flex-end; }   /* одна кнопка «2 эт ▾» у верхнего края карты (§164); список этажей раскрывается вниз */
.pp-eflist{ position:absolute; right:0; top:calc(100% + 6px); display:flex; flex-direction:column; gap:6px; align-items:flex-end; max-height:min(45vh, 300px); overflow-y:auto; padding:2px 8px 10px 14px; margin:0 -8px 0 0; }   /* поля - чтобы тень кнопок не обрезалась прокруткой */
.pp-efbtn{ min-width:48px; max-width:96px; font-size:14px; padding:0 8px; }
.pp-efbtn.open{ border-color:var(--accent); }
.pp-efloors[hidden]{ display:none; }
.pp-efl{ flex:none; min-width:48px; max-width:120px; min-height:48px; padding:0 10px; font-size:15px; text-transform:none; letter-spacing:0; background:var(--pm-halo); color:var(--pm-ink); border:1px solid rgba(0, 0, 0, 0.12); border-radius:24px; box-shadow:0 2px 6px rgba(0, 0, 0, 0.45); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pp-efl.active{ border-color:var(--accent); background:var(--accent); color:#fff; font-weight:700; }
.pp-efl.pend{ border:2px solid var(--accent); color:var(--accent); background:color-mix(in srgb, var(--accent) 18%, var(--pm-halo)); font-weight:700; }
.pp-efl-all{ font-size:13px; }
.pp-zb, .pp-rcol .rc-cbtn{ flex:none; width:48px; height:48px; min-width:48px; padding:0; font-size:17px; line-height:1; background:var(--pm-halo); color:var(--pm-ink); border:1px solid rgba(0, 0, 0, 0.12); border-radius:50%; box-shadow:0 2px 6px rgba(0, 0, 0, 0.45); }   /* белый круг с тенью: видно на спутнике (§156) */
.pp-zb.active{ background:var(--accent); color:#fff; border-color:var(--accent); }
.pp-rcol .rc-compass{ position:static; display:flex; flex-direction:column; gap:6px; }
.pp-rcol .rc-compass[hidden]{ display:none; }
.pp-rcol .rc-cbtn{ font-size:22px; }
/* прицел: вещь в центре карты, ручка поворота под ней */
.tm-aim{ position:absolute; inset:0; z-index:6; pointer-events:none; overflow:hidden; }
.tm-aim[hidden]{ display:none; }
.tm-handle{ position:absolute; left:50%; top:75%; width:56px; height:56px; margin:-28px 0 0 -28px; padding:0; border:0; background:none; pointer-events:auto; touch-action:none; cursor:grab; -webkit-tap-highlight-color:transparent; }
.tm-handle[hidden]{ display:none; }
.tm-handle i{ display:flex; align-items:center; justify-content:center; width:44px; height:44px; margin:6px; border-radius:50%; box-sizing:border-box; background:var(--accent); color:#fff; font-style:normal; font-size:26px; line-height:1; box-shadow:0 0 0 3px var(--pm-halo), 0 2px 6px rgba(0, 0, 0, 0.4); }
.tm-msg{ position:absolute; left:50%; top:8px; transform:translateX(-50%); max-width:calc(100% - 140px); padding:4px 10px; background:rgba(0, 0, 0, 0.7); color:#fff; font-size:13px; line-height:1.3; border-radius:6px; text-align:center; pointer-events:none; }
.tm-msg.empty{ display:none; }
.tm-cross{ position:absolute; left:50%; top:50%; width:60px; height:60px; margin:-30px 0 0 -30px; pointer-events:none; }   /* красный крест прицела (§152, §162), только пока вещь мельче TM.CROSS_PX (thingmove.js) */
.tm-cross .tm-x{ display:block; }
.tm-cross[hidden]{ display:none; }
.pp-stage{ touch-action:none; }
/* §154: шаг «Параметры» - заполненные поля вещи: у каждого «✓ Верно» / «✏ Изменить», внизу серым - пустые важные */
.rcs-parsec{ display:flex; flex-direction:column; gap:12px; padding-bottom:24px; }
.rcp-list{ display:flex; flex-direction:column; gap:8px; }
.rcp-f{ display:flex; flex-direction:column; gap:6px; border:1px solid var(--line-soft); padding:8px 10px; min-width:0; }
.rcp-f.ok{ border-color:var(--accent); background:color-mix(in srgb, var(--accent) 8%, transparent); }
.rcp-k{ font-size:12.5px; color:var(--dim); overflow-wrap:anywhere; }
.rcp-val{ display:flex; align-items:center; gap:8px; justify-content:space-between; min-width:0; }
.rcp-vt{ font-size:16px; overflow-wrap:anywhere; min-width:0; }
.rcp-acts, .rcp-eb{ display:flex; flex-wrap:wrap; gap:8px; }
.rcp-b{ min-height:48px; padding:0 14px; font-size:15px; text-transform:none; letter-spacing:0; }
.rcp-okb.on{ border-color:var(--accent); color:var(--accent); font-weight:700; }
.rcp-in{ width:100%; min-height:48px; font-size:16px; box-sizing:border-box; }
.rcp-ta{ min-height:96px; resize:vertical; }
.rcp-err{ color:var(--bad, #d33); font-size:13px; }
.rcp-empty{ display:flex; flex-direction:column; gap:8px; margin-top:4px; }
.rcp-et{ font-size:12.5px; }
.rcp-add{ min-height:48px; text-transform:none; letter-spacing:0; border-style:dashed; color:var(--dim); justify-content:flex-start; }
.rcp-ef{ border-style:dashed; }
.rcp-none{ padding:12px 0; }

/* ===== §163: окно вещи-2 - строка состояния, серые шаги, чипы шагов, «Сверьте» блоками, «Где искать?», способ измерения, блокировка прокрутки фона ===== */
body.rc-win-on{ overflow:hidden; }
.rc-back, .rc-wbody{ overscroll-behavior:contain; }
body.rc-win-on #rc-upind{ display:none; }
.rcs-stat{ flex:none; padding:0 10px; border-bottom:1px solid var(--line-soft); }
.rcs-sbar{ height:3px; margin:0 -10px; background:var(--line-soft); }
.rcs-sbar i{ display:block; height:100%; background:var(--accent); }
.rcs-srow{ display:flex; align-items:center; gap:12px; min-height:24px; font-size:13px; color:var(--dim); }
.rcs-left{ font-weight:600; color:var(--text); }
.rcs-up{ margin-left:auto; display:inline-flex; align-items:center; gap:3px; font-weight:600; color:var(--text); }
.rcs-upbad{ margin-left:auto; min-height:24px; padding:0 4px; color:var(--red); font-weight:600; }
.rcs-up + .rcs-upbad{ margin-left:0; }
/* Переучёт без связи (recountq.js): значок у вещи, строка «⏳ N ждут связи», скачивание задания */
.rcq-m{ display:inline-block; margin-left:6px; font-size:13px; font-weight:600; vertical-align:middle; }
.rcq-m.bad{ color:var(--red); }
.rcq-m.ok{ color:var(--green, #2e7d32); }
.rcq-wait,.rcq-bad{ min-height:24px; padding:0 4px; font-weight:600; }
.rcq-bad{ color:var(--red); }
.rcq-dl{ margin-left:auto; font-size:12px; color:var(--dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; }
.rcs-srow .rcs-left{ white-space:nowrap; }
.rcq-ind{ gap:4px; }
body.rc-win-on #rcq-ind{ display:none; }
.rcs-st.off{ opacity:.45; }
.rcs-st.off.cur{ opacity:.8; }
.rcs-st.off .rcs-mk{ filter:grayscale(1); }
.rcs-cfg{ display:flex; flex-direction:column; gap:6px; }
.rcs-chips{ display:flex; flex-wrap:wrap; gap:6px; }
.rcs-chip{ min-height:40px; padding:0 12px; border:1px solid var(--line); background:transparent; color:var(--dim); font-family:inherit; font-size:14px; cursor:pointer; text-transform:none; letter-spacing:0; }
.rcs-chip.on{ border-color:var(--accent); color:var(--text); background:color-mix(in srgb, var(--accent) 14%, transparent); font-weight:700; }
.rcs-cfgchk{ display:flex; align-items:center; gap:8px; min-height:36px; font-size:14px; cursor:pointer; }
.rcs-cfgchk input{ width:20px; height:20px; }
.rcs-cfgdlg .rcs-cfg{ margin:10px 0 4px; }
/* «Где искать?» после «Не найдено» */
.rcs-look{ flex:none; display:flex; flex-direction:column; gap:6px; padding:8px 10px; margin-bottom:6px; border:1px solid var(--line); background:var(--panel2); }
.rcs-lookb{ display:flex; flex-wrap:wrap; gap:8px; }
.rcs-lookb .tb-btn{ min-height:48px; padding:0 16px; font-size:16px; text-transform:none; letter-spacing:0; }
.rcs-lookta{ width:100%; min-height:72px; box-sizing:border-box; font-size:16px; }
.rcs-lookm{ font-size:13px; color:var(--accent); }
.rcs-lookm.err{ color:var(--red); }
/* способ измерения (234) под листом силуэта */
.rcs-meth{ flex:none; display:flex; align-items:center; gap:10px; padding:6px 10px; border-top:1px solid var(--line); background:var(--panel); }
.rcs-methk{ flex:none; font-size:14px; color:var(--dim); }
.rcs-methsel{ flex:1 1 auto; min-width:0; min-height:44px; font-size:16px; }
/* оранжевая точка на блоке «Признаки», когда признаков нет (§164) */
.rcs-odot{ flex:none; width:13px; height:13px; border-radius:50%; background:var(--orange); }
.rcs-odot[hidden]{ display:none; }
/* «Сверьте»: блок на параметр, название крупно и сразу «+», значения строками «значение · ✏ · ✓» (§164) */
.rcp-bot{ display:flex; justify-content:flex-end; margin-top:12px; }
.rcp-plus{ min-height:44px; padding:0 14px; font-size:15px; text-transform:none; letter-spacing:0; }
.rcp-f .rcp-k{ display:flex; align-items:center; flex-wrap:wrap; gap:4px 8px; font-size:25px; line-height:1.2; color:var(--text); font-weight:600; }
.rcp-kn{ min-width:0; overflow-wrap:anywhere; }
/* «+» у названия параметра: мелкий серый знак без рамки и фона; тап-зона больше самого знака (::after), а рядом с последним словом он не отрывается на другую строку */
.rcp-nw{ white-space:nowrap; }
.rcp-pl{ position:relative; display:inline-block; min-width:0; min-height:0; margin:0 0 0 4px; padding:0 4px; border:0; border-radius:4px; background:none; box-shadow:none; color:var(--dim); font:inherit; font-size:0.62em; font-weight:400; line-height:1; text-transform:none; cursor:pointer; vertical-align:baseline; }
.rcp-pl::after{ content:''; position:absolute; inset:-14px -10px; }
.rcp-pl:hover, .rcp-pl:focus-visible{ color:var(--text); }
.rcp-f.ok{ border-color:var(--green); background:var(--green-dim); }
.rcp-vr{ display:flex; align-items:center; gap:8px; min-width:0; padding:2px 4px; border:1px solid transparent; }
.rcp-vr.ok{ border-color:var(--green); background:var(--green-dim); }
.rcp-ed{ flex:none; min-width:48px; min-height:48px; padding:0; font-size:18px; text-transform:none; }
.rcp-edoff{ display:block; }
.rcp-vr .rcp-vt{ flex:1 1 auto; min-width:0; }
.rcp-prev{ display:block; font-size:12px; color:var(--dim); }
.rcp-vb{ flex:none; min-width:52px; min-height:48px; padding:0; font-size:22px; font-weight:700; text-transform:none; color:var(--dim); }
.rcp-vb.on{ border-color:var(--green); color:var(--green); background:var(--green-dim); }
.rcp-rm{ align-self:center; min-height:44px; padding:0 4px; font-size:15px; font-weight:400; }
.rcp-del{ margin-left:auto; }

/* ===== §159: окно вещи переучёта - название и ⓘ, полоса шагов, действия шага внизу окна, итог; нижняя панель «« N / M »» · «Не сейчас» · «⋯» ===== */
.rcs-bar{ flex:none; display:grid; grid-auto-flow:column; grid-auto-columns:minmax(0, 1fr); align-items:end; gap:2px; padding:2px 6px 0; border-bottom:1px solid var(--line); min-width:0; }
.tw-tab, .rcs-st{ position:relative; display:flex; flex-direction:column; align-items:center; justify-content:flex-end; gap:3px; min-width:0; min-height:56px; padding:4px 1px 6px; border:0; border-bottom:3px solid transparent; background:none; color:var(--dim); font-family:inherit; cursor:pointer; text-transform:none; letter-spacing:0; }
.tw-tab .rcs-sn, .rcs-st .rcs-sn{ max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:12.5px; line-height:1.2; }
.rcs-st.done{ color:var(--text); }
.tw-tab.cur, .rcs-st.cur{ color:var(--text); border-bottom-color:var(--accent); background:color-mix(in srgb, var(--accent) 12%, var(--panel)); }
.tw-tab.cur .rcs-sn, .rcs-st.cur .rcs-sn{ font-size:16px; font-weight:700; }
.tw-tab:focus-visible, .rcs-st:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px; }
.rcs-mk{ display:block; width:20px; height:20px; border-radius:50%; box-sizing:border-box; font:700 14px/20px var(--mono); font-style:normal; text-align:center; }
.rcs-st.done .rcs-mk{ background:var(--green-dim); color:var(--green); }
.rcs-st.todo .rcs-mk{ background:transparent; position:relative; }
.rcs-st.todo .rcs-mk::after{ content:''; position:absolute; left:50%; top:50%; width:11px; height:11px; margin:-5.5px 0 0 -5.5px; border-radius:50%; background:var(--orange); }
.tw-tab.cur .rcs-mk, .rcs-st.cur .rcs-mk{ width:24px; height:24px; line-height:24px; }
.rcs-st.cur.todo .rcs-mk::after{ width:13px; height:13px; margin:-6.5px 0 0 -6.5px; }
.rcs-head .rc-wtitle{ font-size:19px; font-weight:700; }
/* действия шага: над нижней панелью, внутри окна */
.rcs-foot{ flex:none; display:flex; align-items:center; justify-content:space-between; gap:10px; padding:8px 10px; border-top:1px solid var(--line); background:var(--panel); }
.rcs-foot:empty{ display:none; }
.rcs-skip{ flex:none; min-height:44px; padding:0 8px; font-size:13px; color:var(--dim); text-decoration:underline; background:none; border:0; cursor:pointer; font-family:inherit; }
.rcs-skip:disabled{ opacity:.45; cursor:default; }
.rcs-facts{ flex:1 1 auto; min-width:0; display:flex; justify-content:flex-end; gap:8px; }
.rcs-ans, .rcs-done{ min-height:56px; padding:0 14px; font-size:17px; font-weight:700; text-transform:none; letter-spacing:0; white-space:nowrap; flex:1 1 0; min-width:0; max-width:220px; overflow:hidden; text-overflow:ellipsis; }
.rcs-done{ flex:0 1 220px; min-width:120px; }
.rcs-ans:disabled, .rcs-done:disabled{ opacity:.45; cursor:default; }
.rcs-ans.on.rcs-here{ border-color:var(--green); color:var(--green); background:var(--green-dim); }
.rcs-ans.on.rcs-lost{ border-color:var(--red); color:var(--red); background:var(--red-dim); }
.rcs-foot-sum{ justify-content:center; }
.rcs-foot-sum .rcs-next{ width:auto; min-width:240px; max-width:100%; }
/* итог */
.rcs-sum{ flex:1 1 auto; min-height:0; display:flex; align-items:center; justify-content:center; padding:12px 16px; overflow:auto; }
.rcs-sumbox{ display:flex; flex-direction:column; align-items:center; gap:10px; text-align:center; max-width:420px; }
.rcs-sumok{ width:96px; height:96px; border-radius:50%; background:var(--green-dim); color:var(--green); font-size:64px; line-height:96px; font-weight:700; }
.rcs-sumt{ font-size:26px; font-weight:700; }
.rcs-suml{ font-size:15px; line-height:1.9; }
.rcs-sumk{ color:var(--dim); }
.rcs-sumgo{ min-height:40px; padding:0; margin:0 2px; font-size:16px; font-weight:700; color:var(--orange); }
.rcs-sumend{ font-size:20px; font-weight:700; color:var(--green); }
/* отмена изменений места - под картой */
.rcs-undorow{ flex:none; padding:2px 10px 0; }
.rcs-undorow:has(.rcs-undo[hidden]){ display:none; }
.rcs-undo{ min-height:44px; padding:0 12px; font-size:14px; text-transform:none; letter-spacing:0; }
.rcs-undo[hidden]{ display:none; }
/* «Уточнение»: строка-кнопка в одну строку и раскрывающиеся способы */
.rcs-nline{ display:flex; align-items:center; gap:6px; width:100%; min-height:40px; padding:0 4px; border:0; background:none; color:var(--text); font-family:inherit; font-size:14px; text-align:left; cursor:pointer; text-transform:none; letter-spacing:0; }
.rcs-nk{ flex:none; font-weight:700; }
.rcs-nt{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--dim); }
.rcs-nc{ flex:none; color:var(--dim); }
.rcs-nacts{ display:flex; flex-wrap:wrap; gap:6px; padding:2px 0 6px; }
.rcs-nacts .tb-btn{ min-height:44px; padding:0 14px; font-size:15px; text-transform:none; letter-spacing:0; }
.rcs-nvid{ display:inline-flex; align-items:center; justify-content:center; gap:6px; cursor:pointer; }
.rcs-nvid.off{ opacity:.45; pointer-events:none; }
.rcs-nmsg{ font-size:13px; color:var(--accent); overflow-wrap:anywhere; padding-bottom:4px; }
.rcs-nmsg.err{ color:var(--red); }
/* нижняя панель окна: «« N / M »» · «Не сейчас» · «⋯» */
.rc-appbar{ position:relative; justify-content:space-between; gap:6px; }
.rc-appbar .rc-nav{ flex:1 1 auto; justify-content:flex-start; gap:2px; }
.rc-appbar .rc-pbtn{ min-width:44px; min-height:48px; padding:0 4px; }
.rc-appbar .rc-npos{ flex:0 1 auto; min-width:56px; max-width:84px; font-size:15px; font-weight:600; color:var(--text); text-align:center; white-space:nowrap; }
.rc-later{ flex:none; min-height:48px; padding:0 10px; font-size:12.5px; line-height:1.15; text-transform:none; letter-spacing:0; display:inline-flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; }
.rc-later span{ display:block; }
.rc-appbar .rc-npos{ display:inline-flex; flex-direction:column; align-items:center; line-height:1.1; }
.rc-npos small{ font-size:11px; font-weight:400; color:var(--dim); }
.rc-npos b{ font-size:15px; white-space:nowrap; }
.rc-later:disabled{ opacity:.45; cursor:default; }
.rc-more{ flex:none; font-size:22px; }
.rc-pmenu{ position:absolute; right:0; bottom:calc(100% + 10px); z-index:20; min-width:220px; display:flex; flex-direction:column; gap:2px; padding:4px; background:var(--panel); border:1px solid var(--line); box-shadow:0 -4px 18px rgba(0,0,0,.4); }
.rc-pmenu[hidden]{ display:none; }
.rc-pmenu .tb-btn{ justify-content:flex-start; min-height:48px; padding:0 14px; font-size:15px; text-transform:none; letter-spacing:0; text-align:left; }
.rc-pmenu .tb-btn:disabled{ opacity:.45; }
@media (max-width:430px){
  .rc-appbar{ gap:2px; }
  .rc-appbar .rc-pbtn{ min-width:38px; }
  .rc-appbar .rc-npos{ min-width:48px; font-size:14px; }
  .rc-later{ padding:0 5px; font-size:11.5px; }
  .tw-tab .rcs-sn, .rcs-st .rcs-sn{ font-size:11.5px; }
  .tw-tab.cur .rcs-sn, .rcs-st.cur .rcs-sn{ font-size:12.5px; font-weight:700; letter-spacing:-.2px; }
  .rcs-foot{ gap:6px; padding:8px 6px; }
  .rcs-skip{ padding:0 4px; font-size:12px; }
  .rcs-facts{ gap:6px; }
  .rcs-ans, .rcs-done{ padding:0 4px; font-size:15px; min-width:0; }
}
/* §159: полоска «Убрано · Вернуть», блок «Убрано (N) ▸» в «Обзоре», метка «на глаз» */
.rcs-toast{ flex:none; display:flex; align-items:center; justify-content:center; gap:8px; padding:6px 10px; min-height:44px; background:var(--panel2); border-top:1px solid var(--line); font-size:15px; }
.rcs-toast[hidden]{ display:none; }
.rcs-toastgo{ min-height:44px; padding:0 12px; font-size:16px; font-weight:700; color:var(--accent); }
.rc-rmbtn{ margin-top:6px; }
.rc-rmrow{ display:flex; flex-direction:column; gap:4px; opacity:.85; }
.rc-restore{ min-height:44px; text-transform:none; letter-spacing:0; font-size:14px; }
.rc-mark.eye{ color:var(--orange); }

/* ===== §164: «Окно вещи-3» - просмотр: кнопки пометки, комментарий уточнения; лист «Местоположение»; строка «Уточнение:» и снимки этого переучёта ===== */
.rcs-vfm .fm-mark{ display:none; }   /* пометка 230 в просмотре - кнопки «Целиком» / «Признаки» / «Прочее» (rcsVMarkHtml) */
.rcs-vmark{ display:flex; gap:8px; justify-content:center; margin-top:8px; }
.rcs-vmark .rcs-vm{ flex:1 1 0; max-width:160px; }
.rcs-vm.on{ border-color:var(--accent); color:var(--accent); background:color-mix(in srgb, var(--accent) 16%, transparent); font-weight:700; }
.rcs-vcom{ margin:4px 0; font-size:14px; text-align:left; overflow-wrap:anywhere; }
.rcs-vta{ width:100%; box-sizing:border-box; min-height:64px; font-size:16px; margin-bottom:4px; }
.rcs-crv{ margin:3px 0; text-align:left; }
.rcs-sheetb{ position:fixed; inset:0; z-index:10035; display:flex; align-items:flex-end; justify-content:center; background:rgba(0, 0, 0, .55); zoom:calc(1 / var(--ui-zoom)); }
.rcs-sheet{ display:flex; flex-direction:column; width:min(560px, 100%); max-height:88%; background:var(--panel); color:var(--text); border:1px solid var(--line); border-bottom:0; }
.rcs-shh{ flex:none; display:flex; align-items:center; gap:10px; padding:6px 6px 6px 12px; border-bottom:1px solid var(--line); }
.rcs-shh b{ flex:1; font-size:17px; }
.rcs-shb{ flex:1 1 auto; min-height:0; overflow-y:auto; padding:8px 12px calc(14px + env(safe-area-inset-bottom)); display:flex; flex-direction:column; gap:10px; }
.rcs-shpath{ font-size:15px; font-weight:700; overflow-wrap:anywhere; }
.rcs-shmap{ flex:none; height:min(34vh, 260px); border:1px solid var(--line); background:var(--panel2); display:flex; align-items:center; justify-content:center; overflow:hidden; }
.rcs-shmap svg{ width:100%; height:100%; display:block; }
.rcs-shbtn .tb-btn{ min-height:44px; text-transform:none; letter-spacing:0; }
.rcs-shl{ display:flex; flex-direction:column; gap:8px; }
.rcs-cr{ display:flex; align-items:center; gap:10px; min-width:0; padding:6px; border:1px solid var(--line); background:var(--panel2); }
.rcs-crt{ width:64px; height:64px; }
.rcs-cri{ flex:none; width:44px; text-align:center; font-size:26px; }
.rcs-crx{ flex:1 1 auto; min-width:0; font-size:14px; overflow-wrap:anywhere; }
.rcs-crt2{ white-space:pre-wrap; }
.rcs-crold{ font-size:12px; }
.rcs-cdel{ flex:none; min-width:44px; min-height:44px; padding:0; font-size:18px; }
.rcs-shnone{ padding:8px 0; font-size:14px; }
.rcs-clrow{ display:flex; align-items:center; gap:8px; padding:2px 10px 0; }
.rcs-clk{ flex:none; font-size:14px; font-weight:700; }
.rcs-cb{ flex:none; width:52px; min-width:52px; height:48px; min-height:48px; padding:0; display:flex; align-items:center; justify-content:center; font-size:22px; line-height:1; text-transform:none; cursor:pointer; }
.rcs-cb.off{ opacity:.45; pointer-events:none; }
.rcs-old5{ padding:2px 10px 0; font-size:12.5px; overflow-wrap:anywhere; }
.rc-where .rc-wnote{ padding:0 0 2px; }
.rc-where .rc-wnote .rc-noteedit{ padding:2px 10px 0; }
.rc-where .rc-wnote .rcs-nmsg{ padding:0 10px; }
.rcs-snapbox{ min-width:0; }
.rcs-snk{ padding:2px 10px 0; font-size:12.5px; color:var(--dim); }
.rcs-snaps{ display:flex; align-items:center; gap:5px; padding:2px 10px 4px; min-height:48px; overflow-x:auto; overflow-y:hidden; touch-action:pan-x; -webkit-overflow-scrolling:touch; scrollbar-width:none; }
.rcs-snaps::-webkit-scrollbar{ display:none; }
.rcs-snaps .rcs-mi{ width:48px; height:48px; }
.pp-embed .tm-msg{ top:60px; }   /* подпись поверх карты - под верхними кнопками (мини-карта слева, этажи справа) */

/* ===== «Выбор места» (placepick.js, режим «выбор», §167): ✕ и заголовок, путь, карта до самого низа, «Выбрать» ===== */
.pp-pick .pp-bar{ flex:none; }
.pp-pick .pp-title{ flex-direction:row; align-items:center; }
.pp-pickpath{ position:relative; flex:none; padding:4px 10px; min-height:40px; border-bottom:1px solid var(--line-soft); font-size:15px; align-items:center; }
.pp-pickpath .pv-crumb, .pp-pickpath .pv-crumb-self{ min-height:36px; display:inline-flex; align-items:center; padding:0 3px; }
.pp-pickpath .pv-crumb-self{ font-weight:800; }
.pp-ptop{ font-size:20px; }
.pp-terrmenu{ position:absolute; left:6px; top:calc(100% - 2px); z-index:30; display:flex; flex-direction:column; min-width:200px; max-width:calc(100% - 12px); max-height:50vh; overflow-y:auto; background:var(--panel); border:1px solid var(--line); box-shadow:0 4px 14px rgba(0, 0, 0, 0.45); }
.pp-terrm{ flex:none; min-height:46px; justify-content:flex-start; text-align:left; border:none; border-bottom:1px solid var(--line-soft); font-size:15px; text-transform:none; letter-spacing:0; }
.pp-terrm.on{ color:var(--accent); font-weight:700; }
.pp-pickextra{ flex:none; min-width:0; padding:6px 10px; border-bottom:1px solid var(--line-soft); }
.pp-pickextra[hidden]{ display:none; }
.pp-pickextra.rcs-cfg, .pp-pickextra .rcs-cfg{ flex-direction:row; align-items:center; flex-wrap:nowrap; }
.pp-pickextra.rcs-cfg{ gap:8px; overflow-x:auto; overflow-y:hidden; }
.pp-pickextra .rcs-chips{ flex:none; flex-wrap:nowrap; }
.pp-pickextra .rcs-chip, .pp-pickextra .rcs-cfgchk{ flex:none; white-space:nowrap; }
.pp-pick .pp-stagewrap{ flex:1 1 0; min-height:0; display:flex; flex-direction:column; }
.pp-pick .pp-stage{ flex:1 1 0; min-height:0; height:auto; border:none; }
.pp-pick .pv-s.pp-sel{ stroke-width:6.5; }
.pp-pick .pp-strip{ flex-direction:row; align-items:center; gap:10px; }
.pp-pick .pp-strip .pp-msg{ flex:1 1 auto; min-width:0; }
.pp-pick .pp-skip{ flex:none; margin-right:auto; font-size:12px; color:var(--dim); }
.pp-pick .pp-show{ flex:none; margin-left:auto; min-width:150px; min-height:52px; font-size:17px; text-transform:none; letter-spacing:0; }
/* ===== Окно вещи вкладками (§6.1.1, thingwin.js) и правка поля на месте (fieldedit.js) ===== */
.tw-tabs{ grid-auto-columns:max-content; justify-content:start; overflow-x:auto; overflow-y:hidden; scrollbar-width:none; -webkit-overflow-scrolling:touch; gap:0; }
.tw-tabs::-webkit-scrollbar{ display:none; }
.tw-tab{ min-width:64px; padding-left:8px; padding-right:8px; }
.tw-tab.tw-free .rcs-mk{ visibility:hidden; }
.tw-tab.tw-dis{ opacity:.35; cursor:default; }
.tw-hint{ flex:none; padding:4px 12px; font-size:14px; font-weight:600; color:var(--text); background:color-mix(in srgb, var(--accent) 10%, var(--panel)); border-bottom:1px solid var(--line); }
.tw-hint[hidden]{ display:none; }
.tw-hintgo{ font-size:14px; font-weight:600; min-height:32px; padding:0; text-align:left; }
.tw-sh{ margin:14px 12px 4px; font-size:16px; }
.tw-sh[hidden]{ display:none; }
.tw-x{ position:absolute; top:2px; right:6px; min-width:44px; min-height:44px; padding:0; font-size:20px; text-transform:none; letter-spacing:0; }
.rcs-top{ position:relative; }
.rc-win[data-mode="view"] .rcs-head{ padding-right:48px; }
.rc-win[data-mode="view"] .rcs-stat{ display:none; }
.tw-wait{ position:absolute; inset:0; z-index:5; display:flex; align-items:center; justify-content:center; background:var(--panel); }
.tw-wait[hidden]{ display:none; }
.rc-appbar.tw-view .rc-nav, .rc-appbar.tw-view [data-rcw="exclude"], .rc-appbar.tw-view [data-rcw="plus"], .rc-appbar.tw-view [data-rcw="steps"]{ display:none; }
.rc-appbar.tw-view{ justify-content:flex-end; }
/* значение, которое правится на месте: на телефоне - тап по нему, на компьютере - ✎ при наведении */
.fe-v{ display:inline-flex; align-items:center; gap:4px; min-width:0; max-width:100%; padding:0; border:0; background:none; color:inherit; font:inherit; text-align:left; text-transform:none; letter-spacing:0; cursor:pointer; }
.fe-pen{ display:none; font-size:13px; color:var(--dim); }
@media (hover:hover) and (pointer:fine){ .fe-v:hover .fe-pen, .fe-v:focus-visible .fe-pen{ display:inline; } .fe-v:hover{ text-decoration:underline dotted; } }
.tw-trow{ display:flex; align-items:center; gap:6px; min-width:0; }
.tw-trow .rc-wtitle{ min-width:0; }
.rc-tpen{ flex:none; min-width:32px; min-height:32px; justify-content:center; }
.rc-tpen .fe-pen{ display:inline; }
.fe-back{ position:fixed; inset:0; z-index:2600; display:flex; align-items:flex-end; justify-content:center; background:rgba(0,0,0,.45); }
.rc-thing-back .fe-back{ position:absolute; }   /* окошко - внутри окна вещи, над нижней панелью приложения */
.fe-sheet{ width:min(560px, 100%); box-sizing:border-box; padding:12px 16px calc(12px + env(safe-area-inset-bottom, 0px)); background:var(--panel); border-top:1px solid var(--line); border-radius:12px 12px 0 0; }
.fe-edit{ display:flex; flex-direction:column; gap:8px; min-width:0; }
.fe-edit.fe-inline{ margin:2px 0 6px; padding:6px; border:1px solid var(--accent); background:var(--panel2); }
.fe-title{ font-size:15px; font-weight:700; }
.fe-in{ width:100%; box-sizing:border-box; min-height:44px; font-size:16px; }
.fe-ta{ min-height:88px; resize:vertical; }
.fe-hint{ font-size:12.5px; }
.fe-err{ min-height:0; color:var(--red, #e5484d); font-size:13px; }
.fe-err:empty{ display:none; }
.fe-btns{ display:flex; gap:8px; flex-wrap:wrap; }
.fe-b{ min-height:44px; min-width:88px; }
.fe-del{ min-width:44px; margin-left:auto; }
/* Обзор */
.tw-meta{ flex:none; font-size:13px; color:var(--dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.tw-cat{ color:var(--text); }
.rcs-nv{ min-height:32px; font-size:inherit; }
.tw-parts[hidden]{ display:none; }
/* Медиа: группы, плитки по 3 */
.tw-media{ display:flex; flex-direction:column; gap:12px; padding:8px 10px 0; min-width:0; }
.tw-mg{ min-width:0; }
.tw-mgh{ display:flex; align-items:center; gap:6px; margin-bottom:4px; font-size:15px; }
.tw-mgn{ font-size:12.5px; }
.tw-grid{ display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:4px; }
.tw-tile{ min-width:0; display:flex; flex-direction:column; gap:2px; }
.tw-ph{ position:relative; display:block; width:100%; aspect-ratio:1 / 1; padding:0; border:1px solid var(--line); background:var(--panel2); overflow:hidden; cursor:pointer; }
.tw-ph .rcs-ph, .tw-ph .rcs-ph img, .tw-ph img{ width:100%; height:100%; object-fit:cover; display:block; }
.tw-ph.pend{ cursor:default; }
.tw-date{ position:absolute; left:3px; bottom:3px; padding:0 4px; font-size:11px; line-height:16px; color:#fff; background:rgba(0,0,0,.55); border-radius:3px; }
.tw-play{ position:absolute; left:50%; top:50%; transform:translate(-50%, -50%); width:34px; height:34px; border-radius:50%; font-size:16px; line-height:34px; text-align:center; color:#fff; background:rgba(0,0,0,.55); }
.tw-main{ position:absolute; right:3px; top:3px; font-size:14px; color:var(--orange); text-shadow:0 0 2px #000; }
.tw-cap{ font-size:11.5px; color:var(--dim); overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow-wrap:anywhere; }
.tw-add{ aspect-ratio:1 / 1; align-items:center; justify-content:center; border:1px dashed var(--line); color:var(--dim); cursor:pointer; }
.tw-add .tw-addt{ font-size:15px; font-weight:600; }
.tw-add.need, .tw-mg.need .tw-add{ border:2px solid var(--orange); color:var(--orange); background:color-mix(in srgb, var(--orange) 10%, var(--panel)); }
/* Размеры, Место: картинка вместо живого редактора */
.tw-prev{ display:flex; flex-direction:column; align-items:center; gap:6px; width:100%; padding:8px; border:1px solid var(--line); background:var(--panel2); color:inherit; font:inherit; text-transform:none; letter-spacing:0; cursor:pointer; }
.tw-silprev svg{ width:100%; height:180px; }
.tw-silp{ fill:color-mix(in srgb, var(--accent) 25%, transparent); stroke:var(--accent); stroke-width:2; }
.tw-silt{ font-size:14px; font-weight:600; }
.rcs-dimsec .tw-sil{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
.rcs-dimsec .tw-dimsf{ flex:none; padding:0 10px 8px; }
.tw-dimsf:empty{ display:none; }
.tw-wview{ display:flex; flex-direction:column; gap:8px; padding:8px 10px; }
.tw-wview[hidden]{ display:none; }
.tw-wpath{ font-size:15px; overflow-wrap:anywhere; }
.tw-wmap svg{ width:100%; height:auto; max-height:260px; }
.tw-wbtns{ display:flex; gap:8px; flex-wrap:wrap; }
.rc-win[data-mode="view"] .rc-where > .rc-pathbox, .rc-win[data-mode="view"] .rc-where > .rc-mapbox, .rc-win[data-mode="view"] .rc-where > .rcs-undorow, .rc-win[data-mode="view"] .rc-where > .rc-state{ display:none; }
.rc-win[data-mode="view"][data-step="where"] .rc-wbody, .rc-win[data-mode="view"][data-step="find"] .rc-wbody{ overflow-y:auto; }
/* Прочее, История */
.tw-misc{ padding:8px 10px 24px; }
.tw-hist{ padding:8px 10px 24px; }
.tw-hl{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:8px; }
.tw-hi{ padding:6px 8px; border-left:3px solid var(--line); background:var(--panel2); min-width:0; }
.tw-hi.op{ border-left-color:var(--accent); }
.tw-hh{ font-size:12.5px; color:var(--dim); }
.tw-hw{ color:var(--text); font-weight:600; }
.tw-hb{ font-size:14px; overflow-wrap:anywhere; }
.tw-hb .oh-acts{ margin:2px 0 0; padding-left:18px; }
.tw-hnote{ margin-bottom:6px; font-size:13px; }
.tw-hmore{ margin-top:8px; min-height:44px; }
/* Широкий экран: все разделы одной страницей, лента вкладок - оглавлением слева; живые карта и силуэт - только в нынешнем разделе */
.rc-win.tw-page{ display:grid; grid-template-columns:180px minmax(0, 1fr); grid-template-rows:auto auto auto auto minmax(0, 1fr) auto auto; grid-template-areas:"top top" "stat stat" "toc hint" "toc wmsg" "toc body" "toc toast" "toc foot"; }
.rc-win.tw-page > .rcs-top{ grid-area:top; }
.rc-win.tw-page > .rcs-stat{ grid-area:stat; }
.rc-win.tw-page > .tw-tabs{ grid-area:toc; display:flex; flex-direction:column; align-items:stretch; overflow-x:hidden; overflow-y:auto; border-bottom:0; border-right:1px solid var(--line); padding:6px 0; }
.rc-win.tw-page > .tw-hint{ grid-area:hint; }
.rc-win.tw-page > .rcs-wmsg{ grid-area:wmsg; }
.rc-win.tw-page > .rc-wbody{ grid-area:body; }
.rc-win.tw-page > .rcs-toast{ grid-area:toast; }
.rc-win.tw-page > .rcs-foot{ grid-area:foot; }
.rc-win.tw-page .tw-tab{ flex-direction:row; justify-content:flex-start; gap:8px; min-height:44px; padding:4px 12px; border-bottom:0; border-left:3px solid transparent; }
.rc-win.tw-page .tw-tab.cur{ border-left-color:var(--accent); }
.rc-win.tw-page .tw-tab .rcs-sn, .rc-win.tw-page .tw-tab.cur .rcs-sn{ font-size:15px; }
.rc-win.tw-page .rc-wbody{ overflow-y:auto !important; display:block; padding-bottom:40px; }
.rc-win.tw-page .rc-wbody > .rc-s{ display:flex; }
.rc-win.tw-page .rc-wbody > .rc-s[hidden]{ display:none; }
.rc-win.tw-page .rc-s.tw-cur{ box-shadow:inset 3px 0 0 var(--accent); }
.rc-win.tw-page .rcs-find{ overflow:visible; }
.rc-win.tw-page .rcs-fd{ flex:none; }
.rc-win.tw-page .rcs-hero{ flex:none; height:340px; }
.rc-win.tw-page .rcs-dimsec.tw-cur .tw-sil{ height:520px; flex:none; }
.rc-win.tw-page .rc-where.tw-cur{ min-height:560px; }
.rc-win.tw-page .rc-where.tw-cur .rc-mapbox{ flex:none; height:480px; }
.rc-win.tw-page .rc-where.tw-cold .rc-mapbox{ position:absolute; left:-200vw; top:0; width:900px; height:480px; visibility:hidden; pointer-events:none; }
.rc-win.tw-page .tw-grid{ grid-template-columns:repeat(3, minmax(0, 200px)); }
.rc-win.tw-page .tw-silprev svg{ height:220px; }
.tw-ph.rcs-rt{ display:block; width:100%; height:auto; aspect-ratio:1 / 1; flex:none; }
.tw-mg.rcs-blk{ gap:6px; padding:8px; }
.tw-mgh .rcs-bt{ flex:none; }
.tw-mgb{ display:flex; gap:4px; margin-left:auto; }
.tw-mgh{ flex-wrap:wrap; }
