/* Шаблоны сообщений чата.
 *
 * Токены объявлены на ТРЁХ корнях (.ctplBtn, .ctplPop, .ctplEd), а не один раз
 * на странице: поповер и окно редактора живут в <body> вне классов раздела и
 * переменных страницы не получают — грабля, на которой в проекте обжигались
 * дважды (см. шапку css/pages/bybit.css и css/ui/template-editor.css).
 *
 * Цвета берутся ИЗ ТОКЕНОВ ПРОЕКТА, а не из макета: у сайта есть светлая тема,
 * и захардкоженные тёмные хексы сделали бы модуль чёрной плитой посреди
 * молочной страницы, а часть текста — нечитаемой. Литералов ровно два —
 * красный и синий: глобальных токенов для них в проекте нет, те же значения
 * стоят в bybit.css (--by-sell, --by-unread).
 *
 * Моноширинного шрифта нет намеренно: 19.08.2026 его из этого раздела убрали,
 * ровные колонки цифр даёт font-variant-numeric: tabular-nums.
 */

.ctplBtn,
.ctplPop,
.ctplEd {
  --ctpl-bg: var(--page-bg-2);
  --ctpl-bg0: var(--page-bg);
  --ctpl-bg2: color-mix(in srgb, var(--text) 4%, transparent);
  --ctpl-hover: color-mix(in srgb, var(--text) 7%, transparent);
  --ctpl-border: color-mix(in srgb, var(--text) 11%, transparent);
  --ctpl-fg: var(--text);
  --ctpl-mut: var(--muted);
  --ctpl-mut2: color-mix(in srgb, var(--text) 45%, transparent);
  --ctpl-acc: var(--primary);
  --ctpl-sell: #e5484d; /* как --by-sell: глобального красного токена нет */
  --ctpl-common: #2f81f7; /* как --by-unread: глобального синего токена нет */
  --ctpl-r: 9px;
}

/* Запас для браузеров без color-mix.
 *
 * Условие ОБЯЗАНО содержать свойство: «@supports not (color-mix(…))» без него
 * синтаксически невалидно, такое условие считается ложным, а «not ложь» —
 * истиной, и запас применялся бы ВСЕГДА. Именно так 19.08.2026 в светлой теме
 * номера строк и превью стали белыми по белому.
 *
 * И даже так запас задан для обеих тем: молчаливо «тёмный» запас — та же
 * ошибка, только отложенная. */
@supports not (color: color-mix(in srgb, white 50%, black)) {
  .ctplBtn,
  .ctplPop,
  .ctplEd {
    --ctpl-bg2: rgba(255, 255, 255, 0.04);
    --ctpl-hover: rgba(255, 255, 255, 0.07);
    --ctpl-border: rgba(255, 255, 255, 0.11);
    --ctpl-mut2: rgba(255, 255, 255, 0.45);
  }

  [data-theme="light"] .ctplBtn,
  [data-theme="light"] .ctplPop,
  [data-theme="light"] .ctplEd {
    --ctpl-bg2: rgba(0, 0, 0, 0.04);
    --ctpl-hover: rgba(0, 0, 0, 0.06);
    --ctpl-border: rgba(0, 0, 0, 0.12);
    --ctpl-mut2: rgba(15, 20, 17, 0.55);
  }
}

/* ---------- кнопка в строке композера ---------- */

/* Высоту задаёт ХОЗЯИН строки: в карточке ордера рядом стоят 30-пиксельные
   контролы, в панели под строкой списка — поле с padding 8px. Магических 30
   и 35 здесь нет намеренно: иначе один композер сломается, а второй не
   заметит. min-height:0 (специфичность 0,1,0) перебивает правило
   mobile.css button{min-height:40px} независимо от порядка файлов.

   Растяжку на всю строку убрали 21.08.2026: поле ввода растёт под текст, и
   кнопка тянулась вместе с ним — при трёх строках она превращалась в столбик
   вдвое выше кнопки отправки. Прижимаем к низу, как остальные контролы, а
   высоту берём переменной от хозяина. */
.ctplBtn {
  align-self: flex-end;
  flex: 0 0 auto;
  height: var(--ctpl-btn-h, auto);
  min-height: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  border: 1px solid var(--ctpl-border);
  border-radius: var(--ctpl-btn-r, var(--ctpl-r));
  background: var(--ctpl-bg2);
  color: var(--ctpl-mut);
  font-family: inherit;
  font-size: var(--ctpl-btn-fs, 11.5px);
  font-weight: 600;
  cursor: pointer;
  transition: background-color 120ms ease-out, border-color 120ms ease-out, color 120ms ease-out;
  /* Долгий тап открывает редактор: системное меню и выделение тут мешают. */
  user-select: none;
  -webkit-touch-callout: none;
  touch-action: manipulation;
}

/* Единственное место, где модуль знает чужие классы: подгонка под композер
   инлайн-чата. Новый хозяин — одна строка здесь. */
.by-icForm .ctplBtn {
  --ctpl-btn-fs: 13px;
  --ctpl-btn-r: 8px;
  --ctpl-btn-h: 35px;
}


.ctplBtn:hover {
  background: var(--ctpl-hover);
  border-color: color-mix(in srgb, var(--text) 18%, transparent);
  color: var(--ctpl-fg);
}

.ctplBtn.is-open {
  background: color-mix(in srgb, var(--ctpl-acc) 14%, transparent);
  border-color: color-mix(in srgb, var(--ctpl-acc) 55%, transparent);
  color: var(--ctpl-acc);
}

.ctplBtn:disabled {
  opacity: 0.4;
  cursor: default;
}

.ctplBtn__n {
  font-variant-numeric: tabular-nums;
  min-width: 1.1em;
  text-align: center;
}

/* Иконка «список»: три линии, третья короче. Рисуется прямо здесь — своего
   файла ради 14 пикселей заводить не за чем, currentColor красит её вместе с
   состояниями кнопки. */
.ctplBtn__icon {
  position: relative;
  display: inline-block;
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
}

.ctplBtn__icon::before,
.ctplBtn__icon::after {
  content: "";
  position: absolute;
  left: 0;
  height: 2px;
  border-radius: 1px;
  background: currentColor;
}

.ctplBtn__icon::before {
  top: 3px;
  width: 14px;
  box-shadow: 0 4px 0 currentColor;
}

.ctplBtn__icon::after {
  top: 11px;
  width: 9px;
}

/* ---------- поповер выбора ---------- */

.ctplPop {
  position: fixed;
  color: var(--ctpl-fg);
  font-family: var(--font-ui, inherit);
}

/* Корень получает фокус программно (tabindex -1) — он нужен клавишам 1…9. Но на
   первом же нажатии Chrome переходит в «клавиатурный» режим и рисует вокруг
   фокусированного узла системную рамку: у владельца по одному Shift
   подсвечивалось ВСЁ окно шаблонов (19.08.2026). Клавиатурное состояние видно по
   выделенной строке (.ctplRow.is-active), рамка вокруг окна лишняя. */
.ctplPop:focus,
.ctplPop:focus-visible,
.ctplPop__panel:focus-visible {
  outline: none;
}

.ctplPop[hidden] {
  display: none !important;
}

/* Текст в списке не выделяется: ⇧клик — это «вставить и отправить», а браузер по
   умолчанию тянул им выделение от начала окна (тот же доклад). Поиску выделение
   оставляем — там оно рабочее. */
.ctplPop__panel {
  user-select: none;
  display: flex;
  flex-direction: column;
  max-height: inherit;
  overflow: hidden;
  background: var(--ctpl-bg);
  border: 1px solid var(--ctpl-border);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
  animation: ctpl-pop-in 130ms cubic-bezier(0.2, 0.8, 0.2, 1);
  transform-origin: bottom right;
}

.ctplPop[data-dir="down"] .ctplPop__panel {
  transform-origin: top right;
}

@keyframes ctpl-pop-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.ctplPop__head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  border-bottom: 1px solid var(--ctpl-border);
}

.ctplPop__search {
  user-select: text;
  flex: 1;
  min-width: 0;
  height: 28px;
  padding: 0 9px;
  border: 1px solid var(--ctpl-border);
  border-radius: 6px;
  background: var(--ctpl-bg0);
  color: var(--ctpl-fg);
  font-family: inherit;
  font-size: 12px;
}

.ctplPop__search:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--ctpl-acc) 55%, transparent);
}

.ctplBadge {
  flex: 0 0 auto;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.ctplBadge.is-buy {
  color: var(--ctpl-acc);
  background: color-mix(in srgb, var(--ctpl-acc) 14%, transparent);
}

.ctplBadge.is-sell {
  color: var(--ctpl-sell);
  background: color-mix(in srgb, var(--ctpl-sell) 14%, transparent);
}

/* Список прокручивается сам; overflow-anchor выключен, иначе браузер сам
   подкручивает ленту при перерисовке — прокрутка уезжает из-под курсора. */
.ctplList {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-anchor: none;
  padding: 4px;
}

/* ---------- строка списка ---------- */

.ctplRow {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 7px 8px;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 90ms linear;
  touch-action: pan-y;
}

.ctplRow:hover,
.ctplRow.is-active {
  background: var(--ctpl-hover);
}

.ctplRow.is-dragging {
  opacity: 0.45;
  background: var(--ctpl-bg2);
}

.ctplRow.is-justMoved {
  animation: ctpl-moved 260ms ease-out;
}

@keyframes ctpl-moved {
  from {
    background: var(--ctpl-hover);
  }
  to {
    background: transparent;
  }
}

.ctplRow__slot {
  position: relative; /* якорь для ручки переноса в ::after */
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  display: grid;
  place-items: center;
  border-radius: 4px;
  background: var(--ctpl-bg2);
  color: var(--ctpl-mut2);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  /* Тянуть на сенсоре можно только за ручку: иначе жест отберёт прокрутку. */
  touch-action: none;
  cursor: grab;
}

/* Ручка переноса. Рисуется ФИГУРОЙ, а не знаком: символа ⠿ в Inter нет, и
   браузер показывал вместо ручки квадратик-заглушку (видно на докладе владельца
   19.08.2026). Приём тот же, что у .ctplEdRow__grip ниже. */
.ctplRow__slot::after {
  content: "";
  position: absolute;
  width: 8px;
  height: 11px;
  background: currentColor;
  clip-path: polygon(0 0, 40% 0, 40% 100%, 0 100%, 0 0, 60% 0, 100% 0, 100% 100%, 60% 100%, 60% 0);
  opacity: 0;
  transition: opacity 90ms linear;
}

/* У строк с десятой и дальше номера нет: пустая подложка читалась бы как
   незаполненный чекбокс. Ручка на месте — тянуть можно и их. */
.ctplRow__slot.is-blank {
  background: transparent;
}

.ctplRow:hover .ctplRow__num,
.ctplRow.is-dragging .ctplRow__num {
  opacity: 0;
}

.ctplRow:hover .ctplRow__slot::after,
.ctplRow.is-dragging .ctplRow__slot::after {
  opacity: 1;
}

.ctplRow__num {
  transition: opacity 90ms linear;
}

/* В режиме поиска номера не работают — и не должны обещать, что работают. */
.ctplPop[data-mode="search"] .ctplRow__num {
  opacity: 0.45;
}

.ctplRow__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ctplRow__head {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.ctplRow__name {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
  font-weight: 500;
}

.ctplRow__side {
  flex: 0 0 auto;
  padding: 0 4px;
  border-radius: 3px;
  font-size: 9.5px;
  font-weight: 700;
}

.ctplRow__side.is-buy {
  color: var(--ctpl-acc);
  background: color-mix(in srgb, var(--ctpl-acc) 18%, transparent);
}

.ctplRow__side.is-sell {
  color: var(--ctpl-sell);
  background: color-mix(in srgb, var(--ctpl-sell) 18%, transparent);
}

.ctplRow__dot {
  flex: 0 0 auto;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ctpl-common);
}

.ctplRow__preview {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;
  color: var(--ctpl-mut2);
}

/* Вариационный шаблон: текст берётся по аккаунту.

   Признак типа — ОДИН знак, не слово: при ширине панели 356 px на середину
   строки остаётся около 276 px, и третья метка отъедает буквы имени.
   Цвет приглушённый, а не фирменный: синий уже занят точкой «общий», и два
   цветных знака рядом читались бы как одна сущность. */
.ctplRow__side.is-var {
  color: var(--ctpl-mut2);
  background: var(--ctpl-bg2);
}

/* Строка без варианта приглушается ТОЛЬКО цветом текста.

   opacity нельзя: 0.45 уже значит «тащу строку», и два состояния слились бы, а
   заодно погасли бы ручка и крестик. Фон нельзя: та же специфичность, что у
   :hover и .is-active, — приглушённая строка перестала бы подсвечиваться и
   мышью, и стрелками, а .is-active единственное, что видно при выборе
   номером. Свой color-mix нельзя: он не покрыт блоком @supports выше и в
   браузере без color-mix не применился бы вовсе. */
.ctplRow__novar {
  color: var(--ctpl-mut2);
}

.ctplRow.is-noVar .ctplRow__name {
  color: var(--ctpl-mut);
}

/* Раскрытия полного текста по наведению НЕТ и быть не должно. Оно меняло высоту
   строки под курсором: соседи уезжали, под курсором оказывалась другая строка,
   раскрытие повторялось — список прыгал так, что в нём нельзя было ни читать, ни
   прокручивать (доклад владельца 19.08.2026). Полный текст отдаёт системная
   подсказка (title у строки): она ничего не двигает. */

.ctplRow__hide {
  flex: 0 0 auto;
  width: 19px;
  height: 19px;
  display: grid;
  place-items: center;
  min-height: 0;
  padding: 0;
  border: none;
  border-radius: 5px;
  background: transparent;
  color: var(--ctpl-mut2);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 120ms ease-out, color 120ms ease-out, background-color 120ms ease-out;
}

.ctplRow:hover .ctplRow__hide {
  opacity: 1;
}

.ctplRow__hide:hover {
  color: var(--ctpl-sell);
  background: color-mix(in srgb, var(--ctpl-sell) 16%, transparent);
}

.ctplMark {
  background: color-mix(in srgb, var(--ctpl-acc) 26%, transparent);
  color: inherit;
  border-radius: 2px;
}

/* ---------- пустые состояния и подвал ---------- */

.ctplEmpty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 18px 12px;
  color: var(--ctpl-mut2);
  font-size: 12px;
  text-align: center;
}

.ctplEmpty.is-err {
  color: var(--ctpl-sell);
}

.ctplEmpty__add {
  min-height: 0;
  padding: 5px 10px;
  border: 1px dashed var(--ctpl-border);
  border-radius: 7px;
  background: transparent;
  color: var(--ctpl-mut);
  font-family: inherit;
  font-size: 11.5px;
  cursor: pointer;
}

.ctplEmpty__add:hover {
  border-color: color-mix(in srgb, var(--ctpl-acc) 55%, transparent);
  color: var(--ctpl-acc);
}

.ctplFoot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 10px;
  border-top: 1px solid var(--ctpl-border);
  font-size: 10.5px;
  color: var(--ctpl-mut2);
}

.ctplFoot__undo,
.ctplFoot__note {
  display: flex;
  align-items: center;
  gap: 8px;
  animation: ctpl-fade 120ms ease-out;
}

@keyframes ctpl-fade {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.ctplFoot__undoBtn {
  min-height: 0;
  padding: 2px 8px;
  border: 1px solid var(--ctpl-border);
  border-radius: 5px;
  background: transparent;
  color: var(--ctpl-acc);
  font-family: inherit;
  font-size: 10.5px;
  cursor: pointer;
}

/* ---------- редактор ---------- */

.ctplEd {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--ctpl-fg);
  font-family: var(--font-ui, inherit);
}

.ctplEd__overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  animation: ctpl-fade-in 140ms ease-out;
}

@keyframes ctpl-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.ctplEd__win {
  position: relative;
  width: min(900px, 92vw);
  min-width: 0;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--ctpl-bg);
  border: 1px solid var(--ctpl-border);
  border-radius: 14px;
  box-shadow: 0 20px 56px rgba(0, 0, 0, 0.55);
  animation: ctpl-win-in 160ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

@keyframes ctpl-win-in {
  from {
    opacity: 0;
    transform: scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.ctplEd__head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--ctpl-border);
}

.ctplEd__title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.ctplEd__sub {
  color: var(--ctpl-mut2);
  font-size: 11px;
}

.ctplEd__close {
  margin-left: auto;
  min-height: 0;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--ctpl-border);
  border-radius: 7px;
  background: transparent;
  color: var(--ctpl-mut);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.ctplEd__body {
  display: flex;
  min-height: 0;
  flex: 1;
}

.ctplEd__side {
  flex: 0 0 326px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  border-right: 1px solid var(--ctpl-border);
  background: var(--ctpl-bg0);
}

.ctplEd__new {
  min-height: 0;
  padding: 7px 10px;
  border: 1px dashed var(--ctpl-border);
  border-radius: 8px;
  background: transparent;
  color: var(--ctpl-mut);
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
}

.ctplEd__new:hover {
  border-color: color-mix(in srgb, var(--ctpl-acc) 55%, transparent);
  color: var(--ctpl-acc);
}

.ctplEd__list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-anchor: none;
}

.ctplEd__groupTitle {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 10px 0 4px;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ctpl-mut2);
}

.ctplEdRow {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 7px;
  cursor: pointer;
  touch-action: pan-y;
}

.ctplEdRow:hover {
  background: var(--ctpl-hover);
}

.ctplEdRow.is-sel {
  background: var(--ctpl-bg2);
}

.ctplEdRow.is-hidden {
  opacity: 0.6;
}

.ctplEdRow.is-dragging {
  opacity: 0.45;
}

.ctplEdRow__grip {
  flex: 0 0 auto;
  width: 12px;
  height: 16px;
  background: currentColor;
  color: var(--ctpl-mut2);
  opacity: 0.55;
  clip-path: polygon(0 0, 40% 0, 40% 100%, 0 100%, 0 0, 60% 0, 100% 0, 100% 100%, 60% 100%, 60% 0);
  touch-action: none;
  cursor: grab;
}

.ctplEdRow__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.ctplEdRow__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
}

.ctplEdRow__body {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;
  color: var(--ctpl-mut2);
}

.ctplEdRow__back {
  flex: 0 0 auto;
  min-height: 0;
  padding: 2px 8px;
  border: none;
  border-radius: 5px;
  background: transparent;
  color: var(--ctpl-acc);
  font-family: inherit;
  font-size: 11px;
  cursor: pointer;
}

.ctplEdRow__back:hover {
  background: color-mix(in srgb, var(--ctpl-acc) 14%, transparent);
}

/* ---------- форма ---------- */

/* Обёртка правой колонки: перерисовывается ТОЛЬКО её содержимое, а не окно
   целиком — иначе оверлей и карточка проигрывали бы анимацию входа на каждый
   клик, и это читалось как мигание. */
.ctplEd__formBox {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
}

.ctplEd__form {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  overflow-y: auto;
  border-radius: 10px;
  transition: box-shadow 200ms ease-out;
}

.ctplEd__form.is-saved {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ctpl-acc) 60%, transparent);
}

.ctplEd__label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 6px;
  font-size: 10.5px;
  color: var(--ctpl-mut2);
}

.ctplEd__count {
  font-variant-numeric: tabular-nums;
}

.ctplEd__count.is-over {
  color: var(--ctpl-sell);
}

.ctplEd__input,
.ctplEd__area {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--ctpl-border);
  border-radius: 7px;
  background: var(--ctpl-bg0);
  color: var(--ctpl-fg);
  font-family: inherit;
  font-size: 12.5px;
}

.ctplEd__area {
  min-height: 104px;
  resize: vertical;
  line-height: 1.4;
}

.ctplEd__area.is-over {
  border-color: var(--ctpl-sell);
}

.ctplEd__hint,
.ctplEd__note,
.ctplEd__warn,
.ctplEd__deniedNote,
.ctplEd__ro,
.ctplEd__status {
  font-size: 10.5px;
  color: var(--ctpl-mut2);
}

/* Список аккаунтов у вариационного шаблона — СВОЯ прокрутка.

   .ctplEd__form прокручивается целиком, а подвал с «Сохранить» прижат к низу
   СОДЕРЖИМОГО: два десятка аккаунтов увели бы кнопку за экран, и человек видел
   бы стену полей без видимого действия. На мобильном поле ввода получает
   min-height 44px из mobile.css — высоту считать от него, не от 35.

   overflow-anchor обязателен: сторож проверяет его только у .ctplList, а
   якорение прокрутки после записи строки дёрнуло бы список из-под пальца. */
.ctplEdVar {
  display: flex;
  flex-direction: column;
  gap: 4px;
  /* Нижняя граница нужна на коротком экране: без неё блок ужимался до полутора
     строк (на 800×700 с мобильным слоем — до 88 px), и список приходилось
     листать в щель. Верхняя граница держит кнопку «Сохранить» в виду. */
  min-height: 120px;
  max-height: 260px;
  padding: 6px;
  overflow-y: auto;
  overflow-anchor: none;
  border: 1px solid var(--ctpl-border);
  border-radius: 8px;
  background: var(--ctpl-bg2);
}

.ctplEdVar__row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.ctplEdVar__acc {
  flex: 0 0 32%;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;
  color: var(--ctpl-mut);
}

/* Выключенный на портале аккаунт остаётся в списке: убрать его значило бы
   бесследно спрятать уже написанный текст. Приглушаем — и только. */
.ctplEdVar__acc.is-off {
  color: var(--ctpl-mut2);
}

.ctplEdVar__inp {
  flex: 1 1 auto;
  min-width: 0;
}

.ctplEdVar__note {
  flex: 0 0 auto;
  min-width: 54px;
  font-size: 10.5px;
  color: var(--ctpl-mut2);
}

.ctplEd__err {
  padding: 6px 8px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--ctpl-sell) 12%, transparent);
  color: var(--ctpl-sell);
  font-size: 11.5px;
}

.ctplSeg {
  display: flex;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--ctpl-border);
  border-radius: 8px;
  background: var(--ctpl-bg0);
}

.ctplSeg__btn {
  flex: 1;
  min-height: 0;
  padding: 6px 8px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--ctpl-mut);
  font-family: inherit;
  font-size: 11.5px;
  cursor: pointer;
  transition: background-color 120ms ease-out, color 120ms ease-out;
}

.ctplSeg__btn.is-on {
  background: var(--ctpl-hover);
  color: var(--ctpl-fg);
}

.ctplSeg__btn.is-off {
  color: color-mix(in srgb, var(--text) 30%, transparent);
  cursor: not-allowed;
}

.ctplEd__preview {
  padding: 4px;
  border: 1px solid var(--ctpl-border);
  border-radius: 8px;
  background: var(--ctpl-bg0);
}

.ctplRow.is-preview {
  cursor: default;
}

.ctplEd__undo {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 6px;
  background: var(--ctpl-bg2);
  font-size: 11.5px;
}

.ctplEd__link {
  min-height: 0;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--ctpl-acc);
  font-family: inherit;
  font-size: 11.5px;
  cursor: pointer;
  text-decoration: underline;
}

.ctplEd__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--ctpl-border);
}

.ctplEd__footL,
.ctplEd__footR {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.ctplEd__del,
.ctplEd__cancel {
  min-height: 0;
  padding: 6px 10px;
  border: 1px solid color-mix(in srgb, var(--ctpl-sell) 40%, transparent);
  border-radius: 7px;
  background: transparent;
  color: var(--ctpl-sell);
  font-family: inherit;
  font-size: 11.5px;
  cursor: pointer;
}

.ctplEd__cancel {
  border-color: var(--ctpl-border);
  color: var(--ctpl-mut);
}

.ctplEd__del.is-muted {
  border-color: var(--ctpl-border);
  color: color-mix(in srgb, var(--ctpl-sell) 45%, var(--ctpl-mut2));
  cursor: not-allowed;
}

.ctplEd__confirm {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
}

.ctplEd__save {
  min-height: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border: none;
  border-radius: 7px;
  background: var(--ctpl-acc);
  color: color-mix(in srgb, var(--ctpl-acc) 22%, #000);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.ctplSpin {
  width: 11px;
  height: 11px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ctpl-spin 700ms linear infinite;
}

@keyframes ctpl-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Заблокированное место отвечает встряской: клик «в никуда» читается как
   поломка, а объяснение уже написано рядом. */
.is-shake {
  animation: ctpl-shake 180ms ease-out;
}

@keyframes ctpl-shake {
  0%,
  100% {
    transform: none;
  }
  25% {
    transform: translateX(-4px);
  }
  75% {
    transform: translateX(4px);
  }
}

/* Поле композера мигает рамкой, когда в него вставили шаблон. */
.is-ctplFilled {
  box-shadow: inset 0 0 0 1px var(--primary);
  transition: box-shadow 220ms ease-out;
}

/* Курсор на всё время переноса — иначе он меняется на границах строк. */
html.is-ctplDragging,
html.is-ctplDragging * {
  cursor: grabbing !important;
  user-select: none !important;
}

/* Мобильные: список должен оставаться пальцевым, окно — во весь экран. */
@media (max-width: 740px) {
  .ctplEd__win {
    width: 100vw;
    max-height: 100vh;
    border-radius: 0;
  }

  .ctplEd__body {
    flex-direction: column;
  }

  .ctplEd__side {
    flex: 0 0 auto;
    max-height: 40vh;
    border-right: none;
    border-bottom: 1px solid var(--ctpl-border);
  }

  .ctplRow {
    min-height: 44px;
  }
}

/* Блок «меньше движения» — ПОСЛЕДНИМ и отдельным: два существующих блока
   reduced-motion в bybit.css привязаны в тестах «первым правилом», и вставка в
   их начало сломала бы проверки. */
@media (prefers-reduced-motion: reduce) {
  .ctplPop__panel,
  .ctplEd__overlay,
  .ctplEd__win,
  .ctplFoot__undo,
  .ctplFoot__note,
  .ctplRow.is-justMoved,
  .is-shake {
    animation: none;
  }

  .ctplRow__num,
  .ctplRow__slot::after,
  .ctplRow__hide,
  .ctplBtn,
  .ctplSeg__btn,
  .ctplEd__form,
  .is-ctplFilled {
    transition: none;
  }

  .ctplSpin {
    animation-duration: 0s;
  }
}
