/* Планировщик квартиры — общие стили. Тёмная тема, адаптив до телефона. */
:root {
  --bg: #1e1f22;
  --panel: #2a2c30;
  --panel-2: #34373c;
  --line: #3a3d42;
  --txt: #e8e8e8;
  --mut: #9aa0a6;
  --acc: #4f8cff;
  --ok: #7fd77f;
  --warn: #ffd54f;
  --err: #ff7a7a;
  --radius: 8px;
  /* Размер цели касания зависит от указателя, а не от ширины экрана: iPad
     боком — это 1366 px и при этом палец. Значение поднимается в блоке
     @media (pointer: coarse). */
  --tap: 34px;
  --header-h: 48px;
  --side-w: 250px;
  --props-w: 288px;
  /* Ширина вертикального рейла инструментов и высота нижней панели. Ими
     пользуются оверлеи, чтобы не завязываться на числа-константы: раньше
     панель выделения стояла на bottom: 64px при реальной высоте панели 61. */
  --rail-w: 0px;
  --bar-h: env(safe-area-inset-bottom, 0px);
  --drawer-w: min(340px, 88vw);
}

* { box-sizing: border-box; }
html, body {
  margin: 0;
  height: 100%;
  font-family: "Segoe UI", Roboto, Arial, sans-serif;
  background: var(--bg);
  color: var(--txt);
  overscroll-behavior: none;
}
body { -webkit-text-size-adjust: 100%; }

button, select, input, textarea {
  background: var(--panel-2);
  color: var(--txt);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px 9px;
  font-size: 13px;
  font-family: inherit;
  min-height: var(--tap);
}
button { cursor: pointer; }
/* Снимает 300 мс задержки двойного тапа. Без неё, после того как из viewport
   убрали maximum-scale, каждый тап по кнопке ощущался бы вязким. */
button, select, input, textarea, .list-item, summary { touch-action: manipulation; }
button { -webkit-tap-highlight-color: transparent; }
button:focus-visible, input:focus-visible, select:focus-visible, a:focus-visible {
  outline: 2px solid var(--acc);
  outline-offset: 1px;
}
button:disabled { opacity: .5; cursor: not-allowed; }
button.acc { background: var(--acc); border-color: var(--acc); color: #fff; }
button.on { outline: 2px solid var(--acc); background: #3a4b6e; }
/* Отклик на касании: :hover на тач-устройствах залипает после тапа. */
button:active { background: #3f434a; }
button.acc:active { background: #6b9dff; }
button.danger { color: var(--err); }
button.mini { padding: 3px 7px; font-size: 12px; min-height: 26px; }
a { color: var(--acc); }

.sep { width: 1px; height: 22px; background: var(--line); flex: none; }
.spacer { flex: 1; }
.muted { color: var(--mut); font-size: 12px; }
.hint { color: var(--mut); font-size: 11px; margin: 4px 0; line-height: 1.45; }
.err-text { color: var(--err); font-size: 13px; min-height: 18px; }
.ok-text { color: var(--ok); font-size: 12px; min-height: 16px; }

/* ------------------------------------------------------------ вход / список */
.center-page {
  min-height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(24px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right))
           calc(24px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));
}
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 24px;
  width: min(420px, 100%);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .35);
}
.card h1 { margin: 0 0 4px; font-size: 21px; }
.card .sub { color: var(--mut); font-size: 13px; margin-bottom: 18px; }
.field { margin-bottom: 12px; }
.field label { display: block; font-size: 12px; color: var(--mut); margin-bottom: 4px; }
.field input { width: 100%; min-height: 40px; }
.card button[type="submit"] { width: 100%; min-height: 42px; font-size: 15px; }

.page {
  max-width: 1100px;
  margin: 0 auto;
  padding: 18px calc(16px + env(safe-area-inset-right))
           calc(60px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));
}
.page-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.page-head h1 { font-size: 20px; margin: 0; }
.plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px;
}
.plan-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.plan-card .thumb {
  height: 130px;
  background: #16171a center/contain no-repeat;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--mut);
  font-size: 12px;
}
.plan-card .body { padding: 10px 12px; flex: 1; }
.plan-card .body b { display: block; font-size: 14px; word-break: break-word; }
.plan-card .actions {
  display: flex;
  gap: 6px;
  padding: 0 10px 10px;
  flex-wrap: wrap;
}
.plan-card .actions button { flex: 1; min-width: 62px; font-size: 12px; }

/* ------------------------------------------------------------ редактор */
#app {
  display: grid;
  grid-template-columns: var(--side-w) 1fr var(--props-w);
  /* auto вместо фиксированной высоты: шапка переносит кнопки на вторую
     строку на узких экранах и не должна их обрезать. */
  grid-template-rows: auto 1fr;
  height: 100%;
  height: 100dvh;
  position: relative;
}
/* Свёрнутые боковые панели: на планшете боком две панели съедали 458 px
   из 1180. Кнопка в шапке убирает обе, холст занимает всю ширину. */
#app.panels-off { grid-template-columns: 1fr; }
#app.panels-off > .side { display: none; }
header {
  /* 1 / -1, а не 1 / 4: при свёрнутых панелях колонка остаётся одна, и
     жёсткое «до четвёртой» создало бы лишние неявные колонки. */
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  /* Шапка выше боковых панелей: выпадающее меню «Файл» уходило под панель
     свойств и было не видно. overflow-x тут держать нельзя по той же
     причине — он обрезал бы выпадающий список. */
  position: relative;
  z-index: 30;
  flex-wrap: wrap;
  row-gap: 4px;
}
header button, header select { flex: none; }
header .toolbar-label { color: var(--mut); font-size: 12px; white-space: nowrap; }
header label.check {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--mut);
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
}
header label.check input { width: auto; min-height: auto; }
#planTitle {
  font-weight: 600;
  font-size: 14px;
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#saveState { font-size: 12px; color: var(--mut); white-space: nowrap; }
#saveState.dirty { color: var(--warn); }
#saveState.saving { color: var(--acc); }
#saveState.error { color: var(--err); }

.side {
  background: var(--panel);
  overflow-y: auto;
  overflow-x: hidden;
  padding: 10px;
  border-right: 1px solid var(--line);
  -webkit-overflow-scrolling: touch;
}
.side.right { border-right: none; border-left: 1px solid var(--line); }
.side h3 {
  font-size: 12px;
  text-transform: uppercase;
  color: var(--mut);
  margin: 14px 0 6px;
  letter-spacing: .04em;
}
.side h3:first-child { margin-top: 0; }

/* auto-fill по ширине контейнера, а не экрана: палитра живёт в панели или в
   шторке шириной 340–400 px, и раньше на телефоне схлопывалась в одну колонку
   там, где помещаются две. */
.palette { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 6px; }
.palette button {
  font-size: 12px;
  padding: 7px 4px;
  min-height: var(--tap);
  text-align: center;
  line-height: 1.2;
}
.row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 5px 0;
  min-width: 0;
}
.row label { flex: 0 0 78px; color: var(--mut); font-size: 12px; }
.row input, .row select { flex: 1 1 0; width: auto; min-width: 0; }
.row input[type="checkbox"] { flex: 0 0 auto; width: auto; min-height: auto; }
.row input[type="color"] { flex: 0 0 46px; width: 46px; height: 32px; padding: 2px; }
.row button { flex: 0 0 auto; white-space: nowrap; }
.row .unit { color: var(--mut); font-size: 12px; flex: none; }

#main { position: relative; overflow: hidden; touch-action: none; }
canvas { display: block; width: 100%; height: 100%; touch-action: none; }
#threeWrap { position: absolute; inset: 0; display: none; touch-action: none; }
#threeWrap canvas { touch-action: none; }

.list-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 6px;
  padding: 6px;
  border-radius: 5px;
  font-size: 13px;
  cursor: pointer;
  min-height: 32px;
}
.list-item:active { background: var(--panel-2); }
.list-item.sel { background: #3a4b6e; }
.list-item .name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}
.list-item .x {
  color: var(--err);
  padding: 2px 6px;
  flex: none;
  border-radius: 4px;
}
.list-item .x:active { background: rgba(255, 122, 122, .15); }

.object-subcat { margin: 7px 0 0; }
.object-subcat > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: var(--mut);
  font-size: 11px;
  cursor: pointer;
  user-select: none;
  list-style: none;
  padding: 4px 0;
}
.object-subcat > summary::-webkit-details-marker { display: none; }
.object-subcat > summary::before { content: '▾'; width: 14px; flex: 0 0 14px; }
.object-subcat:not([open]) > summary::before { content: '▸'; }
.object-subcat > summary .object-subcat-title { flex: 1; min-width: 0; }
.object-subcat > summary .object-subcat-count { color: #c5c9d1; font-size: 10px; }
.object-subcat-body { display: grid; gap: 1px; }

#status, #hint, #hint3d {
  position: absolute;
  bottom: calc(8px + env(safe-area-inset-bottom));
  font-size: 12px;
  color: var(--mut);
  background: rgba(0, 0, 0, .55);
  padding: 4px 9px;
  border-radius: 6px;
  pointer-events: none;
  max-width: 46%;
}
#status { left: calc(8px + env(safe-area-inset-left)); }
#hint, #hint3d { right: calc(8px + env(safe-area-inset-right)); line-height: 1.4; }

textarea {
  width: 100%;
  height: 170px;
  background: #1b1c1f;
  color: #cfe;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 11px;
  padding: 8px;
}

dialog {
  background: var(--panel);
  color: var(--txt);
  border: 1px solid var(--line);
  border-radius: 12px;
  width: min(720px, 94vw);
  /* svh, а не vh: на iOS vh считается по большому вьюпорту, и низ диалога
     уходил под адресную строку. */
  max-height: 88svh;
  overflow: auto;
  padding: 18px;
}
dialog::backdrop { background: rgba(0, 0, 0, .55); }
dialog h3 { margin-top: 0; }
.dialog-actions {
  display: flex;
  gap: 8px;
  margin-top: 14px;
  flex-wrap: wrap;
  align-items: center;
}
.dialog-actions .right { margin-left: auto; }

.menu { position: relative; display: inline-block; }
.dropdown {
  position: absolute;
  right: 0;
  top: 110%;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px;
  min-width: 210px;
  z-index: 50;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .5);
  display: none;
}
.dropdown.open { display: block; }
.dropdown button {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  padding: 9px 10px;
  border-radius: 6px;
}
.dropdown button:active { background: #3a4b6e; }
.dropdown hr { border: none; border-top: 1px solid var(--line); margin: 5px 2px; }

.expgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; }
.expgrid button { padding: 13px 8px; font-size: 14px; }

.panel-section { border-top: 1px solid var(--line); padding-top: 8px; margin-top: 10px; }
.panel-section:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.panel-section > summary {
  cursor: pointer;
  color: var(--mut);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  margin: 0 0 7px;
  list-style: none;
  user-select: none;
  padding: 4px 0;
}
.panel-section > summary::-webkit-details-marker { display: none; }
.panel-section > summary::before { content: '▾'; display: inline-block; width: 14px; }
.panel-section:not([open]) > summary::before { content: '▸'; }

.edge-box { background: #3a371f; padding: 8px; border-radius: 8px; margin-bottom: 9px; }
.edge-box b { color: var(--warn); }
.surface-box { border-top: 1px solid var(--line); margin-top: 10px; padding-top: 6px; }

/* смета */
table.estimate { width: 100%; border-collapse: collapse; font-size: 13px; }
table.estimate th, table.estimate td {
  border-bottom: 1px solid var(--line);
  padding: 6px 8px;
  text-align: left;
}
table.estimate th { color: var(--mut); font-weight: 600; font-size: 11px; text-transform: uppercase; }
table.estimate td.num, table.estimate th.num { text-align: right; white-space: nowrap; }
table.estimate tr.total td { font-weight: 700; border-top: 2px solid var(--line); }
table.estimate tr.group td { background: #232529; font-weight: 600; }
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.toast {
  position: fixed;
  left: 50%;
  /* Над нижней панелью: --bar-h уже включает safe-area. Раньше тост стоял на
     фиксированных 22 px и выезжал поверх кнопок панели. */
  bottom: calc(16px + var(--bar-h));
  transform: translateX(-50%);
  background: #303338;
  border: 1px solid var(--line);
  color: var(--txt);
  padding: 10px 16px;
  border-radius: 10px;
  z-index: 200;
  font-size: 13px;
  max-width: min(520px, 92vw);
  box-shadow: 0 8px 26px rgba(0, 0, 0, .5);
}
.toast.err { border-color: var(--err); color: #ffd7d7; }
.toast.ok { border-color: var(--ok); }

/* ---------------------------------------------------- видимость по режимам
   Базовое состояние — десктоп: показано только «мышиное».
   Селекторы с .dropdown нужны по специфичности: у `.dropdown button` она выше,
   и без них пункты меню для касания оставались видны на десктопе. */
.touch-only, .phone-only, .wide-touch-only,
.dropdown .touch-only, .dropdown .phone-only { display: none; }

#drawerScrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .5);
  z-index: 60;
  display: none;
}
#drawerScrim.open { display: block; }

#mobileBar { display: none; }

/* ---------------------------------------------------- оверлеи внутри #main
   Панель выделения и лист инструментов позиционируются относительно холста,
   а не вьюпорта: на iOS position:fixed расходится с height:100dvh, а в
   рейловых раскладках низ экрана занят холстом, а не панелью. */
#selBar {
  position: absolute;
  left: calc(8px + env(safe-area-inset-left));
  right: calc(8px + env(safe-area-inset-right));
  bottom: 8px;
  z-index: 45;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .5);
}
#toolSheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 75;
  background: var(--panel);
  border-top: 1px solid var(--line);
  border-radius: 14px 14px 0 0;
  padding: 12px;
  box-shadow: 0 -8px 30px rgba(0, 0, 0, .5);
}
#selBar[hidden], #toolSheet[hidden] { display: none; }
/* Лист и панель выделения не показываются одновременно: раньше они ложились
   друг на друга тремя слоями вместе с нижней панелью. */
#main.sheet-open #selBar { display: none; }

.sheet-title {
  font-size: 12px;
  color: var(--mut);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: 10px;
}
.sheet-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.sheet-grid button {
  min-height: 64px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  font-size: 12px;
}
.sheet-grid button .icon { font-size: 22px; }

.sel-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 8px;
}
.sel-title span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sel-title button { min-height: 32px; padding: 2px 10px; border: none; background: none; color: var(--mut); }
.sel-actions { display: grid; gap: 4px; }
.sel-actions button { min-height: 46px; padding: 0; font-size: 17px; }
.sel-actions button:disabled { opacity: .35; }
.sel-step {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  font-size: 12px;
  color: var(--mut);
}
.sel-step button { flex: 1; min-height: 36px; font-size: 12px; }

/* Кнопки нижней панели и рейла выглядят одинаково во всех режимах —
   различается только раскладка контейнера. */
#mobileBar button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 4px 2px;
  border: none;
  background: none;
  color: var(--mut);
  line-height: 1.1;
  text-align: center;
  font-size: 10px;
}
#mobileBar button .icon { font-size: 20px; }
#mobileBar button.on { color: var(--acc); background: rgba(79, 140, 255, .12); outline: none; }

/* ============================================================ АДАПТИВ
   Пять режимов. Ключевое правило: ширина решает раскладку, тип указателя —
   размер целей касания. Раньше и то и другое висело на одном пороге 860 px,
   из-за чего iPad в портрете получал телефонный интерфейс, а iPad боком —
   мышиные кнопки в 34 px.

   Телефон              ≤599 px                       375 / 402 / 420 / 440
   Телефон боком        высота ≤500 px                667…956 × 375…440
   Планшет-портрет      600–1024 px, portrait         iPad mini 744 … 13" 1024
   Планшет боком        ≥1025 px + pointer: coarse    1133 … 1366
   Десктоп              базовые правила без запроса

   Порядок блоков важен: каскадных слоёв в проекте нет.                    */

/* Сужение боковых панелей двумя ступенями: диапазон 1025–1279 (ноутбуки 13",
   iPad 11 боком) раньше был зажат тем же правилом, что и 900 px. */
@media (max-width: 1279px) { :root { --side-w: 210px; --props-w: 248px; } }
@media (max-width: 899px)  { :root { --side-w: 180px; --props-w: 210px; } }

/* ------------------------------------------------------------------------
   ОБЩЕЕ ДЛЯ ВСЕХ РЕЖИМОВ СО ШТОРКАМИ
   Телефон в обеих ориентациях и планшет в портрете: боковые панели уезжают
   за край и вызываются кнопкой. */
@media (max-width: 1024px) and (orientation: portrait), (max-height: 500px) {
  header .desktop-only { display: none !important; }
  .touch-only { display: inline-flex; align-items: center; justify-content: center; }
  /* Пункт меню — блочный: inline-flex сломал бы ему ширину. */
  .dropdown .touch-only { display: block; }
  .dropdown label.touch-only { display: flex; }

  .side {
    position: fixed;
    top: 0;
    bottom: 0;
    width: var(--drawer-w);
    z-index: 70;
    box-shadow: 0 0 40px rgba(0, 0, 0, .6);
    /* visibility убирает закрытую шторку из порядка табуляции: раньше Tab из
       шапки уводил фокус в четыре десятка невидимых элементов. Задержка
       равна длительности выезда, иначе анимация обрывается. */
    visibility: hidden;
    transition: transform .2s ease-out, visibility 0s linear .2s;
  }
  .side.left {
    left: 0;
    transform: translateX(-102%);
    padding: calc(14px + env(safe-area-inset-top)) 12px
             calc(24px + env(safe-area-inset-bottom)) calc(12px + env(safe-area-inset-left));
  }
  .side.right {
    right: 0;
    transform: translateX(102%);
    padding: calc(14px + env(safe-area-inset-top)) calc(12px + env(safe-area-inset-right))
             calc(24px + env(safe-area-inset-bottom)) 12px;
  }
  .side.open {
    transform: translateX(0);
    visibility: visible;
    transition: transform .2s ease-out, visibility 0s;
  }

  .dropdown { min-width: 240px; max-height: 70dvh; overflow-y: auto; }
  .dropdown .menu-check {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    min-height: 44px;
    color: var(--txt);
    font-size: 13px;
  }
  .dropdown .menu-check input { width: 20px; height: 20px; }

  .row label { flex: 0 0 96px; }
}

/* ------------------------------------------------------------------------
   ШАПКА ТЕЛЕФОНА (обе ориентации)
   Остаётся только то, что нужно всегда: меню, название, состояние, отмена. */
@media (max-width: 599px), (max-height: 500px) {
  header .phone-hidden { display: none !important; }
  .phone-only { display: inline-flex; align-items: center; justify-content: center; }

  header {
    gap: 4px;
    min-height: var(--header-h);
    padding: 0 calc(8px + env(safe-area-inset-right)) 0 calc(8px + env(safe-area-inset-left));
    padding-top: env(safe-area-inset-top);
    /* Ничего не переносим: содержимое помещается в одну строку. */
    flex-wrap: nowrap;
    overflow: hidden;
  }
  #planTitle { flex: 1; min-width: 0; max-width: none; font-size: 15px; }
  /* На узком экране от статуса нужен только цветной индикатор. */
  #saveState { font-size: 0; }
  #saveState::before { content: '●'; font-size: 15px; }

  /* Диалог листом снизу: холст остаётся виден, закрывать удобнее большим
     пальцем. Высота по содержимому — короткий диалог остаётся коротким,
     длинный дорастает до 88svh, отдельных правил под каждый не нужно. */
  dialog {
    width: 100%;
    max-width: none;
    max-height: 88svh;
    margin: auto 0 0;
    border-radius: 14px 14px 0 0;
    padding: 14px 14px calc(14px + env(safe-area-inset-bottom));
  }
  .dialog-actions {
    position: sticky;
    bottom: calc(-14px - env(safe-area-inset-bottom));
    margin: 14px -14px calc(-14px - env(safe-area-inset-bottom));
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
    background: var(--panel);
    border-top: 1px solid var(--line);
  }

  .page { padding: 14px calc(12px + env(safe-area-inset-right))
                  calc(40px + env(safe-area-inset-bottom)) calc(12px + env(safe-area-inset-left)); }
  .page-head h1 { flex: 1 0 100%; font-size: 18px; }
  .page-head button { flex: 1 1 calc(50% - 6px); }
  .page-head .spacer { display: none; }
}

/* ------------------------------------------------------------------------
   ТЕЛЕФОН, ПОРТРЕТ (≤599 px)
   Нижняя панель под большим пальцем, лист инструментов выезжает над ней. */
@media (max-width: 599px) {
  :root {
    --header-h: 52px;
    /* 52 (кнопка) + 4 + 4 (padding) + 1 (граница) — считаем, а не угадываем:
       панель выделения раньше стояла на 64 px при реальной высоте 61. */
    --bar-h: calc(61px + env(safe-area-inset-bottom));
    --drawer-w: min(340px, 88vw);
  }

  #app { grid-template-columns: 1fr; grid-template-rows: auto 1fr auto; }
  #main { grid-column: 1; grid-row: 2; }

  #mobileBar {
    display: grid;
    grid-column: 1;
    grid-row: 3;
    grid-template-columns: repeat(4, 1fr);
    gap: 2px;
    padding: 4px calc(4px + env(safe-area-inset-right))
             calc(4px + env(safe-area-inset-bottom)) calc(4px + env(safe-area-inset-left));
    background: var(--panel);
    border-top: 1px solid var(--line);
    z-index: 40;
  }
  #mobileBar button { min-height: 52px; }

  #status { font-size: 12px; max-width: calc(100% - 16px); }

  /* Девять кнопок в ряд давали 34,5 px на кнопку при экране 375 px. Пять в
     два ряда дают 65 px. «Удалить» уводим в дальний угол, чтобы не стояла
     вплотную к «Дублировать». */
  .sel-actions { grid-template-columns: repeat(5, 1fr); }
  #selDelete { grid-column: 5; }
}

/* ------------------------------------------------------------------------
   РЕЙЛОВЫЕ РАСКЛАДКИ (планшет-портрет и телефон боком)
   Нижняя панель становится вертикальной: по горизонтали места в избытке,
   по вертикали его нет либо оно ценнее. */
@media (min-width: 600px) and (max-width: 1024px) and (orientation: portrait),
       (max-height: 500px) {
  #app { grid-template-columns: var(--rail-w) 1fr; grid-template-rows: auto 1fr; }
  #main { grid-column: 2; grid-row: 2; }

  #mobileBar {
    display: grid;
    grid-column: 1;
    grid-row: 2;
    grid-template-columns: 1fr;
    align-content: start;
    gap: 2px;
    background: var(--panel);
    border-top: none;
    border-right: 1px solid var(--line);
    overflow-y: auto;
    z-index: 40;
  }

  /* Лист инструментов — поповер у рейла, а не полоса во всю ширину. */
  #toolSheet {
    left: 8px;
    right: auto;
    bottom: calc(8px + env(safe-area-inset-bottom));
    border: 1px solid var(--line);
    border-radius: 12px;
    box-shadow: 0 10px 34px rgba(0, 0, 0, .55);
  }

  /* Панель выделения — плавающая пилюля: заголовок, действия и шаг в одну
     строку, чтобы не отнимать высоту у холста. */
  #selBar {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    bottom: calc(10px + env(safe-area-inset-bottom));
    width: min(560px, calc(100% - 32px));
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
  }
  .sel-title { margin-bottom: 0; flex: 0 1 150px; }
  .sel-actions { grid-auto-flow: column; grid-auto-columns: 44px; }
  .sel-step { margin-top: 0; flex: none; }
  .sel-step span { display: none; }
  .sel-step button { flex: none; min-width: 44px; }
}

/* ------------------------------------------------------------------------
   ПЛАНШЕТ, ПОРТРЕТ (600–1024 px)
   iPad mini 744, iPad 11 / Air 11 820, iPad Pro 11 834, Air 13 / Pro 13 1024.
   Условие orientation отсекает окна браузера на десктопе той же ширины —
   они всегда landscape. */
@media (min-width: 600px) and (max-width: 1024px) and (orientation: portrait) {
  :root {
    --header-h: 52px;
    --rail-w: calc(72px + env(safe-area-inset-left));
    --drawer-w: min(400px, 52vw);
  }

  header {
    min-height: var(--header-h);
    padding: 4px calc(10px + env(safe-area-inset-right))
             4px calc(10px + env(safe-area-inset-left));
    padding-top: calc(4px + env(safe-area-inset-top));
  }
  #planTitle { max-width: 260px; font-size: 15px; }

  #mobileBar {
    grid-auto-rows: 64px;
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom))
             calc(4px + env(safe-area-inset-left));
  }
  #mobileBar button { min-height: 60px; }
  #mobileBar button .icon { font-size: 22px; }

  /* Затемнение слабее, чем на телефоне: план под шторкой должен читаться. */
  #drawerScrim { background: rgba(0, 0, 0, .35); }

  #toolSheet { width: 340px; }
}

/* ------------------------------------------------------------------------
   ТЕЛЕФОН БОКОМ (высота ≤500 px)
   Идёт после телефонного и планшетного блоков и перекрывает их: узкое и
   низкое окно проходит по обоим условиям.
   Раньше под холст оставалось ~145 px из 402 — шапка, нижняя панель и панель
   выделения съедали всё. */
@media (max-height: 500px) {
  :root {
    --header-h: 44px;
    --bar-h: env(safe-area-inset-bottom, 0px);
    --rail-w: calc(56px + env(safe-area-inset-left));
    --drawer-w: min(320px, 46vw);
  }

  header button { min-height: 40px; }
  #planTitle { flex: 0 1 auto; max-width: 160px; font-size: 14px; }

  #mobileBar {
    grid-auto-rows: 52px;
    padding: 4px 2px calc(4px + env(safe-area-inset-bottom)) calc(2px + env(safe-area-inset-left));
  }
  #mobileBar button { min-height: 48px; font-size: 9px; gap: 2px; }
  #mobileBar button .icon { font-size: 19px; }

  #toolSheet { width: 300px; }
  .sheet-grid { grid-template-columns: repeat(2, 1fr); }
  .sheet-grid button { min-height: 56px; }

  #selBar { padding: 6px 8px; width: min(600px, calc(100% - 24px)); }
  .sel-title { flex: 0 1 140px; }
  .sel-actions button { min-height: 44px; }
  .sel-step button { min-width: 40px; min-height: 40px; }

  /* Лист снизу тут не годится — по высоте места нет. */
  dialog { max-height: 92dvh; margin: auto; border-radius: 12px; width: min(720px, 92vw); }
  .dialog-actions { position: static; margin: 14px 0 0; padding: 0; border-top: none; background: none; }
}

/* ------------------------------------------------------------------------
   ТИП УКАЗАТЕЛЯ
   Отвязано от ширины: iPad боком — это 1366 px и при этом палец. */
@media (pointer: coarse) {
  :root { --tap: 44px; }
  /* Меньше 16 px Safari на iOS зумит страницу при фокусе в поле ввода. */
  input, select, textarea { font-size: 16px; }
  .row input[type="color"] { height: 40px; }
  .list-item { min-height: 44px; }
  .list-item .x { padding: 10px 12px; }
  .palette button { font-size: 13px; }
  /* Подсказки описывают мышь, модификаторы и колесо — на касании их нет. */
  #hint, #hint3d { display: none !important; }
}

/* ------------------------------------------------------------------------
   ПЛАНШЕТ БОКОМ (≥1025 px с пальцем)
   iPad mini 1133, Air/Pro 11 — 1180/1194, 13" — 1366. Раскладка остаётся
   десктопной трёхколоночной, меняется только эргономика. */
@media (min-width: 1025px) and (pointer: coarse) {
  header { row-gap: 6px; }
  /* min-width: по высоте кнопку тянет --tap, а по ширине её задаёт контент —
     двух стрелок хватало лишь на 42 px. */
  .wide-touch-only {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--tap);
  }

  /* Точный сдвиг без клавиатуры возможен только отсюда. */
  #selBar {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    bottom: 12px;
    width: min(600px, calc(100% - 40px));
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
  }
  .sel-title { margin-bottom: 0; flex: 0 1 160px; }
  .sel-actions { grid-auto-flow: column; grid-auto-columns: 44px; }
  .sel-step { margin-top: 0; flex: none; }
  .sel-step span { display: none; }
  .sel-step button { flex: none; min-width: 44px; }
}

/* ------------------------------------------------------------------------
   Ховер только там, где есть настоящий курсор: на касании :hover залипает
   после тапа и кнопка остаётся подсвеченной. */
@media (hover: hover) and (pointer: fine) {
  button:hover { background: #3f434a; }
  button.acc:hover { background: #6b9dff; }
  .list-item:hover { background: var(--panel-2); }
  .list-item .x:hover { background: rgba(255, 122, 122, .15); }
  .dropdown button:hover { background: #3a4b6e; }
}

@media (prefers-reduced-motion: reduce) {
  .side, #toolSheet, dialog, .toast { transition: none; animation: none; }
}
