/* UytHome Electrical Planner — публичный конструктор.
   Отдельная дизайн-система от админ-панели: это витрина бизнеса.
   Тёмный премиальный старт (как сайт uythome.ru) + светлая рабочая область
   конструктора: чёрный инженерный canvas читается хуже и пугает клиента. */

:root{
  --pl-bg:#fbfbfd; --pl-panel:#ffffff; --pl-sunken:#f4f5f8;
  --pl-line:#e7eaf0; --pl-line2:#f0f2f6;
  --pl-text:#131722; --pl-muted:#606b80; --pl-faint:#98a1b3;
  --pl-accent:#f97a1f; --pl-accent-h:#e8690d; --pl-accent-soft:#fff4ea;
  --pl-green:#16A06A; --pl-green-soft:#e8f7f0;
  --pl-blue:#3468d1; --pl-blue-soft:#edf2fc;
  --pl-amber:#B7791F; --pl-amber-soft:#fdf6e6;
  --pl-red:#D0453F; --pl-red-soft:#fdeeed;
  --pl-r:14px; --pl-r-s:10px; --pl-r-xs:8px;
  --pl-sh:0 1px 2px rgba(19,23,34,.04), 0 6px 20px rgba(19,23,34,.06);
  --pl-sh-pop:0 12px 48px rgba(19,23,34,.18);
  --pl-font:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --pl-top:60px;
}

*{box-sizing:border-box}
html,body{height:100%}
body.pl{margin:0;background:var(--pl-bg);color:var(--pl-text);font-family:var(--pl-font);
  font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;overscroll-behavior:none}
body.pl a{color:inherit;text-decoration:none}
button{font:inherit;cursor:pointer;color:inherit}
input,select,textarea{font:inherit;color:inherit}
h1,h2,h3,h4{margin:0;letter-spacing:-.022em;font-weight:700}
.pl-num{font-variant-numeric:tabular-nums}
.pl-muted{color:var(--pl-muted)}
.pl-faint{color:var(--pl-faint)}
.pl-small{font-size:12.5px}
.pl-hide{display:none !important}

/* ───────────────── Кнопки ───────────────── */
.pl-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:38px;padding:0 15px;border-radius:var(--pl-r-s);border:1px solid transparent;
  background:transparent;font-weight:600;font-size:13.5px;transition:.14s ease;white-space:nowrap}
.pl-btn:active{transform:translateY(1px)}
.pl-btn.primary{background:var(--pl-accent);color:#fff;box-shadow:0 2px 12px rgba(249,122,31,.28)}
.pl-btn.primary:hover{background:var(--pl-accent-h)}
.pl-btn.ghost{border-color:var(--pl-line);background:var(--pl-panel)}
.pl-btn.ghost:hover{border-color:#d5dae4;background:var(--pl-sunken)}
.pl-btn.quiet{color:var(--pl-muted)}
.pl-btn.quiet:hover{background:var(--pl-sunken);color:var(--pl-text)}
.pl-btn.danger{color:var(--pl-red)}
.pl-btn.danger:hover{background:var(--pl-red-soft)}
.pl-btn.big{min-height:48px;padding:0 22px;font-size:15px;border-radius:12px}
.pl-btn[disabled]{opacity:.45;pointer-events:none}
.pl-icon{width:34px;height:34px;min-height:34px;padding:0;border-radius:9px}

/* ───────────────── Каркас приложения ───────────────── */
.pl-app{display:flex;flex-direction:column;height:100dvh;overflow:hidden}
/* Шапка прокручивается на ЛЮБОЙ ширине, где содержимое не влезло, а не
   только на телефоне: на планшете 768 ей нужно 986 px, и за экран уходили
   отмена, возврат, «?» и «Результат» — прокрутить было нечем, документ по
   горизонтали не едет. Когда всё влезает, оба правила ничего не делают. */
.pl-top{display:flex;align-items:center;gap:14px;padding:0 16px;height:var(--pl-top);
  flex:0 0 var(--pl-top);background:rgba(255,255,255,.9);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--pl-line);z-index:40;
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.pl-top::-webkit-scrollbar{display:none}

/* Кто сейчас за экраном — тёмная шапка у хозяина, светлая у клиента.
   Это не оформление: от роли зависит, станет ли сохранение правкой проекта
   или заявкой клиенту на согласование, а перепутать их стоило целой порции
   правок клиента (07.09.2026). Цвет читается раньше любой подписи. */
.pl-owner .pl-top{background:rgba(23,28,38,.94);border-bottom-color:#2b3345;color:#eef1f6}
.pl-owner .pl-top .pl-title{background:transparent;color:#eef1f6}
.pl-owner .pl-top .pl-title::placeholder{color:#8b95a8}
.pl-owner .pl-top .pl-btn.quiet,
.pl-owner .pl-top .pl-btn.ghost{color:#d7dde8;border-color:#39425a;background:transparent}
.pl-owner .pl-top .pl-btn.quiet:hover,
.pl-owner .pl-top .pl-btn.ghost:hover{background:#252d3d;border-color:#4b5570}
.pl-owner .pl-top .pl-seg{background:#252d3d;border-color:#39425a}
.pl-owner .pl-top .pl-seg button{color:#c3cbdb}
.pl-owner .pl-top .pl-seg button.on{background:#3b455e;color:#fff}
.pl-owner .pl-top .pl-saved span{color:#aab3c4}
.pl-owner .pl-top .pl-logo span{color:#aab3c4}
.pl-owner .pl-top .pl-logo img{filter:invert(1) brightness(1.6)}

/* Подпись роли словами — на случай дальтонизма и печати скриншота. */
.pl-role{flex:0 0 auto;font-size:10.5px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;padding:3px 8px;border-radius:999px;
  background:var(--pl-accent);color:#fff}
.pl-role.guest{background:var(--pl-line2);color:var(--pl-muted)}
/* Приклеивать «Результат» к краю можно только там, где горизонтальная
   прокрутка — привычный жест, то есть на сенсорном экране. Приклеенная
   кнопка ЛОЖИТСЯ ПОВЕРХ соседей, пока шапку не протянули: на десктопе 1400
   в чертёжном виде под ней целиком скрывались «Вернуть» и «?», а мышью
   горизонтально прокручивать шапку никто не догадается. На десктопе шапка
   просто прокручивается — этого достаточно, чтобы ничего не пропало. */
@media (pointer:coarse), (max-width:900px){
  #plResult{position:sticky;right:0;z-index:2}
}
.pl-logo{display:flex;align-items:center;gap:7px;font-weight:800;font-size:15.5px;letter-spacing:-.03em}
.pl-logo b{color:var(--pl-accent);font-weight:800}
.pl-logo img{height:32px;width:auto;display:block}
.pl-logo span{font-size:10px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--pl-faint)}
.pl-title{font-weight:600;font-size:14px;border:1px solid transparent;background:transparent;
  padding:5px 9px;border-radius:8px;min-width:60px;max-width:260px}
.pl-title:hover{border-color:var(--pl-line)}
.pl-title:focus{outline:none;border-color:var(--pl-accent);background:#fff}
.pl-grow{flex:1}
.pl-saved{font-size:12.5px;color:var(--pl-faint);display:flex;align-items:center;gap:6px;white-space:nowrap}
.pl-saved b{width:7px;height:7px;border-radius:50%;background:var(--pl-green)}
.pl-saved.busy b{background:var(--pl-amber)}
.pl-saved.err b{background:var(--pl-red)}
/* Вид плана — сегмент в шапке. Это фишка продукта (два вида для разных
   людей), поэтому подписи, а не иконки; активное положение — светлая
   пилюля с акцентом. На узких экранах подписи сжимаются до иконок. */
.pl-viewseg{display:flex;gap:2px;padding:3px;border:1px solid var(--pl-line);border-radius:11px;
  background:var(--pl-sunken);flex:0 0 auto}
.pl-viewseg button{display:inline-flex;align-items:center;gap:6px;min-height:30px;padding:0 11px;
  border:none;border-radius:8px;background:transparent;color:var(--pl-muted);
  font-weight:600;font-size:12.5px;line-height:1;transition:.14s}
.pl-viewseg button:hover{color:var(--pl-text)}
.pl-viewseg button.on{background:var(--pl-panel);color:var(--pl-accent);
  box-shadow:0 1px 4px rgba(19,23,34,.14)}
.pl-viewseg button svg{flex:0 0 auto}
#plHelpBtn b{font-size:14px}

.pl-costchip{display:flex;flex-direction:column;align-items:flex-end;line-height:1.25;
  padding:5px 13px;border-radius:11px;background:var(--pl-accent-soft);cursor:pointer;
  border:1px solid #ffe2c9;transition:.14s}
.pl-costchip:hover{background:#ffeada}
.pl-costchip i{font-style:normal;font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:#b4621d}
.pl-costchip b{font-size:13.5px;font-weight:700;color:#8f4c12;white-space:nowrap}

.pl-body{flex:1;display:grid;grid-template-columns:264px 1fr 330px;min-height:0}
.pl-embed .pl-body{grid-template-columns:1fr 330px}
.pl-embed .pl-left{display:none}
.pl-left,.pl-right{background:var(--pl-panel);display:flex;flex-direction:column;min-height:0}
.pl-left{border-right:1px solid var(--pl-line)}
.pl-right{border-left:1px solid var(--pl-line)}
.pl-scroll{overflow-y:auto;overscroll-behavior:contain;flex:1;min-height:0}
.pl-scroll::-webkit-scrollbar{width:9px}
.pl-scroll::-webkit-scrollbar-thumb{background:#dfe3ea;border-radius:9px;border:3px solid #fff}

/* ───────────────── Сцена ───────────────── */
.pl-stage{position:relative;background:var(--pl-sunken);min-width:0;overflow:hidden;touch-action:none}
.pl-canvas{position:absolute;inset:0;width:100%;height:100%;display:block}
.pl-stage.drop{outline:2px dashed var(--pl-accent);outline-offset:-8px}

.pl-tools{position:absolute;left:14px;top:14px;display:flex;flex-direction:column;gap:4px;
  background:var(--pl-panel);border:1px solid var(--pl-line);border-radius:12px;padding:5px;
  box-shadow:var(--pl-sh);z-index:12}
.pl-tool{width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;
  border:none;background:transparent;color:var(--pl-muted);font-size:15px;transition:.12s}
.pl-tool:hover{background:var(--pl-sunken);color:var(--pl-text)}
.pl-tool.on{background:var(--pl-accent);color:#fff}
.pl-tool.sep{height:1px;margin:3px 5px;background:var(--pl-line);pointer-events:none}
/* Подпись под иконкой. На десктопе скрыта — там есть наведение и title,
   а панель должна оставаться узкой. Правило показа — ниже, вместе с
   сенсорным слоем. */
.pl-tool .lb{display:none}

.pl-zoom{position:absolute;right:14px;bottom:14px;display:flex;align-items:center;gap:2px;
  background:var(--pl-panel);border:1px solid var(--pl-line);border-radius:11px;padding:4px;
  box-shadow:var(--pl-sh);z-index:12}
.pl-zoom span{min-width:48px;text-align:center;font-size:12px;color:var(--pl-muted);font-variant-numeric:tabular-nums}

/* Подсказка висит ПОВЕРХ плана и стояла на пути: под ней нельзя было ни
   разглядеть чертёж, ни поставить точку — клики доставались ей, а не холсту.
   Теперь она клики пропускает (кроме собственных кнопок) и уходит почти в
   прозрачность, когда указатель к ней подходит. */
.pl-stagehint{position:absolute;left:50%;top:16px;transform:translateX(-50%);z-index:12;
  background:rgba(19,23,34,.9);color:#fff;padding:8px 15px;border-radius:10px;font-size:13px;
  font-weight:500;box-shadow:var(--pl-sh-pop);max-width:min(560px,86vw);text-align:center;
  pointer-events:none;transition:opacity .14s ease}
.pl-stagehint button,.pl-stagehint .pl-hintmode{pointer-events:auto}
.pl-stagehint.pl-shy{opacity:.14}
.pl-stagehint b{color:#ffbe83}
/* Число открытых веток прямо на инструменте комментария. Сам список живёт
   в панели проекта, а она видна только когда ничего не выбрано и пролистана
   вниз: разговор о плане нельзя прятать так глубоко. Значок места не
   занимает — колонка и так впритык. */
.pl-tool{position:relative}
.pl-toolbadge{position:absolute;top:2px;right:2px;min-width:16px;height:16px;padding:0 4px;
  border-radius:8px;background:var(--pl-accent);color:#fff;font-size:10.5px;font-weight:700;
  line-height:16px;text-align:center;pointer-events:none}
/* Значок внутри подсказки — тот же SVG, что на кнопке панели: человек
   ищет глазами ровно то, что видит в тексте. */
.pl-hintico{display:inline-block;vertical-align:-3px;margin:0 2px;color:#ffbe83}
/* Режим привязки прямо в подсказке: Alt на телефоне нажать нечем, а без
   свободного размещения часть элементов туда не поставить вообще. */
.pl-hintmode{display:inline-flex;align-items:center;gap:5px;margin-left:9px;vertical-align:middle}
.pl-hintmode button{border:1px solid rgba(255,255,255,.22);background:transparent;color:#cfd6e2;
  font-size:11.5px;font-weight:600;padding:4px 9px;border-radius:7px;line-height:1.15;transition:.12s}
.pl-hintmode button:hover{border-color:rgba(255,190,131,.6);color:#ffbe83}
.pl-hintmode button.on{background:var(--pl-accent);border-color:var(--pl-accent);color:#fff}
.pl-hintmode i{font-style:normal;font-size:11.5px;color:#98a1b3;margin-left:2px}
.pl-hintnote{font-style:normal;color:#b6bfcd}

/* ───────────────── Палитра элементов ───────────────── */
.pl-secthead{display:flex;align-items:center;gap:8px;padding:13px 15px 7px;
  font-size:10.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--pl-faint)}
.pl-search{margin:11px 12px 4px;position:relative}
.pl-search input{width:100%;height:36px;border-radius:9px;border:1px solid var(--pl-line);
  background:var(--pl-sunken);padding:0 12px}
.pl-search input:focus{outline:none;border-color:var(--pl-accent);background:#fff}

.pl-group{border-bottom:1px solid var(--pl-line2)}
.pl-group>summary{list-style:none;cursor:pointer;padding:10px 15px;display:flex;align-items:center;
  gap:9px;font-weight:600;font-size:13px;user-select:none}
.pl-group>summary::-webkit-details-marker{display:none}
.pl-group>summary:hover{background:var(--pl-sunken)}
.pl-group>summary .dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
.pl-group>summary .n{margin-left:auto;font-size:11.5px;color:var(--pl-faint);font-weight:600}
.pl-items{padding:2px 8px 10px}
.pl-item{display:flex;align-items:center;gap:10px;width:100%;padding:7px 8px;border-radius:9px;
  border:1px solid transparent;background:transparent;text-align:left;font-size:13px;cursor:grab;
  transition:.1s}
.pl-item:hover{background:var(--pl-sunken);border-color:var(--pl-line)}
.pl-item:active{cursor:grabbing}
.pl-item.on{background:var(--pl-accent-soft);border-color:#ffd9b8}
.pl-item .sym svg{width:72%;height:72%;display:block;color:#fff}
/* У статусов свой цвет по состоянию (зелёный/синий/серый), поэтому здесь
   цвет наследуется, а не прибивается белым, как у значков групп. */
.pl-check .st svg{width:72%;height:72%;display:block}
.pl-item .sym{width:24px;height:24px;border-radius:50%;flex:0 0 auto;display:flex;align-items:center;
  justify-content:center;color:#fff;font-size:9px;font-weight:700}
.pl-item .lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pl-item .cnt{font-size:11.5px;color:var(--pl-faint);font-weight:600}
.pl-item .tag{font-size:9.5px;font-weight:700;letter-spacing:.04em;padding:1px 5px;border-radius:5px;
  background:var(--pl-amber-soft);color:var(--pl-amber)}

/* ───────────────── Правая панель ───────────────── */
.pl-card{margin:12px;padding:14px;border:1px solid var(--pl-line);border-radius:var(--pl-r);
  background:var(--pl-panel)}
.pl-card.tint{background:var(--pl-sunken);border-color:transparent}
.pl-card h4{font-size:13.5px;margin-bottom:8px}
.pl-roomhead{padding:15px 15px 10px}
.pl-roomhead h3{font-size:19px}
.pl-roomhead .area{color:var(--pl-muted);font-size:13.5px;margin-top:2px}
.pl-field{margin:10px 15px}
.pl-field label{display:block;font-size:11.5px;font-weight:600;color:var(--pl-muted);margin-bottom:5px}
.pl-field input,.pl-field select,.pl-field textarea{width:100%;height:38px;border-radius:9px;
  border:1px solid var(--pl-line);background:var(--pl-panel);padding:0 11px}
.pl-field textarea{height:auto;min-height:70px;padding:9px 11px;resize:vertical}
.pl-field input:focus,.pl-field select:focus,.pl-field textarea:focus{outline:none;border-color:var(--pl-accent)}

/* Типовые высоты установки — выбор одним нажатием */
.pl-chips{display:flex;flex-wrap:wrap;gap:6px}
.pl-chip{display:flex;flex-direction:column;align-items:flex-start;gap:1px;padding:6px 9px;
  border-radius:9px;border:1px solid var(--pl-line);background:var(--pl-panel);
  line-height:1.15;transition:.12s;text-align:left}
.pl-chip b{font-size:13px;font-weight:700;font-variant-numeric:tabular-nums}
.pl-chip span{font-size:10.5px;color:var(--pl-faint)}
.pl-chip:hover{border-color:var(--pl-accent);color:var(--pl-accent)}
.pl-chip:hover span{color:var(--pl-accent)}
.pl-chip.on{background:var(--pl-accent);border-color:var(--pl-accent);color:#fff}
.pl-chip.on span{color:rgba(255,255,255,.8)}
/* Трасса линейного света: длина крупно — это то число, что уйдёт в расчёт. */
.pl-runlen{display:flex;align-items:baseline;gap:7px;margin-bottom:8px}
.pl-runlen b{font-size:22px;font-weight:700;font-variant-numeric:tabular-nums;color:var(--pl-ink)}
.pl-runlen span{font-size:11.5px;color:var(--pl-faint)}
.pl-runwalls{margin-bottom:8px}
.pl-runacts{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:8px}
.pl-runacts .pl-btn{flex:1;min-height:32px;white-space:nowrap}
.pl-runmodes{display:flex;flex-direction:column;gap:8px}
.pl-runmode{display:flex;flex-direction:column;gap:3px;padding:12px 14px;text-align:left;
  border:1px solid var(--pl-line);border-radius:12px;background:#fff;cursor:pointer;
  transition:border-color .12s,background .12s}
.pl-runmode:hover{border-color:var(--pl-accent);background:var(--pl-accent-soft)}
.pl-runmode b{font-size:14.5px}
.pl-runmode span{font-size:12.5px;color:var(--pl-muted);line-height:1.45}

/* Переключатель готовности точки: смонтировать / заложить на будущее. */
.pl-seg{display:flex;gap:0;border:1px solid var(--pl-line);border-radius:9px;overflow:hidden;
  background:var(--pl-panel)}
.pl-segbtn{flex:1;min-height:34px;padding:6px 8px;font-size:12.2px;font-weight:600;
  color:var(--pl-muted);background:transparent;border:none;transition:.12s;line-height:1.2}
.pl-segbtn+.pl-segbtn{border-left:1px solid var(--pl-line)}
.pl-segbtn:hover:not(:disabled){color:var(--pl-accent)}
.pl-segbtn.on{background:var(--pl-accent);color:#fff}
.pl-segbtn:disabled{opacity:.55}

.pl-meter{height:6px;border-radius:6px;background:var(--pl-line2);overflow:hidden;margin:8px 0 4px}
.pl-meter i{display:block;height:100%;background:var(--pl-green);border-radius:6px;transition:width .3s}
.pl-meter.warn i{background:var(--pl-amber)}

.pl-check{display:flex;align-items:flex-start;gap:9px;padding:8px 0;border-top:1px solid var(--pl-line2)}
.pl-check:first-of-type{border-top:none}
.pl-check .st{width:19px;height:19px;border-radius:6px;flex:0 0 auto;display:flex;align-items:center;
  justify-content:center;font-size:11px;font-weight:700;margin-top:1px}
.pl-check .st.done{background:var(--pl-green-soft);color:var(--pl-green)}
.pl-check .st.open{background:var(--pl-sunken);color:var(--pl-faint);border:1px dashed #cdd4df}
.pl-check .st.later{background:var(--pl-blue-soft);color:var(--pl-blue)}
.pl-check .st.skip{background:var(--pl-sunken);color:var(--pl-faint)}
.pl-check .q{flex:1;font-size:13px;min-width:0}
.pl-check .acts{display:flex;gap:3px;margin-top:5px}
.pl-check .acts button{font-size:11.5px;padding:3px 8px;border-radius:6px;border:1px solid var(--pl-line);
  background:var(--pl-panel);color:var(--pl-muted);font-weight:600}
.pl-check .acts button:hover{border-color:var(--pl-accent);color:var(--pl-accent)}
.pl-check .acts button.on{background:var(--pl-accent);border-color:var(--pl-accent);color:#fff}

.pl-hint{display:flex;gap:9px;padding:10px 12px;border-radius:11px;font-size:12.8px;margin:8px 12px;
  line-height:1.45}
.pl-hint.tip{background:var(--pl-blue-soft);color:#22437f}
.pl-hint.attention{background:var(--pl-amber-soft);color:#7a5313}
.pl-hint.info{background:var(--pl-sunken);color:var(--pl-muted)}
.pl-hint .ic{flex:0 0 auto;line-height:0;margin-top:1px}
.pl-hint .ic svg{display:block;width:16px;height:16px}

/* ───────────────── Стартовый экран ───────────────── */
.pl-start{min-height:100dvh;background:#07090e;color:#f5f7fb;overflow-y:auto}
.pl-start .in{max-width:1080px;margin:0 auto;padding:26px 22px 80px}
.pl-start .nav{display:flex;align-items:center;gap:14px;margin-bottom:56px}
.pl-start .nav .pl-logo{color:#fff}
.pl-start .nav .pl-logo span{color:#7d8798}
.pl-start h1{font-size:clamp(30px,5.2vw,54px);line-height:1.06;letter-spacing:-.035em;max-width:16ch}
.pl-start h1 em{font-style:normal;color:#ff8a2b}
.pl-start .lead{margin-top:20px;font-size:clamp(15px,1.9vw,19px);color:#9da8b8;max-width:56ch;line-height:1.55}
.pl-start .pl-herogrid{display:grid;grid-template-columns:1.04fr .96fr;gap:52px;align-items:center}
.pl-shot{position:relative;display:block}
.pl-shot .frame{display:block;border-radius:22px;overflow:hidden;border:1px solid rgba(255,255,255,.14);
  background:#fff;box-shadow:0 30px 80px rgba(0,0,0,.5);transform:rotate(.6deg);transition:.18s}
.pl-shot:hover .frame{transform:rotate(0deg) translateY(-3px);border-color:rgba(255,138,43,.45)}
.pl-shot .frame img{display:block;width:100%;height:auto}
.pl-shot .chip{position:absolute;padding:10px 14px;border-radius:13px;background:rgba(17,23,34,.87);
  border:1px solid rgba(255,255,255,.14);backdrop-filter:blur(12px);
  box-shadow:0 16px 44px rgba(0,0,0,.35);animation:plchip 5.5s ease-in-out infinite}
.pl-shot .chip b{display:block;font-size:13.5px;color:#fff}
.pl-shot .chip i{font-style:normal;font-size:11px;color:#9da8b8}
.pl-shot .c1{left:-22px;top:12%}
.pl-shot .c2{right:-16px;top:46%;animation-delay:-1.8s}
.pl-shot .c3{left:-12px;bottom:9%;animation-delay:-3.2s}
@keyframes plchip{50%{transform:translateY(-8px)}}
@media(max-width:960px){
  .pl-start .pl-herogrid{grid-template-columns:1fr;gap:34px}
  .pl-shot .frame{transform:none}
  .pl-shot .chip{display:none}
}
.pl-start .ways{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px;margin:44px 0 14px}
.pl-way{text-align:left;padding:26px;border-radius:22px;border:1px solid rgba(255,255,255,.11);
  background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,.02));transition:.18s;color:#fff}
.pl-way:hover{border-color:rgba(255,138,43,.5);transform:translateY(-2px);
  background:linear-gradient(180deg,rgba(255,138,43,.1),rgba(255,255,255,.02))}
.pl-way .ic{margin-bottom:14px;display:block;line-height:0;color:var(--pl-accent)}
.pl-way .ic svg{width:28px;height:28px;stroke-width:1.5}
.pl-way b{display:block;font-size:18px;margin-bottom:7px;letter-spacing:-.02em}
.pl-way span{color:#a7b1c1;font-size:13.8px;line-height:1.5;display:block}
/* Главное действие лендинга должно читаться как действие, а не как
   справочная плашка: у обеих карточек есть строка перехода со стрелкой,
   у первой — акцентный фон. Кнопка «Посмотреть пример» остаётся тихой. */
.pl-way .go{display:inline-flex;align-items:center;gap:7px;margin-top:16px;width:auto;
  font-size:14px;font-weight:700;color:#ff8a2b;letter-spacing:-.01em}
.pl-way .go i{font-style:normal;transition:transform .18s}
.pl-way:hover .go i{transform:translateX(4px)}
.pl-way.primary{border-color:#ff9a4a;background:linear-gradient(165deg,#ff8f38,#f2690a);
  box-shadow:0 16px 42px rgba(249,122,31,.3)}
.pl-way.primary:hover{border-color:#ffb37a;background:linear-gradient(165deg,#ff9c4d,#ff7a17);
  box-shadow:0 20px 50px rgba(249,122,31,.38)}
.pl-way.primary span{color:rgba(255,255,255,.92)}
.pl-way.primary .go{color:#fff}
.pl-start .demo{margin-top:8px;display:flex;gap:12px 18px;flex-wrap:wrap;align-items:center}
/* Встречная ссылка на калькулятор — в тон такой же ссылке на конструктор
   в калькуляторе (.cl-way2). */
.pl-start .pl-way2{color:#9da8b8;font-size:14px;border-bottom:1px dashed rgba(255,255,255,.25);
  padding-bottom:2px;transition:.15s}
.pl-start .pl-way2:hover{color:#ffc796;border-color:rgba(255,138,43,.5)}
.pl-start .demo button{background:transparent;border:1px solid rgba(255,255,255,.16);color:#e6ebf3;
  min-height:42px;padding:0 18px;border-radius:11px;font-weight:600;font-size:13.5px}
.pl-start .demo button:hover{border-color:rgba(255,255,255,.4)}
.pl-steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px;margin-top:64px}
.pl-step{padding:20px;border-radius:18px;background:rgba(255,255,255,.035);border:1px solid rgba(255,255,255,.07)}
.pl-step i{font-style:normal;display:inline-flex;width:26px;height:26px;border-radius:50%;
  background:rgba(255,138,43,.16);color:#ff8a2b;align-items:center;justify-content:center;
  font-weight:700;font-size:12.5px;margin-bottom:11px}
.pl-step b{display:block;font-size:14.5px;margin-bottom:5px}
.pl-step span{color:#8d97a8;font-size:13px;line-height:1.5}
.pl-why{margin-top:64px}
.pl-why h2{font-size:clamp(22px,3vw,30px);letter-spacing:-.03em;margin-bottom:8px}
.pl-why .sub{color:#8d97a8;max-width:60ch;margin-bottom:24px}
.pl-whygrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.pl-whycard{padding:19px;border-radius:16px;background:rgba(255,255,255,.035);
  border:1px solid rgba(255,255,255,.07)}
.pl-whycard b{display:block;font-size:14.5px;margin-bottom:6px;letter-spacing:-.01em}
.pl-whycard span{color:#8d97a8;font-size:13px;line-height:1.55}
.pl-start .pl-whycard a{color:#ff8a2b;text-decoration:underline}
.pl-start .foot{margin-top:56px;padding-top:24px;border-top:1px solid rgba(255,255,255,.08);
  color:#6d778a;font-size:12.5px;line-height:1.6}
.pl-start .foot a{color:#9da8b8;text-decoration:underline}

/* ───────────────── Модалки и шторки ───────────────── */
.pl-overlay{position:fixed;inset:0;background:rgba(15,19,28,.42);
  /* План за окном уходит из фокуса: 3px не читались вовсе, а без
     -webkit- в Safari размытия не было совсем. Подложка светлее —
     под тёмной пеленой размытие всё равно не разглядеть. */
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  z-index:200;display:flex;align-items:center;justify-content:center;padding:20px}
.pl-modal{background:var(--pl-panel);border-radius:18px;box-shadow:var(--pl-sh-pop);
  width:min(560px,100%);max-height:88dvh;display:flex;flex-direction:column;overflow:hidden}
.pl-modal.wide{width:min(940px,100%)}
.pl-modal header{display:flex;align-items:center;gap:12px;padding:18px 20px 12px}
.pl-modal header h3{font-size:17px;flex:1}
.pl-modal .bd{padding:0 20px 4px;overflow-y:auto}
.pl-modal footer{display:flex;gap:9px;justify-content:flex-end;padding:16px 20px;
  border-top:1px solid var(--pl-line);margin-top:12px;flex-wrap:wrap}
.pl-modal footer .pl-grow{flex:1}

/* ───────────────── Онбординг: выбор вида и тур ───────────────── */
.pl-modegrid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media (max-width:640px){ .pl-modegrid{grid-template-columns:1fr} }
.pl-modecard{display:flex;flex-direction:column;gap:8px;padding:12px;text-align:left;
  border:1.5px solid var(--pl-line);border-radius:16px;background:var(--pl-panel);
  cursor:pointer;transition:.15s}
.pl-modecard:hover{border-color:var(--pl-accent);transform:translateY(-1px);box-shadow:var(--pl-sh)}
.pl-modecard.cur{border-color:#ffd9b8;background:var(--pl-accent-soft)}
.pl-modecard .shot{display:block;border-radius:10px;overflow:hidden;border:1px solid var(--pl-line);
  background:#fff}
.pl-modecard .shot img{display:block;width:100%;height:auto}
.pl-modecard b{font-size:15px;display:flex;align-items:center;gap:8px}
.pl-modecard b .now{font-style:normal;font-size:10px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--pl-accent);background:#fff;border:1px solid #ffd9b8;
  padding:2px 7px;border-radius:20px}
.pl-modecard .tx{font-size:12.8px;color:var(--pl-muted);line-height:1.5}

.pl-tour{position:fixed;inset:0;z-index:260}
.pl-tour .hole{position:absolute;border-radius:14px;transition:all .28s ease;
  box-shadow:0 0 0 9999px rgba(15,19,28,.55)}
.pl-tour .card{position:absolute;width:min(340px,calc(100vw - 24px));padding:16px 16px 13px;
  background:var(--pl-panel);border-radius:14px;box-shadow:var(--pl-sh-pop);transition:all .28s ease}
.pl-tour .card>b{display:block;font-size:15px;margin-bottom:5px;padding-right:24px}
.pl-tour .card>p{margin:0 0 12px;font-size:13px;color:var(--pl-muted);line-height:1.5}
.pl-tour .x{position:absolute;top:9px;right:9px;width:26px;height:26px;border:none;border-radius:7px;
  background:transparent;color:var(--pl-faint);font-size:13px;display:flex;align-items:center;
  justify-content:center}
.pl-tour .x:hover{background:var(--pl-sunken);color:var(--pl-text)}
.pl-tour .foot{display:flex;align-items:center;gap:8px}
.pl-tour .dots{display:flex;gap:5px}
.pl-tour .dots i{width:7px;height:7px;border-radius:50%;background:var(--pl-line);transition:.2s}
.pl-tour .dots i.on{background:var(--pl-accent)}
@media (max-width:560px){
  /* На телефоне карточка тура всегда прижата к низу — над таб-баром. */
  .pl-tour .card{left:12px !important;right:12px;width:auto;top:auto !important;
    bottom:calc(76px + env(safe-area-inset-bottom))}
}

.pl-toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:300;
  background:#131722;color:#fff;padding:11px 18px;border-radius:11px;font-size:13.5px;font-weight:500;
  box-shadow:var(--pl-sh-pop);max-width:90vw;text-align:center}
.pl-toast.err{background:var(--pl-red)}
.pl-toast.ok{background:var(--pl-green)}
/* Совместное включение — не ошибка, а предупреждение: янтарь, не красный. */
.pl-toast.warn{background:var(--pl-amber)}

/* ───────────────── Итоговая страница ───────────────── */
.pl-summary{max-width:1000px;margin:0 auto;padding:26px 20px 90px}
.pl-hero{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin:18px 0 26px}
.pl-stat{padding:17px;border-radius:15px;background:var(--pl-panel);border:1px solid var(--pl-line)}
.pl-stat b{display:block;font-size:27px;font-weight:700;letter-spacing:-.035em;line-height:1.1}
.pl-stat span{font-size:12.5px;color:var(--pl-muted);display:block;margin-top:3px}
.pl-stat.accent{background:var(--pl-accent-soft);border-color:#ffe0c4}
.pl-stat.accent b{color:#a3550f}
.pl-price{padding:24px;border-radius:18px;background:var(--pl-panel);border:1px solid var(--pl-line);
  margin-bottom:16px}
.pl-price .rng{font-size:clamp(24px,4vw,34px);font-weight:700;letter-spacing:-.035em}
/* Расшифровка границ диапазона: «от» и «до» — это разная комплектация */
.pl-basis{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px;margin-top:12px}
.pl-basis>div{padding:11px 13px;border-radius:11px;background:var(--pl-sunken)}
.pl-basis b{display:block;font-size:15px;font-weight:700;font-variant-numeric:tabular-nums}
.pl-basis span{display:block;font-size:12px;color:var(--pl-muted);margin-top:2px;line-height:1.4}

.pl-barhead{margin-top:18px;font-size:10.5px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--pl-faint)}
.pl-bars{margin-top:10px;display:flex;flex-direction:column;gap:9px}
.pl-bar{display:flex;align-items:center;gap:11px;font-size:13px}
/* Итог столбика: клиент складывает разделы глазами, и сумма должна быть
   подписана, а не оставаться загадкой рядом с диапазоном. */
.pl-bar.total{border-top:1px solid var(--pl-line);padding-top:9px;margin-top:1px}
.pl-bar.total .nm{color:var(--pl-text);font-weight:600}
.pl-bar.total .vl{font-weight:700}
.pl-bar .nm{width:150px;flex:0 0 auto;color:var(--pl-muted)}
.pl-bar .tr{flex:1;height:9px;border-radius:9px;background:var(--pl-line2);overflow:hidden}
.pl-bar .tr i{display:block;height:100%;background:var(--pl-accent);border-radius:9px}
.pl-bar .vl{width:104px;text-align:right;font-weight:600;font-variant-numeric:tabular-nums}

/* Ход сборки файла. Ширину двигает сам скрипт покадрово — CSS-переход тут
   лишний: он бы догонял уже сглаженное значение и добавлял запаздывание. */
.pl-dlprog{margin-top:14px;height:10px;border-radius:10px;background:var(--pl-line2);
  overflow:hidden}
.pl-dlprog i{display:block;height:100%;width:0;border-radius:10px;
  background:var(--pl-accent)}
.pl-scens{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;margin:14px 0}
.pl-scen{padding:18px;border-radius:15px;border:1px solid var(--pl-line);background:var(--pl-panel)}
.pl-scen.on{border-color:var(--pl-accent);box-shadow:0 0 0 3px var(--pl-accent-soft)}
.pl-scen b{display:block;font-size:15px;margin-bottom:4px}
.pl-scen .rg{font-weight:700;margin:9px 0 6px;font-variant-numeric:tabular-nums}
.pl-scen ul{margin:6px 0 0;padding-left:17px;color:var(--pl-muted);font-size:12.5px}
.pl-note{padding:16px 18px;border-radius:14px;background:var(--pl-sunken);color:var(--pl-muted);
  font-size:13px;line-height:1.55;margin:16px 0}
.pl-cta{display:flex;gap:11px;flex-wrap:wrap;margin-top:22px}
.pl-list{list-style:none;padding:0;margin:8px 0 0}
.pl-list li{display:flex;gap:9px;padding:6px 0;font-size:13.3px;align-items:flex-start}
.pl-list li:before{content:"✓";color:var(--pl-green);font-weight:700;flex:0 0 auto}
.pl-list.dash li:before{content:"—";color:var(--pl-faint)}

.pl-ready{display:flex;align-items:center;gap:14px;padding:15px 18px;border-radius:14px;
  background:var(--pl-panel);border:1px solid var(--pl-line);margin-bottom:16px}
.pl-ring{width:52px;height:52px;flex:0 0 auto;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-weight:700;font-size:14px;color:var(--pl-accent)}

/* ───────────────── Мобильный слой ───────────────── */
.pl-tabbar{display:none}
.pl-sheet{display:none}

@media (max-width:1120px){
  .pl-body{grid-template-columns:230px 1fr 290px}
}
@media (max-width:900px){
  .pl-body{grid-template-columns:1fr}
  .pl-left,.pl-right{position:fixed;left:0;right:0;bottom:0;top:auto;max-height:74dvh;z-index:120;
    border:none;border-top:1px solid var(--pl-line);border-radius:20px 20px 0 0;
    box-shadow:var(--pl-sh-pop);transform:translateY(101%);transition:transform .25s ease}
  .pl-left.open,.pl-right.open{transform:translateY(0)}
  .pl-sheet{display:block;position:fixed;inset:0;background:rgba(15,19,28,.4);z-index:110;
    opacity:0;pointer-events:none;transition:opacity .2s}
  .pl-sheet.on{opacity:1;pointer-events:auto}
  .pl-tabbar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:130;background:var(--pl-panel);
    border-top:1px solid var(--pl-line);padding:6px 6px calc(6px + env(safe-area-inset-bottom))}
  .pl-tabbar button{flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;padding:7px 2px;
    border:none;background:transparent;color:var(--pl-muted);font-size:10.5px;font-weight:600;border-radius:10px}
  .pl-tabbar button .ic{line-height:0}
  .pl-tabbar button .ic svg{width:20px;height:20px;display:block}
  .pl-tabbar button.on{color:var(--pl-accent);background:var(--pl-accent-soft)}
  /* Холст не заезжает под таб-бар — иначе план визуально «тонет».
     Высоту задаём числом, а НЕ height:auto. canvas — замещаемый элемент: при
     auto он берёт высоту из соотношения сторон своего буфера, а не из
     top/bottom. Дальше plResize() мерил канву и писал ту же высоту обратно в
     буфер — соотношение закреплялось, и план на телефоне навсегда оставался
     полоской в четверть экрана. Выхода из петли не было даже через plFit(). */
  .pl-canvas{inset:0 0 64px 0;height:calc(100% - 64px)}
  /* Подсказка идёт под горизонтальной панелью инструментов, а не под неё:
     иначе половина текста (и переключатель привязки) уезжает за кнопки. */
  .pl-stagehint{top:calc(72px + env(safe-area-inset-top))}
  .pl-zoom{bottom:76px;right:10px}
  /* Вертикальная колонка инструментов на телефоне съедала треть плана —
     кладём её горизонтально и даём прокручиваться. */
  .pl-tools{left:8px;right:8px;top:8px;flex-direction:row;overflow-x:auto;
    scrollbar-width:none;padding:4px;gap:2px}
  .pl-tools::-webkit-scrollbar{display:none}
  .pl-tool{flex:0 0 auto}
  .pl-tool.sep{width:1px;height:auto;margin:4px 3px}
  .pl-costchip{padding:4px 9px}
  .pl-costchip i{display:none}
  .pl-costchip b{font-size:12.5px}
  .pl-sheetgrip{display:block;width:38px;height:4px;border-radius:4px;background:#d8dde6;
    margin:9px auto 2px;flex:0 0 auto}
  /* Название проекта занимает всё свободное место шапки: при фиксированной
     ширине оно резалось на полуслове («Проект э»). */
  .pl-title{flex:1 1 auto;min-width:40px;max-width:none;text-overflow:ellipsis}
  /* Распорка в шапке больше не нужна — свободное место забирает название,
     а сама она съедала ещё и отступ по бокам. */
  .pl-top .pl-grow{display:none}
}
@media (min-width:901px){ .pl-sheetgrip{display:none} }
@media (max-width:560px){
  .pl-top{gap:8px;padding:0 10px}
  .pl-logo span{display:none}
  /* Сегмент видов сжимается до иконок: подписи не помещаются рядом с
     названием проекта и кнопкой результата. Смысл сохраняют тултипы. */
  .pl-viewseg button span{display:none}
  .pl-viewseg button{padding:0 9px}
  .pl-summary{padding:18px 14px 90px}
  /* Отмена и возврат остаются: прятать их было нельзя. Комментарий здесь
     утверждал, что они «доступны жестами и из панели», — это было неправдой:
     plUndo() зовётся только с клавиатуры, а Ctrl+Z на телефоне нажать нечем.
     Другой кнопки отмены в планере нет вообще. Клиент, поставивший розетку
     не туда, не мог её убрать. Место им нашлось прокруткой шапки — см. ниже,
     где они уходят в её начало. */
  .pl-saved span{display:none}
  /* Логотип уступает место названию проекта: подпись «Проект э…» в шапке
     не сообщает ничего, а места он занимал больше трети ширины. */
  .pl-top .pl-logo img{height:22px}
  .pl-title{font-size:12.5px;padding:5px 6px}
  .pl-top .pl-btn.primary{padding:0 12px}
  /* Диапазон цены целиком в шапку не помещается — он и так на экране «Итог». */
  .pl-costchip{display:none}
  .pl-tools{top:calc(8px + env(safe-area-inset-top))}

  /* Подписи в сегментах на узком экране скрыты, а у кнопки «Все» иконки нет —
     она превращалась в пустой прямоугольник. Ей подпись возвращаем. */
  .pl-sheetseg button[data-sheetv=""] span{display:inline}
}

/* Крупные зоны нажатия на сенсорных экранах */
/* Сенсорная раскладка: отмена и возврат — в начало шапки. Остальное можно
   доскроллить, а эти две нужны под рукой: жеста отмены в планере нет, и
   клавиатуры на планшете тоже. Порядок меняем стилем, а не разметкой, чтобы
   на десктопе шапка осталась ровно такой, какой была. */
@media (pointer:coarse), (max-width:900px){
  .pl-top > *{flex-shrink:0}
  .pl-title{flex:1 1 110px;min-width:80px}
  .pl-top .pl-logo{order:-2}
  #plUndo,#plRedo{display:inline-flex;order:-1}
}

@media (pointer:coarse){
  .pl-item{padding:10px 8px}
  .pl-check .acts button{padding:6px 11px}
}

/* Инструменты с подписями: пальцем навести курсор нельзя, и назначение
   иконки узнать неоткуда. Показываем подписи там, где нет наведения, и на
   мобильной раскладке; десктопная панель остаётся иконочной. */
@media (pointer:coarse), (max-width:900px){
  .pl-tool{flex-direction:column;gap:3px;width:auto;height:auto;min-width:54px;
    min-height:46px;padding:5px 7px}
  .pl-tool .lb{display:block;font-size:9.5px;font-weight:600;line-height:1;
    letter-spacing:.005em;white-space:nowrap}
  .pl-tool.sep{min-width:1px;min-height:0;padding:0}
}

@media print{
  .pl-top,.pl-left,.pl-right,.pl-tabbar,.pl-tools,.pl-zoom,.pl-cta{display:none !important}
  body.pl{background:#fff}
}

/* Выбор листа комплекта в окне результата: три листа одной геометрии —
   розетки, свет, слаботочка. Скачивается тот, что выбран. */
.pl-sheetpick { margin: 14px 0 4px }
.pl-sheetpick-t { font-size: 12px; color: #69748c; margin-bottom: 6px }
.pl-seg { display: inline-flex; gap: 2px; padding: 3px; border-radius: 10px; background: #eef0f4 }
.pl-seg button {
  border: 0; background: none; cursor: pointer; font: 600 13px/1 Inter, sans-serif;
  color: #69748c; padding: 7px 14px; border-radius: 8px;
}
.pl-seg button.on { background: #fff; color: #151a23; box-shadow: 0 1px 3px rgba(20,32,48,.14) }

/* Переключатель листа комплекта в шапке. Тот же язык, что у сегмента вида,
   но приглушённее: лист — это фильтр показа, а не смена подачи. */
.pl-sheetseg { margin-right: 8px }
.pl-sheetseg button { font-weight: 600 }
@media (max-width: 1180px) { .pl-sheetseg { display: none } }
/* Ниже 1500 сегмент листов сворачивается до цветных точек: он самый широкий
   в шапке (334 px из 1599 на 1400), и без этого «Результат» не помещался на
   обычном ноутбуке. Кнопка «Все» подпись сохраняет — у неё нет точки, и без
   текста она превратилась бы в пустой прямоугольник. Название листа остаётся
   в подсказке при наведении и в тосте после переключения. */
@media (max-width:1500px){
  .pl-sheetseg button[data-sheetv]:not([data-sheetv=""]) span{display:none}
  .pl-sheetseg button{padding:0 9px}
}
.pl-sheetdot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; margin-right: 6px }

/* Подсказка под курсором: что за обозначение под ним. Значок на чертеже
   читает электрик, хозяину дома нужна подпись словами. */
.pl-hovertip {
  position: absolute; z-index: 6; pointer-events: none;
  background: #151a23; color: #fff; font: 500 12px/1.35 Inter, sans-serif;
  padding: 6px 9px; border-radius: 7px; max-width: 260px;
  box-shadow: 0 6px 18px rgba(20,32,48,.22);
}

/* Панель группы: что именно выбрано и сколько. */
.pl-multilist { padding: 4px 15px 10px }
.pl-multirow {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 7px 0; border-bottom: 1px solid #eef0f4; font-size: 13px; color: #3f4756;
}
.pl-multirow:last-child { border-bottom: 0 }
.pl-multirow b { color: #151a23 }
.pl-btn.pl-wide { width: 100%; justify-content: center }

/* Цветная точка у подписи поля пометки — тот же цвет, что и знак на плане. */
.pl-notedot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 5px }
.pl-notedot.red { background: #D92D20 }
.pl-notedot.green { background: #12A150 }

/* Список «какой выключатель включает этот светильник». */
.pl-linklist { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px }
.pl-linkrow { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #3f4756 }
.pl-linkrow b {
  min-width: 20px; height: 20px; border-radius: 50%; background: #545454; color: #fff;
  font: 700 11px/20px Inter, sans-serif; text-align: center; flex: none;
}
.pl-linkrow span { flex: 1 }
.pl-linkoff {
  border: 0; background: none; cursor: pointer; color: #9aa4b4; font-size: 16px;
  line-height: 1; padding: 2px 4px;
}
.pl-linkoff:hover { color: #d92d20 }

/* ───────────────── Комментарии на плане ─────────────────
   Переписка клиента и монтажника поверх чертежа. Цвета сторон те же, что у
   пометок к устройствам (красный — монтажник, зелёный — клиент): одна
   азбука на весь конструктор. */
.pl-cmtdot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: 0 0 auto }
.pl-cmtdot.installer { background: #D92D20 }
.pl-cmtdot.client { background: #12A150 }
.pl-cmtdot.done { background: #98A2B3 }

.pl-cmtlist { display: flex; flex-direction: column; gap: 2px; margin: 9px 0 2px }
.pl-cmtrow {
  display: flex; align-items: flex-start; gap: 8px; width: 100%; text-align: left;
  padding: 8px 9px; border: none; border-radius: var(--pl-r-s);
  background: var(--pl-sunken); transition: .12s;
}
.pl-cmtrow:hover { background: #eceff5 }
.pl-cmtrow .pl-cmtdot { margin-top: 5px }
/* Первая строка ветки — приманка для глаза, но не пересказ: длинный текст
   режется, разговор читается внутри ветки. */
.pl-cmtrow .tx {
  flex: 1 1 auto; min-width: 0; font-size: 12.5px; color: var(--pl-text); line-height: 1.4;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.pl-cmtrow .tx b { font-weight: 600; color: var(--pl-muted); font-size: 11.5px }
.pl-cmtrow .n {
  flex: 0 0 auto; min-width: 19px; height: 19px; border-radius: 10px; background: #dfe3ea;
  color: var(--pl-muted); font-size: 11px; font-weight: 700; line-height: 19px; text-align: center;
}
.pl-cmtrow.done .tx { color: var(--pl-faint) }
.pl-cmttoggle {
  display: flex; align-items: center; gap: 7px; margin-top: 9px;
  font-size: 12px; color: var(--pl-muted); cursor: pointer;
}
.pl-cmttoggle input { width: 15px; height: 15px; accent-color: var(--pl-accent) }

.pl-cmtthread { display: flex; flex-direction: column; gap: 8px; margin: 10px 12px }
.pl-cmtmsg { padding: 10px 12px; border-radius: var(--pl-r-s); background: var(--pl-sunken) }
/* Свои реплики выделены фоном: в переписке двоих важно сразу видеть, где чей
   голос, не вчитываясь в подпись. */
.pl-cmtmsg.mine { background: var(--pl-accent-soft) }
.pl-cmtmsg .hd { display: flex; align-items: center; gap: 6px; margin-bottom: 4px }
.pl-cmtmsg .hd b { font-size: 11.5px; font-weight: 600; color: var(--pl-muted) }
.pl-cmtmsg .hd .you {
  font-size: 10px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  color: var(--pl-accent);
}
.pl-cmtmsg .hd .dt { margin-left: auto; font-size: 11px; color: var(--pl-faint) }
.pl-cmtmsg .bd { font-size: 13px; line-height: 1.45; white-space: pre-wrap; word-break: break-word }

.pl-cmtacts { display: flex; gap: 8px; margin: 2px 12px 10px }
.pl-cmtacts .pl-btn { flex: 1 1 0; justify-content: center }

/* Управление светом в карточке: обычная кнопка, состояние ожидания и
   подсказка «рядом». Раньше это были три одинаковые серые плашки во всю
   ширину — читалось как временная заглушка. */
.pl-linkbtn { width: 100%; justify-content: center; gap: 7px; margin-top: 2px }
.pl-linkbtn-i { display: inline-flex; width: 15px; height: 15px; opacity: .55 }
.pl-linkbtn-i svg { width: 100%; height: 100% }

.pl-linkarm {
  display: flex; align-items: center; gap: 8px; margin-top: 2px;
  padding: 9px 10px 9px 12px; border-radius: 10px;
  background: #fff4e9; border: 1px solid #f7c99a;
}
.pl-linkarm .dot {
  width: 8px; height: 8px; border-radius: 50%; background: #f97a1f; flex: none;
  animation: plLinkPulse 1.1s ease-in-out infinite;
}
@keyframes plLinkPulse { 0%,100% { opacity: 1 } 50% { opacity: .25 } }
.pl-linkarm .t { flex: 1; font-size: 13px; color: #8a4a10; font-weight: 600 }
.pl-linkarm-x {
  border: 0; background: none; cursor: pointer; padding: 2px; line-height: 0;
  color: #b3752f; width: 20px; height: 20px; flex: none;
}
.pl-linkarm-x svg { width: 100%; height: 100% }
.pl-linkarm-x:hover { color: #8a4a10 }

.pl-linkhint {
  display: flex; align-items: center; gap: 10px; margin-top: 8px;
  padding: 8px 10px; border-radius: 10px; background: #f5f6f8;
}
.pl-linkhint .c { flex: 1; min-width: 0; line-height: 1.3 }
.pl-linkhint b { display: block; font-size: 11px; color: #8a93a5; font-weight: 600 }
.pl-linkhint span {
  display: block; font-size: 13px; color: #3f4756;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pl-linkhint-go {
  border: 0; background: none; cursor: pointer; flex: none;
  font: 600 13px Inter, sans-serif; color: #f97a1f; padding: 4px 2px;
}
.pl-linkhint-go:hover { color: #e8690d; text-decoration: underline }

/* ───────────────── Экран внимания ─────────────────
   Встречный экран клиенту после разбора: план приглушён вуалью на холсте,
   светятся только отмеченные места, а текст замечания живёт в карточке —
   на телефоне навести нечем, и по наведению его не прочитать. */
.pl-att { position: fixed; inset: 0; z-index: 190; pointer-events: none }
.pl-att .card {
  position: absolute; pointer-events: auto;
  width: min(330px, calc(100vw - 24px)); padding: 15px 16px 12px;
  background: var(--pl-panel); border-radius: var(--pl-r);
  box-shadow: var(--pl-sh-pop); transition: left .2s ease, top .2s ease;
}
.pl-att .card > b { display: block; font-size: 14.5px; margin-bottom: 5px; padding-right: 24px }
.pl-att .card > p {
  margin: 0 0 12px; font-size: 13px; color: var(--pl-text); line-height: 1.5;
  white-space: pre-wrap; word-break: break-word;
}
/* Род замечания подписан словами, а не только цветом: «учтите» и «ответьте» —
   разные обязательства, и путать их клиенту не нужно. */
.pl-att .kind {
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  margin-bottom: 6px;
}
.pl-att .kind.note { color: #D92D20 }
.pl-att .kind.comment { color: #12A150 }
.pl-att .x {
  position: absolute; top: 9px; right: 9px; width: 26px; height: 26px;
  border: none; border-radius: 7px; background: transparent; color: var(--pl-faint);
}
.pl-att .x:hover { background: var(--pl-sunken); color: var(--pl-text) }
.pl-att .foot { display: flex; align-items: center; gap: 8px }
.pl-att .pos { font-size: 11.5px; color: var(--pl-faint); font-variant-numeric: tabular-nums }

/* Кнопка возврата в шапке: тихая, с числом. */
#plAttBtn { border: 1px solid var(--pl-line); font-size: 12.5px; padding: 0 11px; min-height: 32px }

@media (max-width: 900px) {
  /* На телефоне карточка липнет к низу: гоняться за ней по экрану,
     когда план ещё и переезжает, невозможно. */
  .pl-att .card {
    left: 12px !important; right: 12px; width: auto;
    /* Таб-бар внизу занимает ~62px вместе с безопасной зоной — карточка
       садится над ним, а не поверх «Плана» и «Итога». */
    top: auto !important; bottom: calc(74px + env(safe-area-inset-bottom));
  }
}

/* Кнопка «Причесать» у пометки монтажника: инструмент внутри поля, а не
   отдельное действие панели — поэтому живёт в строке подписи и не спорит
   с ней по весу. */
.pl-field label.pl-lblrow{display:flex;align-items:center;justify-content:space-between;gap:8px}
.pl-aibtn{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--pl-line);
  background:var(--pl-bg);color:var(--pl-muted);border-radius:7px;padding:2px 7px;
  font:inherit;font-size:11px;font-weight:600;line-height:18px;cursor:pointer;
  text-transform:none;letter-spacing:0}
.pl-aibtn:hover:not(:disabled){color:var(--pl-accent);border-color:var(--pl-accent)}
.pl-aibtn:disabled{opacity:.55;cursor:default}
.pl-aibtn svg{flex:none;opacity:.75}

/* ───────────────── Развёртка стены (вид спереди) ───────────────── */
.pl-elevbtn{width:100%;justify-content:flex-start}
.pl-elevbtn-i{display:inline-flex;color:var(--pl-blue)}
.pl-elevbtn-i svg{width:18px;height:18px}

.pl-elev{display:flex;flex-direction:column;gap:12px;padding-top:2px}
.pl-elev-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.pl-elev-where{display:flex;align-items:baseline;gap:9px;flex:1;min-width:180px}
.pl-elev-where b{font-size:14px}
.pl-elev-where span{font-size:12.5px;color:var(--pl-muted)}
.pl-elev-ceil{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;
  color:var(--pl-muted);white-space:nowrap}
.pl-elev-ceil input{width:78px;height:32px;padding:0 8px;border:1px solid var(--pl-line);
  border-radius:var(--pl-r-xs);background:var(--pl-panel);text-align:right;font-size:13px}
.pl-elev-ceil input:focus{outline:none;border-color:var(--pl-accent)}

.pl-elev-box{overflow-x:auto;overflow-y:hidden;border:1px solid var(--pl-line);
  border-radius:var(--pl-r-s);background:var(--pl-panel);-webkit-overflow-scrolling:touch}
.pl-elev-box canvas{display:block}

.pl-elev-list{display:flex;flex-direction:column;gap:2px}
.pl-elev-row{display:flex;align-items:center;gap:9px;width:100%;padding:6px 8px;
  border:none;border-radius:var(--pl-r-xs);background:transparent;text-align:left;
  font-size:13px;transition:.12s}
.pl-elev-row:hover{background:var(--pl-sunken)}
.pl-elev-row i{width:9px;height:9px;border-radius:50%;flex:none}
.pl-elev-row b{font-weight:600;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.pl-elev-row span{font-size:12px;font-weight:600;color:var(--pl-blue);
  background:var(--pl-blue-soft);border-radius:20px;padding:2px 8px;flex:none}
.pl-elev-row em{font-style:normal;font-size:12px;color:var(--pl-faint);flex:none}

.pl-elev-notes{margin:0;padding:0 0 4px 16px;display:flex;flex-direction:column;gap:4px}
.pl-elev-notes li{font-size:12.3px;color:var(--pl-muted);line-height:1.45}

@media (max-width:560px){
  .pl-elev-row{flex-wrap:wrap;gap:6px 8px;padding:7px 8px}
  .pl-elev-row b{flex:1 0 100%;white-space:normal}
  .pl-elev-where{flex:1 0 100%}
}
.pl-elev-hint{font-size:12.3px;color:var(--pl-faint);padding:2px 8px}

/* ───────────── Перелёт к щиту и его лицевая панель ─────────────
   Одно движение: план отходит назад от точки щита, сама отметка
   поднимается с чертежа и разворачивается лицом к зрителю. Всё, что
   двигается, — это transform и opacity: перелёт не должен стоить кадров
   на слабой машине. Кто отключил анимации, получает то же состояние без
   движения (класс ставится, переходов нет). */

.pl-flight{position:fixed;inset:0;z-index:240;pointer-events:none}
.pl-flight.on{pointer-events:auto}
.pl-flight--live .pl-flight-veil{cursor:zoom-out}
.pl-flight--noanim *{transition:none !important;animation:none !important}

.pl-flight-veil{position:absolute;inset:0;opacity:0;
  background:radial-gradient(135% 115% at 50% 40%,rgba(12,16,25,.55),rgba(6,8,14,.93));
  transition:opacity .34s ease}
.pl-flight.on .pl-flight-veil{opacity:1}

.pl-flight-stage{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  padding:20px;perspective:1150px;perspective-origin:50% 42%}
/* Подлёт и разворот — две дорожки одного движения. Коробка приезжает
   быстро и решительно, разворот идёт дольше и мягче: если крутить тем же
   рывком, поворот заканчивается за первую треть пути и его не видно. */
.pl-flight-box{position:relative;width:min(560px,86vw);transform-style:preserve-3d;
  transition:transform .4s cubic-bezier(.22,.68,.24,1)}
.pl-flight-turn{position:relative;transform-style:preserve-3d;transform-origin:50% 64%;
  transition:transform .48s cubic-bezier(.3,.78,.28,1)}

/* Корпус: тёмная дверца, за ней светлая лицевая плита. Тёмная рамка — это
   ещё и склейка с планом: знак щита на чертеже такой же тёмный квадрат. */
.pl-flight-face{position:relative;overflow:hidden;border-radius:16px;padding:12px;
  background:linear-gradient(180deg,#232936,#141821);
  box-shadow:0 1px 4px rgba(0,0,0,.4);
  transition:box-shadow .42s ease}
.pl-flight.on .pl-flight-face{
  box-shadow:0 44px 120px rgba(3,5,11,.7),0 8px 26px rgba(0,0,0,.5),
             inset 0 1px 0 rgba(255,255,255,.1)}

/* Толщина корпуса: грань стоит перпендикулярно лицу, поэтому видна ровно
   настолько, насколько щит наклонён, и сама уходит, когда он развернулся. */
.pl-flight-edge{position:absolute;left:7px;right:7px;top:100%;height:20px;
  transform-origin:top center;transform:rotateX(-90deg);border-radius:0 0 7px 7px;
  background:linear-gradient(180deg,#2c333f,#0d1017)}

/* Блик по дверце в момент разворота — то, из-за чего движение читается
   как поворот предмета, а не как масштабирование картинки. */
.pl-flight-gloss{position:absolute;left:0;top:-60%;width:38%;height:220%;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.17),transparent);
  transform:translate3d(-160%,0,0) rotate(15deg);opacity:0}
.pl-flight.on .pl-flight-gloss{animation:plGloss .8s cubic-bezier(.3,.6,.2,1) .05s 1 both}
@keyframes plGloss{
  0%{transform:translate3d(-160%,0,0) rotate(15deg);opacity:0}
  25%{opacity:1}
  100%{transform:translate3d(420%,0,0) rotate(15deg);opacity:0}}

/* Содержимое проявляется чуть позже самого движения: пока щит поднимается,
   он ещё выглядит как знак на плане, и склейки не видно. */
.pl-shield-head,.pl-shield-plate,.pl-shield-foot{opacity:0;transition:opacity .24s ease .1s}
.pl-flight.on .pl-shield-head,
.pl-flight.on .pl-shield-plate,
.pl-flight.on .pl-shield-foot{opacity:1}

.pl-shield-head{display:flex;align-items:baseline;gap:12px;padding:3px 7px 12px;color:#eef1f6}
.pl-shield-head b{flex:1 1 auto;min-width:0;font-size:15.5px;font-weight:700;letter-spacing:-.015em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pl-shield-head span{flex:0 1 auto;min-width:0;font-size:11px;font-weight:600;letter-spacing:.09em;
  text-transform:uppercase;color:#8b95a8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Крестик нужен только там, где лицевая панель — конечная остановка
   (клиент). На пути в Shield Designer закрывать нечего: страница уходит. */
.pl-shield-x{display:none;align-self:center;flex:0 0 auto;width:28px;height:28px;padding:0;
  margin:-6px -3px -6px 0;border:none;border-radius:8px;background:transparent;color:#8b95a8}
.pl-flight--live .pl-shield-x{display:inline-flex;align-items:center;justify-content:center}
.pl-shield-x:hover{background:rgba(255,255,255,.08);color:#eef1f6}

/* Лицевая плита с рейками — так, как выглядит настоящая крышка модульного
   щита: светлые накладки с прорезями под ручки аппаратов и винты по углам.
   Прорези пустые намеренно: какие аппараты встанут на место, решает
   электрик в Shield Designer (CLAUDE.md п.13, п.14). Рисовать сюда
   выдуманные автоматы было бы враньём в публичном контуре. */
.pl-shield-plate{display:grid;gap:8px;padding:13px 11px;border-radius:9px;
  /* Винты по углам. Последняя остановка обязана быть прозрачной: за
     пределами круга градиент продолжает свой последний цвет и заливает им
     всю плиту — четыре таких слоя делали её тёмной. */
  background-image:
    radial-gradient(circle 3px at 9px 9px,#fff 0 28%,#a9b1bf 62%,rgba(19,23,34,.5) 96%,rgba(0,0,0,0) 96%),
    radial-gradient(circle 3px at calc(100% - 9px) 9px,#fff 0 28%,#a9b1bf 62%,rgba(19,23,34,.5) 96%,rgba(0,0,0,0) 96%),
    radial-gradient(circle 3px at 9px calc(100% - 9px),#fff 0 28%,#a9b1bf 62%,rgba(19,23,34,.5) 96%,rgba(0,0,0,0) 96%),
    radial-gradient(circle 3px at calc(100% - 9px) calc(100% - 9px),#fff 0 28%,#a9b1bf 62%,rgba(19,23,34,.5) 96%,rgba(0,0,0,0) 96%),
    linear-gradient(180deg,#e9edf4,#d6dce7);
  background-repeat:no-repeat;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),inset 0 -1px 0 rgba(19,23,34,.14),
             0 1px 2px rgba(0,0,0,.35)}
.pl-shield-rail{position:relative;height:clamp(22px,4.4dvh,32px);border-radius:3px;
  background:linear-gradient(180deg,#fdfeff,#eef1f7 44%,#e4e9f1 56%,#f7f9fc);
  box-shadow:inset 0 0 0 1px rgba(19,23,34,.17),0 1px 1px rgba(19,23,34,.10)}
.pl-shield-rail i{position:absolute;left:9px;right:9px;top:50%;height:46%;display:block;
  transform:translateY(-50%);border-radius:2px;
  background-color:#2a3040;
  background-image:linear-gradient(90deg,rgba(255,255,255,.16) 0 1px,transparent 1px);
  background-size:calc(100% / var(--mods,12)) 100%;
  box-shadow:inset 0 1px 3px rgba(0,0,0,.6),0 1px 0 rgba(255,255,255,.6)}

.pl-shield-foot{display:flex;align-items:center;gap:9px;padding:12px 7px 2px;
  font-size:12.5px;color:#98a2b4}
.pl-shield-est{margin-left:auto;flex:0 0 auto;font-size:10px;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:#c3cad7;padding:2px 7px;border-radius:5px;
  border:1px solid rgba(255,255,255,.17)}
.pl-shield-spin{flex:0 0 auto;width:13px;height:13px;border-radius:50%;
  border:2px solid rgba(255,255,255,.18);border-top-color:var(--pl-accent);
  animation:plSpin .7s linear infinite}
@keyframes plSpin{to{transform:rotate(360deg)}}

/* План отходит назад — и отходит именно от щита: точку отсчёта ставит JS. */
.pl-canvas{transition:transform .42s cubic-bezier(.19,.72,.22,1),opacity .42s ease}
.pl-stage.pl-flying .pl-canvas{transform:scale(1.07);opacity:.4}

/* Нырок сквозь дверцу: коробка проходит мимо зрителя и гаснет, вуаль
   добирает до полной темноты. Дальше уже страница щита всплывает из этой
   же темноты — стык приходится на чёрный кадр, а не на светлую панель. */
.pl-flight--dive .pl-flight-box{transform:scale(1.3);opacity:0;
  transition:transform .2s cubic-bezier(.5,0,.85,.4),opacity .2s ease-in .02s}
.pl-flight--dive .pl-flight-veil{background:#06080e;transition:opacity .34s ease,background .2s ease}

.pl-shield-go{width:100%;margin-top:11px}

@media (max-width:560px){
  .pl-shield-head b{font-size:14px}
  .pl-shield-head span{font-size:10px}
  .pl-flight-face{border-radius:14px;padding:10px}
}

@media (prefers-reduced-motion:reduce){
  .pl-flight *,.pl-canvas{transition:none !important;animation:none !important}
  .pl-stage.pl-flying .pl-canvas{transform:none;opacity:.4}
}

/* Ввод размера прямо на плане: поле встаёт на место бейджа и повторяет его
   вид, чтобы подпись не «прыгала» при переходе в редактирование. */
.pl-diminput{position:fixed;z-index:320;width:68px;height:24px;padding:0 6px;
  border:0;border-radius:7px;background:rgba(52,104,209,.97);color:#fff;
  font:700 12px Inter,sans-serif;text-align:center;box-shadow:0 3px 10px rgba(20,40,90,.3)}
.pl-diminput:focus{outline:2px solid #fff;outline-offset:-2px}
.pl-diminput::-webkit-outer-spin-button,
.pl-diminput::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* ───────── Разбор правок клиента ─────────
   Карточка та же, что у экрана внимания (.pl-att), отличаются подпись рода и
   кнопки: там «учтите», здесь «принять или нет». */
.pl-review .kind.add { color: #12A150 }
.pl-review .kind.del { color: #D92D20 }
.pl-review .kind.change { color: #B4621D }
/* Зависимость называется словами: молча принять два объекта вместо одного —
   значит соврать про то, что человек сделал. */
.pl-review .dep {
  margin: -6px 0 10px; padding: 7px 9px; border-radius: var(--pl-r-xs);
  background: var(--pl-amber-soft); color: #8a5b12; font-size: 12px; line-height: 1.4;
}
#plEditsBtn { border: 1px solid var(--pl-line); font-size: 12.5px; padding: 0 11px; min-height: 32px }
/* Клиенту та же кнопка служит подписью и никуда не ведёт — она не должна
   выглядеть нажимаемой. */
#plEditsBtn.pl-flat { cursor: default; background: var(--pl-amber-soft);
  border-color: #f0e0bd; color: #8a5b12 }
#plEditsBtn.pl-flat:hover { background: var(--pl-amber-soft) }

/* Карандаш у своей реплики. Появляется только у своих: подменять чужие слова
   в общем разговоре нельзя, и предлагать это кнопкой тоже не следует. */
.pl-cmtedit{margin-left:auto;border:0;background:transparent;color:var(--pl-faint);
  padding:2px 4px;border-radius:6px;line-height:0;cursor:pointer}
.pl-cmtedit:hover{color:var(--pl-accent);background:var(--pl-sunken)}

/* ───────────────── Крыша и трассы (PLANNER_ROUTING.md) ───────────────── */
#plRoutesBtn{border:1px solid var(--pl-line);font-size:12.5px;padding:0 11px;min-height:32px}
.pl-roof-sep{height:1px;background:var(--pl-line);margin:14px 15px}
.pl-roof-pitched .pl-field:first-child{margin-top:0}
#plRoofRidgeBtn{margin-right:8px}
#plRouteRecalc{margin-right:8px}
.pl-route-total{margin:10px 15px;font-size:13.5px;color:var(--pl-text)}
.pl-route-table{width:calc(100% - 30px);margin:4px 15px 10px;border-collapse:collapse;font-size:12.5px}
.pl-route-table td{padding:5px 8px;border-bottom:1px solid var(--pl-line2);color:var(--pl-muted)}
.pl-route-table td:last-child{text-align:right;color:var(--pl-text);white-space:nowrap}

/* ───────────── 3D-сцена трасс (planner_scene.js, только монтажнику) ─────────────
   Холст слева, карточка выбранного справа; на телефоне карточка уходит вниз.
   Холст сам подбирает высоту от окна, поэтому у бокса высоты нет. */
.pl-scene{display:flex;gap:14px;align-items:flex-start}
.pl-scene-box{position:relative;flex:1;min-width:0;border:1px solid var(--pl-line);
  border-radius:var(--pl-r-s);background:#f8fafc;overflow:hidden}
.pl-scene-box canvas{display:block;width:100%;touch-action:none;cursor:grab}
.pl-scene-tools{position:absolute;left:8px;top:8px;display:flex;gap:8px;align-items:center;
  background:rgba(255,255,255,.85);border-radius:var(--pl-r-xs);padding:4px 6px}
.pl-scene-chk{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;color:var(--pl-muted)}
.pl-scene-card{width:280px;flex:none;display:flex;flex-direction:column;gap:6px;font-size:13px}
.pl-scene-card h4{margin:0 0 4px;font-size:15px}
.pl-scene-card h5{margin:8px 0 2px;font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:var(--pl-muted)}
.pl-scene-kv{display:flex;align-items:center;gap:8px;justify-content:space-between;padding:3px 0;
  border-bottom:1px dashed var(--pl-line)}
.pl-scene-kv span{color:var(--pl-muted)}
.pl-scene-kv b{font-weight:600;white-space:nowrap}
.pl-scene-total b{color:var(--pl-blue);font-size:15px}
.pl-scene-adj{flex-wrap:wrap;justify-content:flex-start}
.pl-scene-adj input{width:64px;height:30px;padding:0 6px;border:1px solid var(--pl-line);
  border-radius:var(--pl-r-xs);background:var(--pl-panel);text-align:right;font-size:13px}
.pl-scene-muted{margin:2px 0;font-size:12.3px;color:var(--pl-muted);line-height:1.45}
.pl-scene-bad{margin:2px 0;font-size:12.5px;color:#b91c1c}
.pl-scene-row{display:flex;align-items:center;gap:8px;width:100%;padding:5px 6px;border:none;
  border-radius:var(--pl-r-xs);background:transparent;text-align:left;font-size:12.5px;cursor:pointer}
.pl-scene-row:hover{background:var(--pl-sunken)}
.pl-scene-row i{width:9px;height:9px;border-radius:50%;flex:none}
.pl-scene-row b{font-weight:500;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pl-scene-row span{font-size:12px;font-weight:600;color:var(--pl-blue);flex:none}
.pl-scene-tools input[type=range]{width:80px;vertical-align:middle}
.pl-scene-seg{display:inline-flex;gap:2px}
.pl-shieldplan-wrap{overflow:auto;max-height:60vh;border:1px solid var(--pl-line);border-radius:var(--pl-r-s)}
.pl-shieldplan-t{width:100%;border-collapse:collapse;font-size:12.5px}
.pl-shieldplan-t th{position:sticky;top:0;background:var(--pl-panel);text-align:left;padding:6px 8px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--pl-muted);border-bottom:1px solid var(--pl-line)}
.pl-shieldplan-t td{padding:5px 8px;border-bottom:1px dashed var(--pl-line);vertical-align:top}
.pl-shieldplan-t select{height:28px;padding:0 4px;font-size:12.5px;border:1px solid var(--pl-line);border-radius:var(--pl-r-xs);background:var(--pl-panel)}
.pl-shieldplan-t tr.is-assigned td{color:var(--pl-muted)}
.pl-shieldplan-sum{margin-top:8px;font-size:13px}
.pl-scene-build{margin-top:6px}
.pl-scene-progress{height:6px;border-radius:3px;background:var(--pl-sunken);overflow:hidden}
.pl-scene-progress i{display:block;height:100%;background:var(--pl-blue)}
.pl-scene-work-head{display:flex;align-items:flex-start;gap:8px;padding:6px 0;font-size:12.5px}
.pl-scene-work-head i{width:10px;height:10px;border-radius:50%;flex:none;margin-top:3px}
.pl-scene-work-head>div{flex:1;min-width:0}
.pl-scene-work-head span{font-weight:600;color:var(--pl-muted);flex:none}
.pl-scene-steps{margin:4px 0;padding-left:20px;font-size:13px;line-height:1.45}
.pl-scene-steps li{margin:3px 0}
.pl-scene-work-btns{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:6px}
.pl-scene-work-btns .pl-btn.primary{flex:1 1 100%;height:40px;font-size:14px}
.pl-routes-btn{display:inline-flex;align-items:center;gap:6px}
.pl-lines-legend{position:absolute;left:12px;bottom:12px;z-index:5;max-height:46%;overflow:auto;background:rgba(255,255,255,.94);
  border:1px solid var(--pl-line);border-radius:var(--pl-r-s);padding:8px 10px;font-size:12px;min-width:180px;max-width:260px;box-shadow:0 4px 14px rgba(15,23,42,.08)}
.pl-lines-legend b{display:block;margin-bottom:4px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--pl-muted)}
.pl-lines-legend div{display:flex;align-items:center;gap:7px;padding:2px 0;cursor:pointer}
.pl-lines-legend div:hover{color:var(--pl-blue)}
.pl-lines-legend i{width:10px;height:10px;border-radius:50%;flex:none}
.pl-lines-legend span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pl-lines-legend em{font-style:normal;color:var(--pl-muted)}
.pl-routes-layer{display:inline-flex;align-items:center}
.pl-routes-layer input{width:15px;height:15px;margin:0;cursor:pointer}
.pl-modal.pl-scene-full{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0}
.pl-overlay:has(.pl-scene-full){padding:0}
.pl-modal.pl-scene-full .bd{flex:1;overflow:auto}
.pl-modal.pl-scene-full footer{margin-top:6px;padding:10px 20px}
.pl-wallruns-sides{display:flex;gap:6px;flex-wrap:wrap}
.pl-lines-advice{border:1px solid var(--pl-line);border-radius:var(--pl-r-s);padding:8px 10px;background:var(--pl-sunken)}
.pl-lines-advice p{margin:4px 0}
.pl-lines-row{border-top:1px solid var(--pl-line);padding:8px 0}
.pl-lines-head{display:flex;align-items:center;gap:8px}
.pl-lines-head i{width:10px;height:10px;border-radius:50%;flex:none}
.pl-lines-head b{flex:1}
.pl-lines-head em{font-style:normal;font-size:12px;color:var(--pl-muted)}
.pl-lines-pts{display:flex;flex-direction:column;gap:3px;margin-top:6px}
.pl-lines-pt{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:12.5px;padding:2px 0 2px 18px}
.pl-lines-pt small{color:var(--pl-faint)}
.pl-lines-pt select{font:inherit;font-size:12px;padding:2px 4px;border:1px solid var(--pl-line);border-radius:var(--pl-r-xs);background:var(--pl-panel)}
@media (max-width:700px){
  .pl-scene{flex-direction:column;align-items:stretch}
  .pl-scene-box{width:100%}
  .pl-scene-card{width:100%}
}
