/* ============================================================
   Bybit — торговый экран (dark launch)

   Принцип: один экран без вертикальной прокрутки. Плотность важнее воздуха,
   поэтому размеры здесь мельче, чем на остальных страницах портала.

   Цвета и шрифты берём из переменных проекта, а не из макета: страница должна
   жить в обеих темах вместе с остальным сайтом. Локальные --by-* — это
   производные от общих токенов, собранные в одном месте.
   ============================================================ */

/* JS показывает/скрывает блоки атрибутом hidden — правило должно побеждать
   любые display:flex/grid ниже.
   Карточка ордера живёт в <body> (см. ниже), поэтому её селекторы отдельно. */
.bybit-page [hidden],
.by-viewer[hidden],
.by-cpwin[hidden] { display: none !important; }

/* Токены нужны и странице, и вынесенным в body карточке ордера и окну
   истории контрагента: узел в body вне этих классов токенов НЕ получит
   (грабля ловилась дважды — см. комментарии ниже по файлу). */
.bybit-page,
.by-cpwin {
  /* поверхности: те же ступени, что и в админ-панели */
  --by-panel: color-mix(in srgb, var(--text) 4%, transparent);   /* шапки, панели */
  --by-panel2: color-mix(in srgb, var(--text) 7%, transparent);  /* поля, выделенная строка */
  --by-panel3: color-mix(in srgb, var(--text) 11%, transparent); /* активный таб */
  --by-zebra: color-mix(in srgb, var(--text) 2%, transparent);   /* чётные строки */
  --by-border2: color-mix(in srgb, var(--text) 7%, transparent); /* слабая граница в таблицах */

  --by-mut: var(--muted);
  --by-mut2: color-mix(in srgb, var(--text) 45%, transparent);   /* подписи, плейсхолдеры */

  /* Смысловые цвета.
     Акцент Hydra и «покупка» — это один и тот же зелёный (--primary): выдумывать
     четвёртый цвет ради различия не нужно, свои объявления и так узнаются по
     заливке строки и полосе слева, которых больше ни у кого нет. */
  --by-acc: var(--primary);
  --by-accdim: color-mix(in srgb, var(--primary) 14%, transparent);
  --by-buy: var(--primary);
  --by-sell: #e5484d;
  --by-amber: #e0a83c;
  /* Непрочитанные сообщения — синий; в макете ордеров это отдельный смысл,
     не «акцент» и не «покупка». */
  --by-unread: #2f81f7;
  /* Основной текст под токенами раздела: раньше --by-txt использовался, но
     нигде не объявлялся — правило молча становилось недействительным. */
  --by-txt: var(--text);

  /* Раньше здесь стоял системный моноширинный (ui-monospace/Consolas) — чужой
     для проекта шрифт, который бросался в глаза среди Inter. Теперь это наш
     же интерфейсный шрифт; ровные колонки цифр даёт не моноширинность, а
     табличные цифры (font-variant-numeric ниже). */
  --by-mono: var(--font-ui);
  --by-r: 9px; /* радиус мелких контролов: --control-r слишком крупный для плотного экрана */
}

/* Сама страница: занимает всю высоту контейнера и не скроллится целиком. */
.bybit-page {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  font-family: var(--font-ui);
  font-size: 12px;
  color: var(--text);
  /* Без своей рамки и фона-плиты: панели стоят прямо на фоне портала, как в
     новых дизайнах «Приёма» (решение владельца 14.08.2026). Стеклянная
     обёртка вокруг всего раздела дублировала панельность содержимого. */
  overflow: hidden;
}

/* Числа набираются нашим шрифтом, но с табличными цифрами: одинаковая
   ширина знака держит колонки курсов, сумм и лимитов ровными. */
.bybit-page .mono,
/* Окно-слой живёт в body, вне страницы: без него табличных цифр
   у номеров в реестре и в истории сделок не было. */
.by-cpwin .mono {
  font-family: var(--by-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.bybit-page .ta-r { text-align: right; }

/* Экран занимает всю высоту контейнера и не скроллится целиком */
.content[data-route="bybit"] {
  overflow: hidden;
  padding: 18px 20px;
}

@media (max-width: 1100px) {
  .content[data-route="bybit"] { overflow: auto; }
}

/* ============================================================
   Полоса неполадок: аккаунты команды, чьи ордера сейчас не видны
   ============================================================ */

/* Во всю ширину и сверху: пропавшие ордера одного аккаунта иначе не заметить —
   список просто короче. Пока всё в порядке, полосы нет вовсе: постоянная
   зелёная плашка перестаёт читаться через день. */
.by-trouble {
  padding: 7px 14px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--by-sell);
  background: color-mix(in srgb, var(--by-sell) 14%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--by-sell) 32%, transparent);
  animation: by-trouble-in .2s ease-out;
}

@keyframes by-trouble-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================
   Сообщение об ошибке / предупреждение
   ============================================================ */

.by-alert {
  margin: 10px 14px 0;
  padding: 8px 11px;
  font-size: 11.5px;
  color: var(--by-amber);
  background: color-mix(in srgb, var(--by-amber) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--by-amber) 32%, transparent);
  border-radius: var(--by-r);
}

.by-alert--bad {
  color: var(--by-sell);
  background: color-mix(in srgb, var(--by-sell) 12%, transparent);
  border-color: color-mix(in srgb, var(--by-sell) 32%, transparent);
}

/* ---------- масштаб: у ордеров и объявлений свой ----------
   Свой, не браузерный: zoom меняет раскладку только помеченных блоков.
   Регуляторов два (решение владельца 14.08.2026): плотность списка ордеров и
   плотность панели объявлений — разные задачи. Карточка ордера ходит с
   масштабом ОРДЕРОВ (это их продолжение), окно шаблонов — с масштабом
   ОБЪЯВЛЕНИЙ (общая переменная --by-zoom, её читает виджет). Конвертам
   fixed-окон zoom не даём — уезжали бы от центра, масштабируется содержимое. */
.by-ords {
  zoom: var(--by-zoom-orders, 1);
}

.by-ads {
  zoom: var(--by-zoom, 1);
}

/* Сама лупа — общий виджет портала: разметка в js/ui/zoom.js, вид в
   css/ui/zoom.css. Здесь остаются только ЗОНЫ этого раздела и их
   переменные — их читают чужие файлы (окно шаблонов, окно ордера). */

/* ============================================================
   Рабочая область: ордера | мои объявления
   ============================================================ */

/* Значок стороны в карточке объявления: B зелёным, S красным. Раньше жил на
   классах стакана — стакан снесён 14.08.2026, значок переехал в своё
   пространство имён. */
.by-adSide {
  font-family: var(--font-heading);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .07em;
  flex-shrink: 0;
}

.by-adSide--buy { color: var(--by-buy); }
.by-adSide--sell { color: var(--by-sell); }

.by-work {
  /* Раскладка «Приёма» (Классика New / Тетрис): слева работа, справа рельс,
     границу тянут мышью. Переменные те же по смыслу: ширину рельса держит
     --by-ads-w, умолчание задаёт CSS, перетаскивание пишет inline. */
  --by-ads-w: 320px;
  --by-split-w: 14px;
  --by-orders-min: 480px;

  flex: 1;
  display: grid;
  grid-template-columns:
    minmax(var(--by-orders-min), 1fr)
    var(--by-split-w)
    min(max(var(--by-ads-w), 280px), calc(100% - var(--by-orders-min) - var(--by-split-w)));
  gap: 0;
  min-height: 0;
  position: relative;
  padding: 10px;
}

/* Грид-дети упираются в высоту зоны, а не растут по содержимому: у grid-
   элементов min-height по умолчанию auto, и длинный список выталкивал кнопку
   «Создать» за экран, а прокрутка истории переставала работать — скроллить
   было нечему, колонка становилась высотой с контент. */
.by-work > * { min-height: 0; }

/* Свёрнуты ОБЕ стороны ордеров: держать под две полосы половину экрана
   бессмысленно — блок ужимается по содержимому, а панель объявлений забирает
   освободившееся. Так сворачивание остаётся тем, чем задумано: способом не
   отдавать место тому, чем сейчас не пользуются.

   `:where()` внутри `:has` обнуляет специфичность аргумента (иначе это
   правило перебило бы соседнее — свёрнутую панель объявлений — и при «всё
   свёрнуто» раскладка разъехалась бы). */
.by-work:has(:where(.by-ords__col.is-folded) + :where(.by-ords__col.is-folded)) {
  grid-template-columns: auto var(--by-split-w) minmax(0, 1fr);
}

/* Ордера ужаты по содержимому — сплиттеру нечего тянуть. Прячем СОХРАНЯЯ
   грид-ячейку: display:none убрал бы бокс из сетки и сдвинул авторасстановку
   (та же грабля, что с панелью объявлений 18.08.2026). */
.by-work:has(:where(.by-ords__col.is-folded) + :where(.by-ords__col.is-folded)) .by-splitter {
  visibility: hidden;
  pointer-events: none;
}

/* Свёрнутая панель объявлений: рельс — узкая полоса, сплиттер прячется —
   тянуть нечего. Идёт ПОСЛЕ правила двух свёрнутых колонок и с той же
   специфичностью: свёрнута панель — её раскладка главнее. */
.by-work:has(.by-ads.is-collapsed) {
  grid-template-columns: minmax(0, 1fr) 0 30px;
}

/* Сплиттер прячем, СОХРАНЯЯ его грид-ячейку: display:none убирал бокс из
   сетки, авторасстановка сдвигала панель во вторую колонку (ширина 0) — и
   свёрнутая полоса с кнопкой «развернуть» исчезала целиком, вернуть панель
   было нечем (поймано владельцем 18.08.2026). */
.by-work:has(.by-ads.is-collapsed) .by-splitter {
  visibility: hidden;
  pointer-events: none;
}

/* ---------- разделитель ----------
   Зона захвата шире линии; сама линия и «ручка» — как в «Приёме». */
.by-splitter {
  position: relative;
  cursor: col-resize;
  background: transparent;
  border: none;
  padding: 0;
  touch-action: none; /* иначе жест перехватит прокрутка страницы */
}

.by-splitter::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  transform: translateX(-50%);
  background: var(--border);
  transition: width 120ms ease, background-color 120ms ease;
}

.by-splitter::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 3px;
  height: 28px;
  transform: translate(-50%, -50%);
  border-radius: 2px;
  background: var(--border);
  transition: background-color 120ms ease;
}

.by-splitter:hover::before,
.by-splitter:focus-visible::before { width: 3px; background: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.by-splitter:hover::after,
.by-splitter:focus-visible::after { background: color-mix(in srgb, var(--primary) 65%, var(--border)); }

/* Пока тянут — не выделять текст и держать курсор на всём документе. */
html.is-splitting { cursor: col-resize; user-select: none; }


/* ============================================================
   ОРДЕРА — блок собран заново под макет 12.08.2026
   ============================================================
   Ничего от прежней таблицы: своё пространство классов by-ord*, своя сетка,
   свои отступы. Цвета макета переложены на токены темы (панель у нас
   переключается), шрифт — наш интерфейсный; ровные колонки цифр даёт
   font-variant-numeric, а не моноширинный шрифт.

   Блок тянется на всю доступную ширину: список — главное на экране. */

.by-ords {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* Отступы и границы больше не «таблица»: панели сами по себе, фон страницы
     между ними — как в новых дизайнах «Приёма». */
  padding: 0 10px 0 0;
}

/* ---------- шапка колонки, вкладки, фильтры ----------
   Вкладки живут ВНУТРИ колонки: у продажи и покупки они независимы, чтобы
   можно было смотреть активную продажу рядом с завершёнными покупками. */

.by-ords__colHead {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex-shrink: 0;
  padding: 8px 10px 4px;
}

.by-ords__side {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
}

.by-ords__side--sell { color: var(--by-sell); }
.by-ords__side--buy { color: var(--by-buy); }
.by-ords__count { font-size: 11px; color: var(--by-mut); font-variant-numeric: tabular-nums; }

/* Состояние связи с ПОРТАЛОМ в шапке колонки.
   Спокойное, а не тревожное: список на экране остался прежним, и красная
   плашка во всю ширину пугала сильнее, чем сообщала. Красным здесь только
   точка — она и отличает «данные замерли» от обычной подписи.
   margin-left: auto — строка прижата к кнопке сворачивания, а не болтается
   сразу за счётчиком. */
.by-ords__conn {
  display: inline-flex;
  align-items: center;
  /* Шапка стоит на baseline, а у строки первый ребёнок — точка: без своего
     выравнивания она тянула бы базовую линию за собой. */
  align-self: center;
  gap: 5px;
  margin-left: auto;
  min-width: 0;
  font-size: 11px;
  color: var(--by-mut2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.by-ords__conn[hidden] { display: none; }

/* Точка — геометрией, а не символом: «●» зависит от шрифта, и в узкой шапке
   его размер не предсказать. */
.by-ords__conn::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--by-sell);
}

/* Свёрнутая колонка: шапки нет вовсе, и о замерших данных говорит точка на
   полосе — там же, где живые числа стороны. */
.by-ords__railMark--conn {
  min-width: 8px;
  width: 8px;
  height: 8px;
  padding: 0;
  background: var(--by-sell);
}

/* На телефоне в шапке места нет: остаётся точка и время (data-short), а полный
   текст живёт в подсказке. Порог тот же, что у остального мобильного вида. */
@media (max-width: 860px), (orientation: landscape) and (max-height: 520px) {
  .by-ords__conn { font-size: 0; gap: 4px; }
  .by-ords__conn::after {
    content: attr(data-short);
    font-size: 11px;
    font-variant-numeric: tabular-nums;
  }
}


.by-ords__tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0; /* по вертикали: полосу не плющит список под ней */
  padding: 0 8px 6px;
  /* Вкладки не сжимаются и не переносятся — при нехватке места полоса
     ЛИСТАЕТСЯ вбок, а не рисуется поверх соседней колонки (владелец,
     17.08.2026: «Отменённые» продажи наезжали на «Активные» покупки).
     Полосу прокрутки прячем: листание колесом и свайпом остаётся. */
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}
.by-ords__tabs::-webkit-scrollbar { display: none; }
.by-ords__tabs .by-ordTab { flex-shrink: 0; }

.by-ordTab {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  font: inherit;
  font-size: 11px;
  color: var(--by-mut);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 7px;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.by-ordTab:hover { color: var(--text); }
.by-ordTab.is-active { color: var(--text); font-weight: 600; background: var(--by-panel3); }

/* Счётчик ордеров — сразу за названием, непрочитанные — синим справа от него. */
.by-ordTab__count { font-weight: 600; color: var(--by-mut2); font-variant-numeric: tabular-nums; }
.by-ordTab.is-active .by-ordTab__count { color: var(--by-amber); }
.by-ordTab.is-alarm { color: var(--by-sell); }
.by-ordTab.is-alarm .by-ordTab__count { color: var(--by-sell); }

.by-ordTab__unread {
  padding: 0 6px;
  font-size: 10.5px;
  font-weight: 700;
  color: #fff;
  background: var(--by-unread);
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

.by-ordTab__unread[hidden] { display: none; }

.by-ordTab.has-unread {
  background: color-mix(in srgb, var(--by-unread) 12%, transparent);
  border-color: color-mix(in srgb, var(--by-unread) 33%, transparent);
}

/* ---------- фильтры истории: одна строка, без лишнего воздуха ---------- */
.by-ordFilters {
  display: flex;
  align-items: center;
  /* Страховка от «наезда» на соседнюю колонку: чему не хватило места,
     то переносится на вторую строку, а не вылезает за край. */
  flex-wrap: wrap;
  gap: 6px;
  flex-shrink: 0;
  margin: 0 10px 8px;
  padding: 5px 6px;
  border-radius: 8px;
  background: var(--by-panel2);
}

.by-ordFilters[hidden] { display: none; }

.by-ordSeg {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  background: var(--by-panel3);
  border-radius: 7px;
  flex-shrink: 0;
}

.by-ordSeg[hidden] { display: none; }

.by-segBtn {
  padding: 3px 8px;
  font: inherit;
  font-size: 10.5px;
  color: var(--by-mut);
  background: none;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}

.by-segBtn:hover { color: var(--text); }
.by-segBtn.is-active { color: var(--text); background: var(--by-panel); }

.by-ordSelect,
.by-ordSearch {
  height: 26px;
  min-width: 0;
  padding: 0 8px;
  font: inherit;
  font-size: 11.5px;
  color: var(--text);
  background: var(--by-panel3);
  border: 1px solid transparent;
  border-radius: 7px;
}

/* Выбор аккаунта ужат до предела: подписи короткие, а место нужнее
   поиску — им пользуются заметно чаще. */
.by-ordSelect { flex: 0 1 56px; }
.by-ordSelect--reason { flex: 0 1 88px; }
.by-ordSearch { flex: 1 1 120px; }

/* «Отменённые»: фильтров больше (причина), поэтому выбор — одной строкой,
   а поиск — своей, во всю ширину. Аккаунту и причине можно чуть свободнее:
   строку они делят только с валютами. */
.by-ordFilters.is-twoRows .by-ordSearch { flex: 1 1 100%; }
.by-ordFilters.is-twoRows .by-ordSelect { flex: 1 1 64px; }
.by-ordFilters.is-twoRows .by-ordSelect--reason { flex: 1 1 96px; }
.by-ordSearch::placeholder { color: var(--by-mut2); }

/* Фильтр аккаунтов одет глобальным customSelect: кнопка наследует классы
   селекта, а обёртке нужны его флексы — иначе она перекрывает весь ряд. */
.by-ordFilters .hc-selectWrap { width: auto; flex: 0 1 96px; min-width: 0; }
.by-ordFilters.is-twoRows .hc-selectWrap { flex: 1 1 96px; }

.by-ordFilters .hc-selectBtn.by-ordSelect {
  width: 100%;
  flex: 1 1 auto;
  padding-right: 22px !important;
}

.by-ordFilters .hc-selectBtn.by-ordSelect::after {
  right: 8px;
  width: 6px;
  height: 6px;
  border-width: 1.5px;
}

/* ---------- единый выпадающий список страницы ----------
   Все селекты раздела несут data-hc-menu-class="by-menu": базовое меню
   портала рассчитано на крупные формы и рядом с плотным торговым экраном
   выглядело великаном, да и вперемешку с нативными списками у всех был свой
   размер. Здесь один строй: панель раздела, компактные пункты, зелёный акцент. */
.hc-selectMenu.by-menu {
  min-width: 130px;
  padding: 5px;
  background: var(--page-bg-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, .5);
}

.hc-selectMenu.by-menu .hc-selectOpt {
  padding: 6px 10px;
  gap: 8px;
  border-radius: 7px;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--text);
}

.hc-selectMenu.by-menu .hc-selectOpt:hover {
  background: color-mix(in srgb, var(--text) 8%, transparent);
}

/* Выбранный пункт: подкрашен акцентом, а не залит кричащим зелёным блоком. */
.hc-selectMenu.by-menu .hc-selectOpt.is-selected,
.hc-selectMenu.by-menu .hc-selectOpt.is-active {
  background: color-mix(in srgb, var(--primary) 14%, transparent);
  color: var(--text);
}

.hc-selectMenu.by-menu .hc-selectOpt.is-selected.is-active {
  background: color-mix(in srgb, var(--primary) 20%, transparent);
}

.hc-selectMenu.by-menu .hc-selectOpt__check {
  color: var(--primary);
  width: 12px;
  flex: 0 0 12px;
  font-size: 11px;
}

/* Обёртка причины отмены в ряду фильтров — те же флексы, что были у селекта. */
.by-ordFilters .hc-selectWrap:has(.by-ordSelect--reason) { flex: 0 1 110px; }
.by-ordFilters.is-twoRows .hc-selectWrap:has(.by-ordSelect--reason) { flex: 1 1 110px; }
.by-ordSelect:focus,
.by-ordSearch:focus { outline: none; border-color: color-mix(in srgb, var(--primary) 55%, var(--border)); }

/* ---------- две колонки ---------- */
/* Обе стороны свёрнуты: колонка сетки ужалась по содержимому (см. .by-work),
   и сам блок ордеров не должен растягивать её обратно. */
.by-ords:has(.by-ords__col.is-folded + .by-ords__col.is-folded) {
  flex: 0 0 auto;
  padding-right: 0;
}

.by-ords__cols {
  /* Именно flex, а не grid (было `1fr 1fr` до 23.08.2026): сворачивание
     колонки — это анимация ширины, а flex-grow/flex-basis браузеры
     интерполируют везде, тогда как переход `1fr` → `38px` в
     grid-template-columns разъезжается рывком. Две равные колонки
     `flex: 1 1 0` дают ровно ту же раскладку, что давал `1fr 1fr`. */
  --by-rail-w: 40px;
  --by-col-gap: 10px;

  flex: 1;
  min-height: 0;
  display: flex;
  gap: var(--by-col-gap);
}

.by-ords__col {
  /* Контейнер для @container-запросов ниже: ширина колонки зависит от того,
     свёрнута ли панель объявлений, а не от размера окна — медиазапросы тут
     промахивались. */
  container-type: inline-size;
  /* Точка отсчёта для полосы свёрнутой колонки (inset: 0). container-type
     позиционного контекста НЕ создаёт — без этого полоса ушла бы к предку. */
  position: relative;
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  border-radius: 12px;
  background: var(--by-panel);
  transition: flex-grow .28s cubic-bezier(.2, .8, .2, 1),
              flex-basis .28s cubic-bezier(.2, .8, .2, 1),
              background .2s ease;
}

/* ---------- свёрнутая колонка ----------
   Сотрудник работает то только на покупку, то только на продажу: пустая
   половина экрана — потерянное место. Свёрнутая сторона превращается в узкую
   полосу, вторая занимает освободившееся.

   Содержимое гасим прозрачностью и режем overflow, но из DOM НЕ убираем:
   строки остаются на месте, renderColumn обеих сторон работает как работал,
   поток ордеров не трогаем вовсе. Свёрнутая колонка — это внешний вид, а не
   отключение стороны. */
.by-ords__col.is-folded {
  flex: 0 0 var(--by-rail-w);
  overflow: hidden;
  background: var(--by-panel2);
}

.by-ords__col.is-folded > *:not(.by-ords__rail) {
  opacity: 0;
  pointer-events: none;
  /* Не только прозрачность: невидимое содержимое обязано уйти и из порядка
     обхода Tab, и из дерева доступности — иначе клавиатура проваливается в
     свёрнутую колонку, а диктор читает список, которого на экране нет.
     Гасим ПОСЛЕ затухания (delay), чтобы анимация не обрывалась. */
  visibility: hidden;
  /* Быстрее, чем едет ширина: иначе на 40 пикселях содержимое успевает
     смяться в кашу и мелькнуть поверх соседней колонки. */
  transition: opacity .12s ease, visibility 0s linear .12s;
}

.by-ords__col > *:not(.by-ords__rail) {
  transition: opacity .18s ease .1s, visibility 0s linear 0s;
}

/* Восстановление свёрнутости при заходе на раздел не должно выглядеть
   схлопыванием на глазах: класс снимается следующим кадром (bybit.page.js). */
.by-ords__cols.is-noanim .by-ords__col,
.by-ords__cols.is-noanim .by-ords__col > *,
.by-ords__cols.is-noanim .by-ords__rail { transition: none; }

/* Кнопка сворачивания в шапке колонки. Шапка выровнена по базовой линии —
   кнопке нужна своя середина. */
.by-ords__fold {
  align-self: center;
  margin-left: auto;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--by-mut2);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.by-ords__fold::before {
  content: "";
  width: 6px;
  height: 6px;
  border-left: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  /* Стрелка показывает, КУДА уедет колонка: продажа складывается влево,
     покупка — вправо. */
  transform: rotate(45deg);
  margin-left: 2px;
}

.by-ords__col[data-side="buy"] .by-ords__fold::before {
  transform: rotate(-135deg);
  margin-left: 0;
  margin-right: 2px;
}

.by-ords__fold:hover {
  color: var(--text);
  background: var(--by-panel2);
  border-color: var(--by-border2);
}

.by-ords__fold:focus-visible {
  outline: 2px solid var(--by-acc);
  outline-offset: 1px;
}

/* ---------- полоса свёрнутой колонки ----------
   Занимает всю колонку и сама является кнопкой «развернуть»: попасть по ней
   легко с любого места полосы. */
.by-ords__rail {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 8px 0 10px;
  border: 1px solid transparent;
  border-radius: 12px;
  background: var(--by-panel);
  color: var(--by-mut);
  font: inherit;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease .08s, background .15s ease, border-color .15s ease;
}

.by-ords__col.is-folded .by-ords__rail {
  opacity: 1;
  pointer-events: auto;
}

.by-ords__col.is-folded .by-ords__rail:hover {
  background: var(--by-panel2);
  border-color: var(--by-border2);
}

.by-ords__rail:focus-visible {
  outline: 2px solid var(--by-acc);
  outline-offset: -2px;
}

/* Цвет стороны — тонкой полосой по внутреннему краю: даже боковым зрением
   видно, продажа это свернулась или покупка. Приглушена намеренно: полоса
   опознаёт колонку, а кричать на весь экран должны метки новостей. */
.by-ords__rail::after {
  content: "";
  position: absolute;
  top: 8px;
  bottom: 8px;
  width: 2px;
  border-radius: 2px;
  background: var(--by-railColor);
  opacity: .3;
}

.by-ords__col.is-folded .by-ords__rail:hover::after { opacity: .5; }

.by-ords__col[data-side="sell"] .by-ords__rail { --by-railColor: var(--by-sell); }
.by-ords__col[data-side="buy"] .by-ords__rail { --by-railColor: var(--by-buy); }
.by-ords__col[data-side="sell"] .by-ords__rail::after { right: 3px; }
.by-ords__col[data-side="buy"] .by-ords__rail::after { left: 3px; }

.by-ords__railChev {
  flex-shrink: 0;
  width: 7px;
  height: 7px;
  border-top: 1.6px solid currentColor;
  border-right: 1.6px solid currentColor;
  /* Разворачивается наружу — стрелка смотрит туда же. */
  transform: rotate(45deg);
  opacity: .7;
}

.by-ords__col[data-side="buy"] .by-ords__railChev { transform: rotate(-135deg); }

.by-ords__railCount {
  flex-shrink: 0;
  min-width: 22px;
  padding: 2px 4px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  color: var(--text);
  background: var(--by-panel3);
  border-radius: 7px;
  font-variant-numeric: tabular-nums;
}

/* Ноль активных — число не должно кричать: сворачивают ровно ту сторону, где
   работы сейчас нет. */
.by-ords__rail[data-empty="1"] .by-ords__railCount {
  color: var(--by-mut2);
  background: transparent;
}

.by-ords__railName {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--font-heading);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .12em;
  color: var(--by-railColor);
  /* Название уступает место меткам, а не наоборот: на короткой полосе
     обрежется слово, но «+2 новых» останется целым. */
  flex: 0 1 auto;
  min-height: 0;
  overflow: hidden;
}

/* Метки идут СРАЗУ за названием, а не прижаты к низу полосы: на высоком
   экране низ — это периферия зрения, и «+2 новых» там читается последним,
   хотя ради него полоса и сделана. */
.by-ords__railMarks {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
}

.by-ords__railMark {
  min-width: 20px;
  padding: 1px 3px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1.4;
  text-align: center;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

.by-ords__railMark[hidden] { display: none; }

/* Новые ордера, пришедшие уже при свёрнутой колонке, — то самое, ради чего
   полоса вообще нужна: не заметить их нельзя. */
.by-ords__railMark--new {
  color: #fff;
  background: var(--by-amber);
  animation: by-railPulse 1.8s ease-in-out infinite;
}

.by-ords__railMark--unread {
  color: #fff;
  background: var(--by-unread);
}

.by-ords__railMark--appeal {
  min-width: 0;
  padding: 2px 3px;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  letter-spacing: .06em;
  color: #fff;
  background: var(--by-sell);
  border-radius: 6px;
}

@keyframes by-railPulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--by-amber) 55%, transparent); }
  50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--by-amber) 0%, transparent); }
}

/* Свёрнутая колонка с новостями подсвечивает и саму полосу — заметно с
   расстояния, без чтения цифр. */
.by-ords__col.is-folded .by-ords__rail:has(.by-ords__railMark--new:not([hidden])) {
  border-color: color-mix(in srgb, var(--by-amber) 45%, transparent);
  background: color-mix(in srgb, var(--by-amber) 8%, var(--by-panel));
}

.by-ords__col.is-folded .by-ords__rail:has(.by-ords__railMark--appeal:not([hidden])) {
  border-color: color-mix(in srgb, var(--by-sell) 45%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .by-ords__col,
  .by-ords__col > *:not(.by-ords__rail),
  .by-ords__rail { transition: none; }
  .by-ords__railMark--new { animation: none; }
}

.by-ords__list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 0 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  scrollbar-width: thin;
  scrollbar-color: var(--by-mut2) transparent;
}

.by-ords__list::-webkit-scrollbar { width: 8px; }
.by-ords__list::-webkit-scrollbar-track { background: transparent; }
.by-ords__list::-webkit-scrollbar-thumb { background: var(--by-border2); border-radius: 4px; }
.by-ords__list::-webkit-scrollbar-thumb:hover { background: var(--by-mut2); }

/* Ожидание данных: три пульсирующие точки вместо серых прямоугольников.
   Прямоугольники обещали строки, которых может и не быть, и читались как
   поломка вёрстки. */
.by-ordLoad {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 34px 16px;
  color: var(--by-mut2);
  font-size: 11.5px;
}

.by-ordLoad__dots { display: inline-flex; gap: 6px; }
.by-ordLoad__text { letter-spacing: .01em; animation: by-ordLoadText 1.8s ease-in-out infinite; }

.by-ordLoad__dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--by-mut);
  animation: by-ordLoad .9s ease-in-out infinite;
}

.by-ordLoad__dots i:nth-child(2) { animation-delay: .15s; }
.by-ordLoad__dots i:nth-child(3) { animation-delay: .3s; }

/* Подскок с масштабом: движение видно и боковым зрением — раньше точки
   мерцали так робко, что индикатор принимали за статичную надпись. */
@keyframes by-ordLoad {
  0%, 70%, 100% { opacity: .2; transform: translateY(0) scale(.8); }
  35%           { opacity: 1;  transform: translateY(-5px) scale(1.15); }
}

@keyframes by-ordLoadText {
  0%, 100% { opacity: .55; }
  50%      { opacity: 1; }
}

/* prefers-reduced-motion индикатор НЕ выключает — намеренно. Это не
   украшение, а сообщение «идёт загрузка»: замороженные точки читались как
   зависание (и у Windows с выключенными «эффектами анимации» ровно так и
   вышло). Прыжок мелкий и локальный, укачать не способен. */

/* Пусто — тоже часть дизайна: не голая строчка, а спокойная плашка. */
.by-ordEmpty {
  margin: 6px 4px;
  padding: 22px 16px;
  border-radius: 10px;
  border: 1px dashed var(--border);
  text-align: center;
  color: var(--by-mut2);
  font-size: 11.5px;
}

.by-ordEmpty b {
  display: block;
  margin-bottom: 3px;
  font-size: 12px;
  font-weight: 600;
  color: var(--by-mut);
}

/* ---------- строка ордера ---------- */
.by-ordCard {
  border-radius: 8px;
  border: 1px solid transparent;
  background: transparent;
  transition: background .15s ease, border-color .15s ease;
}

.by-ordCard:hover { background: var(--by-panel2); }

/* ---------- телефон из чата в строке списка (владелец, 17.08.2026) ----------
   Строка с распознанным номером становится двухэтажной: сумма и мета сверху,
   телефон снизу, а статус слева и кнопки справа растягиваются на обе строки и
   центрируются — стоят «между» строками текста. */
/* Единый блок «сумма + мета». Центр со смещением: слева 30% свободного места,
   справа 70% (владелец, 17.08.2026) — чистый центр казался сдвинутым вправо
   из-за широкой колонки статуса слева. Доли держат псевдо-распорки: они
   сжимаемы (basis 0), на узкой колонке честно исчезают первыми. */
.by-ordMid {
  display: flex;
  align-items: center;
  min-width: 0;
}
.by-ordMid::before,
.by-ordMid::after { content: ""; display: block; }
.by-ordMid::before { flex: 30 1 0px; }
.by-ordMid::after { flex: 70 1 0px; }

/* Колонка «информация + номер»: распорки двигают её ЦЕЛИКОМ, поэтому номер не
   может уехать относительно информации ни на каком сужении — они одна ширина.
   Номер центрируется под информацией самой колонкой. */
.by-ordMidCol {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
}
.by-ordLine1 {
  display: flex;
  align-items: baseline;
  /* Отступ дышит с шириной КОЛОНКИ (cqw — контейнер .by-ords__col).
     Кривая по точкам владельца (17.08.2026, третья правка): до 450px — прежний
     минимум 8px, при 600px — ровно 24px, потолок 34px около 695px. Прямая
     через (450,8) и (600,24): 10.67cqw со сдвигом −40px. */
  gap: clamp(8px, calc(10.67cqw - 40px), 34px);
  /* Ширина колонки меняется скачком (панель объявлений свернули/раскрыли) —
     отступ перетекает, а не прыгает с 34 на 24 (владелец, 17.08.2026). */
  transition: gap 0.25s ease;
  min-width: 0;
  max-width: 100%;
}

/* Номер живёт внутри колонки .by-ordMidCol — своих распорок и своей ячейки
   сетки у него больше нет (они и позволяли ему уезжать вправо при сужении).
   Строка осталась одноэтажной сеткой: статус и кнопки центрирует базовое
   align-items: center самой строки, двухэтажная машинерия span 2 не нужна. */

/* Плавное раскрытие блока неизвестной высоты: grid-строка 0fr → 1fr.
   Класс is-open вешает дифф списка — с задержкой кадра, когда номер только
   распознался, и синхронно, когда строка просто перерисовалась. */
.by-ordPhoneWrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.28s ease;
}
.by-ordPhoneWrap.is-open { grid-template-rows: 1fr; }
.by-ordPhoneCell { min-height: 0; overflow: hidden; }

/* Простой текст, не кнопка: клик проходит сквозь и открывает ордер
   (решение владельца 17.08.2026 — копирование здесь убрано). */
.by-ordPhone {
  font-size: 12.5px;
  color: var(--by-txt);
  font-variant-numeric: tabular-nums;
  opacity: 0.9;
  /* Номер не переносится: дефисы в +7(916)825-17-52 — точки разрыва строки.
     Совсем не влез — честное «…», а не обрубок «+7(977)722-». */
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* В крупной карточке действия номер — средней строкой по центру. */
.by-ordAct__line--phone { justify-content: center; }
.by-ordAct__line--phone .by-ordPhone { font-size: 13.5px; font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .by-ordPhoneWrap { transition: none; }
  .by-ordLine1,
  .by-ordMeta { transition: none; }
}

.by-ordRow {
  display: grid;
  /* Три колонки: статус | единый блок информации | кнопки. Сумма и мета живут
     внутри общего блока (.by-ordMid) и центрируются им — решение владельца
     17.08.2026: у всех строчных ордеров одинаковое центрирование. Прежняя
     раскладка с отдельной колонкой суммы держала суммы по одной вертикали,
     но блок в целом выглядел прижатым влево. */
  grid-template-columns: 112px minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  padding: 6px 9px;
  cursor: pointer;
}

.by-ordStatus {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  min-width: 0;
  max-width: 100%;
  /* Не растягиваться на всю ячейку: плашка запроса отмены должна быть по
     ширине текста, а не во всю колонку статуса. */
  justify-self: start;
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.by-ordStatus__text {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Короткая подпись включается в узкой колонке (см. @container ниже). */
.by-ordStatus__short { display: none; }

/* Плашка запроса отмены: ответ требуется от нас — потому и плашка. */
.by-ordStatus--req {
  padding: 2px 7px;
  border-radius: 5px;
  background: var(--by-amber);
  color: #4a1008;
  font-weight: 700;
}

/* Отсчёт внутри плашки красился «своим» янтарным по янтарному фону и
   становился невидимым — на скриншоте от него оставалось только «мин». */
.by-ordStatus--req .by-ordLeft,
.by-ordStatus--req .by-ordLeft.is-urgent { color: inherit; }

.by-ordLeft { font-variant-numeric: tabular-nums; }
.by-ordLeft--warn { color: inherit; }

.by-ordSum {
  font-size: 12.5px;
  font-weight: 600;
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.by-ordMeta {
  display: flex;
  align-items: baseline;
  /* Та же кривая: до 450px — минимум 5px, при 600px — ровно 14px, потолок
     24px около 767px. Прямая через (450,5) и (600,14): 6cqw − 22px. */
  gap: clamp(5px, calc(6cqw - 22px), 24px);
  transition: gap 0.25s ease;
  min-width: 0;
  font-size: 11px;
  color: var(--by-mut2);
  white-space: nowrap;
}

/* Точки-разделители, как в макете: «88,00 · K.Petrov · C.Moltisanti».
   Точка живёт у последующего элемента: спрятался элемент — ушла и она. */
.by-ordMeta > span + span::before {
  content: "· ";
  color: var(--by-mut2);
  font-weight: 400;
}

/* Ник — то, по чему ордер узнают; ему и отдаём остаток места. */
.by-ordMeta__cp {
  color: var(--text);
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.by-ordMeta__rate,
.by-ordMeta__acc { flex: 0 0 auto; }
.by-ordMeta__rate { font-variant-numeric: tabular-nums; }
.by-ordMeta__acc { color: var(--by-mut); }
.by-ordActs { display: inline-flex; align-items: center; gap: 6px; }

/* ---------- кнопки строки ---------- */
.by-ordChatBtn {
  min-width: 36px;
  padding: 2px 7px;
  font: inherit;
  font-size: 10.5px;
  color: var(--by-mut);
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}

.by-ordChatBtn:hover { color: var(--text); border-color: var(--by-mut2); }

.by-ordChatBtn.is-unread {
  color: #fff;
  font-weight: 700;
  background: var(--by-unread);
  border-color: var(--by-unread);
}

.by-ordChatBtn.is-open { color: var(--text); border-color: var(--by-mut2); }

.by-ordDo {
  /* Ширина одна на ВСЕ состояния: «точно?» шире галочки, и без фиксации
     соседние кнопки уезжали бы на каждом шаге подтверждения. */
  min-width: 52px;
  height: 22px;
  position: relative;
  display: inline-grid;
  place-items: center;
  padding: 0 8px;
  font: inherit;
  font-size: 11px;
  font-weight: 700;
  color: #08130d;
  background: var(--by-acc);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: background .15s ease, transform .12s ease;
}

.by-ordDo:hover { background: color-mix(in srgb, var(--by-acc) 80%, #fff); transform: scale(1.05); }
.by-ordDo:disabled { opacity: .6; cursor: default; transform: none; }
.by-ordDo.is-asking { background: var(--by-amber); color: #4a1008; font-size: 11px; }

/* Запрос в полёте: галочка уступает место волчку — тот же приём, что у цены
   объявления. Отпуск монеты идёт СЕКУНДЫ (backend перечитывает состояние у
   биржи и только потом отпускает), и без этого тишина читалась как «не
   нажалось» (владелец, 25.08.2026).

   Глиф — своим span'ом: меняется только он, коробка стоит на месте. */
.by-ordDo__glyph { display: block; line-height: 1; transition: opacity .12s ease; }

.by-ordDo.is-busy { cursor: default; transform: none; }
.by-ordDo.is-busy .by-ordDo__glyph { opacity: 0; }
.by-ordDo.is-busy::after {
  content: "";
  position: absolute;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, #08130d 30%, transparent);
  border-top-color: #08130d;
  animation: by-ordDo-spin .7s linear infinite;
}

/* Успех: галочка возвращается и «лопается» — раздувается и тает. */
.by-ordDo.is-done .by-ordDo__glyph { animation: by-ok-pop .45s ease-out forwards; }

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

/* Денежное действие в карточке ордера в полёте. Занимает место кнопки, чтобы
   блок действий не менял высоту: карточка не имеет права дёргаться в момент,
   когда оператор смотрит на результат необратимого нажатия. */


@media (prefers-reduced-motion: reduce) {
  .by-ordDo.is-busy::after { animation-duration: 1.4s; }
  .by-ordDo.is-done .by-ordDo__glyph { animation: none; }
}

/* ---------- подсветки ----------
   Полоса слева и мягкая заливка: спор красным, запрос отмены жёлтым,
   непрочитанные синим. Спор серьёзнее — при совпадении цвет за ним. */
.by-ordCard.is-unread {
  background: color-mix(in srgb, var(--by-unread) 7%, transparent);
  box-shadow: inset 2px 0 0 var(--by-unread);
}

.by-ordCard.is-cancelreq {
  background: color-mix(in srgb, var(--by-amber) 8%, transparent);
  box-shadow: inset 2px 0 0 var(--by-amber);
}

.by-ordCard.is-appeal {
  background: color-mix(in srgb, var(--by-sell) 8%, transparent);
  box-shadow: inset 2px 0 0 var(--by-sell);
}

/* ---------- ордер, ждущий действия ----------
   Карточка в два этажа, как в макете: плашка статуса + курс + крупная
   сумма, ниже ник, аккаунт и кнопки. В общую сетку строк она не встаёт —
   и не должна: это другой вид, места ему хватает всегда. */
.by-ordCard.is-action { border-radius: 12px; margin: 3px 0; }

.by-ordCard.is-action .by-ordRow {
  display: flex;
  flex-direction: column;
  /* Базовая строка центрирует содержимое (align-items: center) — во
     flex-колонке это сжимает этажи по содержимому и стаскивает их в
     середину: сумме некуда уезжать вправо. Этажи должны быть во всю ширину. */
  align-items: stretch;
  gap: 8px;
  padding: 10px 11px;
}

.by-ordAct__line { display: flex; align-items: center; gap: 8px; min-width: 0; }

.by-ordPill {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding: 3px 8px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.by-ordPill--release { background: color-mix(in srgb, var(--by-acc) 15%, transparent); color: var(--by-acc); }
.by-ordPill--pay { background: color-mix(in srgb, var(--by-amber) 15%, transparent); color: var(--by-amber); }
.by-ordPill--req { background: var(--by-amber); color: #4a1008; font-weight: 700; }
.by-ordPill--req .by-ordLeft,
.by-ordPill--req .by-ordLeft.is-urgent { color: inherit; }

/* Точка перед таймером, как в макете («Ждёт отпуска · 14:32») — у самого
   таймера: истёк и исчез — вместе с точкой. */
.by-ordPill .by-ordLeft::before { content: "· "; }

.by-ordAct__rate {
  flex: 0 1 auto;
  font-size: 10.5px;
  color: var(--by-mut2);
  white-space: nowrap;
  overflow: hidden;
}

.by-ordAct__rate b { font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }

.by-ordAct__sum {
  margin-left: auto;
  font-size: 17px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.by-ordAct__cp {
  font-size: 11.5px;
  color: var(--text);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.by-ordAct__acc { font-size: 10.5px; color: var(--by-mut); white-space: nowrap; }

.by-ordAct__line .by-ordActs { margin-left: auto; }

.by-ordCard.is-action--release {
  background: color-mix(in srgb, var(--by-acc) 9%, transparent);
  border-color: color-mix(in srgb, var(--by-acc) 40%, transparent);
}

.by-ordCard.is-action--release:hover { border-color: var(--by-acc); }

.by-ordCard.is-action--pay {
  background: color-mix(in srgb, var(--by-amber) 9%, transparent);
  border-color: color-mix(in srgb, var(--by-amber) 40%, transparent);
}

.by-ordCard.is-action--pay:hover { border-color: var(--by-amber); }

/* Раскрытый чат — общая рамка со строкой. */
.by-ordCard.is-chatOpen {
  border-color: color-mix(in srgb, var(--by-unread) 45%, transparent);
  background: var(--by-panel2);
}

.by-ordCard.is-entering { animation: by-rowIn .22s ease-out; }
.by-ordCard.is-leaving { animation: by-rowOut .18s ease-in forwards; pointer-events: none; }

/* ---------- история: дни и компактные строки ---------- */
/* Разделитель дня: заметная полоса во всю ширину колонки — по ней глаз
   цепляется за границу суток, не вчитываясь во время каждой строки. */
.by-ordDay {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 5px 0 3px;
  padding: 3px 8px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--text) 12%, transparent);
  font-size: 11px;
  font-weight: 600;
}

.by-ordDay:first-child { margin-top: 0; }

.by-ordDay__sum {
  font-weight: 400;
  font-size: 10px;
  color: var(--by-mut2);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* Строка истории: та же карточка, но плотнее — там смотрят списком. */
.by-ordCard--hist:hover { background: var(--by-panel2); }

.by-ordRow--hist {
  /* Фиксированные ширины по той же причине, что у активных: суммы и курсы
     всех строк должны стоять ровными столбиками. */
  grid-template-columns: 34px 80px 44px minmax(0, 1fr) auto auto;
  gap: 7px;
  padding: 4px 9px;
}

.by-histTime { font-size: 10px; color: var(--by-mut2); font-variant-numeric: tabular-nums; }

/* Время завершения, которого мы не знаем точно. Смысл несёт ЗНАК в самой
   строке («≈» — по наблюдению портала, «~» — показано время создания), а
   не только приглушённый цвет: цвет не имеет права быть единственным
   носителем смысла. Подробности — в подсказке при наведении. */
.by-histTime.is-approx,
.by-histTime.is-unknown { opacity: .7; }

.by-histSum {
  font-size: 12px;
  font-weight: 600;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.by-histSum.is-cancelled {
  text-decoration: line-through;
  text-decoration-color: var(--by-mut2);
  color: var(--by-mut);
}

.by-histRate {
  font-size: 10.5px;
  text-align: right;
  color: var(--by-mut2);
  font-variant-numeric: tabular-nums;
}

.by-histCp {
  font-size: 11px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.by-histAcc {
  font-size: 10px;
  color: var(--by-mut2);
  background: var(--by-panel2);
  border-radius: 5px;
  padding: 2px 8px;
  white-space: nowrap;
}

.by-histAcc:empty { display: none; }

/* Причина отмены — тонкая вторая строчка ордера. В сетке строки она
   обрезалась многоточием, а причину нужно видеть целиком. Отступ слева —
   под колонку времени, чтобы текст начинался вровень с суммой. */
.by-histReason {
  margin-top: -3px;
  padding: 0 10px 4px 50px;
  font-size: 10px;
  line-height: 1.25;
  color: var(--by-mut);
}

/* Отмена, ударившая по НАШЕМУ проценту выполнения, — единственный случай с
   пометкой ⚠: мы отменили с причиной «ошибка продавца», а он её отклонил. */
.by-histReason.is-warn { color: var(--by-amber); }

.by-histReason.is-bad { color: var(--by-sell); }

.by-histNote { padding: 10px 12px 4px; font-size: 10.5px; color: var(--by-mut2); }

/* ============================================================
   Мои объявления
   ============================================================ */

.by-ads {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.by-ads__head {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 28px;
  padding: 0 13px;
  flex-shrink: 0;
  font-family: var(--font-heading);
  font-size: 11.5px;
  font-weight: 600;
  background: var(--by-panel);
  border-bottom: 1px solid var(--border);
}

.by-ads__count { font-family: var(--font-ui); color: var(--by-mut); font-weight: 400; }
.by-ads__list { flex: 1; min-height: 0; }

/* ============================================================
   Пустые состояния и скелетоны
   ============================================================ */

.by-empty {
  padding: 15px 13px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--by-mut2);
}

.by-empty b { display: block; margin-bottom: 3px; color: var(--by-mut); font-weight: 600; }

.by-skeleton {
  height: 9px;
  margin: 3px 8px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--by-panel), var(--by-panel3), var(--by-panel));
  background-size: 200% 100%;
  animation: by-shimmer 1.2s linear infinite;
}

.by-skeleton--order { height: 23px; margin: 0; border-radius: 0; border-bottom: 1px solid var(--by-border2); }

@keyframes by-shimmer {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .by-skeleton { animation: none; }
}

/* ============================================================
   Карточка ордера
   ============================================================ */


@keyframes by-fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* «Создать реквизит - Приём» — кнопка в шапке карточки ордера.

   Стоит ПЕРЕД крестиком в разметке, а он прижат `margin-left: auto` — поэтому
   кнопка оказывается слева от него и прижимается к нему же, а не улетает к
   сумме. Своего margin ей не нужно.

   Ширина по содержимому и высота 26px — как у крестика: шапка складывается в
   строку из разнородных элементов, и всё, что выше, ломает её ритм. */
.by-quickAdd {
  margin-left: auto;
  height: 26px;
  padding: 0 12px;
  font: 600 11.5px var(--font-ui);
  white-space: nowrap;
  color: var(--primary);
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  border: 0;
  border-radius: var(--by-r);
  cursor: pointer;
  transition: var(--transition);
}

.by-quickAdd:hover { background: color-mix(in srgb, var(--primary) 20%, transparent); }
.by-quickAdd:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--input-focus); }
.by-quickAdd[disabled] { opacity: .55; pointer-events: none; }

/* Реквизит уже заведён. С 31.08.2026 это КНОПКА: нажатием раскрывается полка
   сделок площадок по этому ордеру, поэтому ни `cursor: default`, ни вид
   «нажимать нечего» здесь больше не годятся. Вид кнопки в самом окне ордера
   задаётся своими токенами (`.bw-win .by-quickAdd--done` в order-window.css) —
   это правило остаётся базой для любого другого хозяина. */
.by-quickAdd--done {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--by-mut);
  background: none;
  cursor: pointer;
}

/* Крестик окон истории контрагента и реестра скамеров (.by-cpwin); от снесённой
   карточки ордера остался только он. */
.by-modal__close {
  margin-left: auto;
  width: 26px;
  height: 26px;
  font-size: 18px;
  line-height: 1;
  color: var(--by-mut);
  background: transparent;
  border: 0;
  border-radius: var(--by-r);
  cursor: pointer;
  transition: var(--transition);
}

.by-modal__close:hover { color: var(--text); background: var(--by-panel2); }

.by-kv {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 3px 0;
  font-size: 11.5px;
}

.by-kv__label { color: var(--by-mut2); flex: 0 0 auto; }

.by-kv__value {
  text-align: right;
  min-width: 0;
  overflow-wrap: anywhere;
}

.by-soon {
  padding: 8px 10px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--by-mut2);
  background: var(--by-panel);
  border: 1px dashed var(--border);
  border-radius: var(--by-r);
}

/* ---------- ожидание данных: живой скелет ----------
   Место под строки занято заранее — когда данные приедут, соседние блоки не
   сдвинутся (иначе это и читается как «дёрнулось»).

   Параметры взяты из набора движения (Loading/Skeleton): проход подсветки по
   background-position, 1.4 с, sine.inOut — воспринимается как «грузится»
   отчётливее, чем пульсация прозрачностью. Волна ОДНА на группу: строки
   стартуют вместе, а разница фаз задана отрицательной задержкой, поэтому
   подсветка идёт по блоку единым гребнем, а не рябью из независимых огоньков. */
.by-soon--wait { display: grid; gap: 6px; }

.by-soon__text { opacity: .85; }

.by-skelRow {
  height: 9px;
  border-radius: 4px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--text) 6%, transparent) 20%,
    color-mix(in srgb, var(--text) 15%, transparent) 38%,
    color-mix(in srgb, var(--text) 6%, transparent) 62%
  );
  background-size: 300% 100%;
  animation: bySkelSweep 1.4s ease-in-out infinite;
}

/* Разная длина строк — блок выглядит как текст, а не как полосатый забор. */
.by-skelRow:nth-child(2n) { width: 84%; }
.by-skelRow:nth-child(3n) { width: 66%; }

/* Фазы одной волны: гребень проходит сверху вниз. */
.by-skelRow:nth-child(2) { animation-delay: -.12s; }
.by-skelRow:nth-child(3) { animation-delay: -.24s; }
.by-skelRow:nth-child(4) { animation-delay: -.36s; }
.by-skelRow:nth-child(5) { animation-delay: -.48s; }
.by-skelRow:nth-child(6) { animation-delay: -.6s; }

@keyframes bySkelSweep {
  from { background-position: 100% 0; }
  to   { background-position: -100% 0; }
}

/* ---------- данные доехали ----------
   Решение владельца 19.08.2026 после смены за маком: НИКАКИХ цветных
   подсветок и никаких скачков строк. Зелёные вспышки на каждом обновлении и
   выделение новых строк за долгую смену изматывают — рабочий экран не должен
   привлекать внимание к себе, пока не случилось чего-то важного.

   Осталось только то, без чего непонятно, что данные пришли: содержимое
   колонки, где был скелет, проявляется одним мягким переходом. Ступеней,
   сдвигов и цвета нет — движение не отвлекает даже краем глаза. */


@keyframes byColArrive {
  from { opacity: .55; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .by-skelRow { animation: none; }
  
}

/* ---------- реквизиты, названные в переписке ---------- */

/* «Уехавшее» сообщение в ленте — обычный пузырь собеседника (30.08.2026).
   Отдельный блок над лентой («Контрагент писал не в этот чат») здесь СНЯТ:
   правило показа одно на обоих зрителей, и в окне ордера такие сообщения
   идут лентой с 25.08.2026. Своих правил пузырю не нужно — он и должен
   выглядеть обычным входящим; отличает его только подсказка при наведении. */

/* Подсветка названий банков по клику на «???»: рамка сообщения + сами слова. */
.by-msg.is-bankFlash { outline: 1px solid color-mix(in srgb, var(--by-amber) 55%, transparent); }


/*
 * Ожидание — кольцо, нарисованное рамкой, а не символ: «◌» в этом кегле
 * выглядит бледной точкой, и его симметрия читается как дрожание. Габариты те
 * же, что у значка с глифом, — строка не дёргается при смене состояния.
 */
.by-icReq__mark.is-spin {
  box-sizing: border-box;
  border: 1.5px solid var(--by-mut2);
  border-top-color: transparent;
  border-radius: 50%;
  animation: byCheckSpin 0.9s linear infinite;
}

@keyframes byCheckSpin {
  to { transform: rotate(360deg); }
}

/*
 * Сноска под сообщением: итог проверки номера, названного в нём же. Отдельной
 * строкой ВНУТРИ пузыря — иначе появление подписи сдвигало бы ленту.
 */
.by-msg__note {
  display: block;
  margin-top: 3px;
  font-size: 10px;
  line-height: 1.3;
  opacity: 0.85;
}

.by-msg__note--ok { color: var(--by-buy); }
.by-msg__note--bad { color: var(--by-sell); }
.by-msg__note--wait { color: var(--by-mut2); }

/*
 * Пузырь с файлом кладёт подпись под содержимым, а не в строку: у него
 * горизонтальная раскладка (значок, имя, кнопки, время), и подпись, попавшая
 * в тот же ряд, растянула бы его по ширине на всю ленту.
 */
.by-msg--withNote { flex-wrap: wrap; }
.by-msg--withNote .by-msg__note { flex: 1 0 100%; }

/*
 * Значок проверки у фишки реквизита в ленте под строкой списка. Габариты
 * жёсткие по той же причине, что и в карточке: фишки стоят в строке, которая
 * не должна менять высоту от появления значка.
 */
.by-icReq__mark {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-left: 3px;
  font-size: 9px;
  line-height: 12px;
  text-align: center;
  vertical-align: middle;
}


/* Подсветка сообщения, к которому перешли из списка реквизитов.
   Свойство animation здесь перекрывается более поздним правилом by-msg-flash —
   оставлен только радиус, чтобы две анимации не спорили за одно место. */
.by-msg.is-flash {
  border-radius: var(--by-r);
}

@keyframes by-flash {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  50% { box-shadow: 0 0 0 2px var(--by-acc); }
}

/* Сработавший предохранитель автоматики — над списком объявлений.
   Пульсирует: тревога должна быть заметна боковым зрением, а не только цветом. */
.by-guard {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 0 8px;
  padding: 8px 10px;
  border-radius: var(--by-r);
  color: var(--by-sell);
  background: color-mix(in srgb, var(--by-sell) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--by-sell) 45%, transparent);
  animation: by-guard-pulse 1.6s ease-in-out infinite;
}

.by-guard__text {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 10.5px;
  line-height: 1.4;
}

.by-guard__text b { display: block; font-size: 11.5px; margin-bottom: 2px; }
.by-guard .by-btn { flex: 0 0 auto; }

@keyframes by-guard-pulse {
  0%, 100% { border-color: color-mix(in srgb, var(--by-sell) 45%, transparent); }
  50%      { border-color: color-mix(in srgb, var(--by-sell) 90%, transparent); }
}

@media (prefers-reduced-motion: reduce) {
  .by-guard { animation: none; }
}

/* Разбор записей реестра скамеров — содержимое слоя (by-cpwin).
   Кнопка в строке проверки: счётчик записей и стрелка. */


.by-mark {
  padding: 8px 10px;
  border-radius: var(--by-r);
  background: var(--by-panel);
  border: 1px solid var(--border);
  border-left: 3px solid color-mix(in srgb, var(--by-sell) 65%, transparent);
}

/* Оспоренная гаснет, но остаётся: удалить запись нельзя, и прятать её нечестно
   — оператор должен видеть, что кто-то уже разбирался. */
.by-mark.is-disputed {
  opacity: .7;
  border-left-color: color-mix(in srgb, var(--by-mut) 65%, transparent);
}


.by-mark__head { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.by-mark__kind { font-size: 9.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--by-mut2); }
.by-mark__value { font-size: 12.5px; font-weight: 600; }
.by-mark__src { font-size: 10px; color: var(--by-mut2); margin-left: auto; min-width: 0; overflow-wrap: anywhere; }
.by-mark__facts { margin-top: 3px; font-size: 10.5px; color: var(--by-mut2); }

.by-mark__quote {
  margin-top: 5px;
  padding: 5px 7px;
  font-size: 11px;
  line-height: 1.4;
  overflow-wrap: anywhere;
  color: var(--by-mut);
  background: var(--by-panel2);
  border-radius: var(--by-r);
}

.by-mark__disputed { margin-top: 5px; font-size: 10.5px; color: var(--by-mut2); overflow-wrap: anywhere; }
.by-mark__note { margin-top: 6px; font-size: 10.5px; color: var(--by-mut2); }

.by-mark__btn {
  margin-top: 7px;
  padding: 3px 9px;
  font: inherit;
  font-size: 11px;
  color: var(--by-mut);
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--by-r);
  cursor: pointer;
}

.by-mark__btn:hover { color: var(--text); background: var(--by-panel3); }

.by-mark__form { display: flex; gap: 6px; margin-top: 7px; }

.by-mark__reason {
  flex: 1 1 auto;
  min-width: 0;
  padding: 4px 8px;
  font: inherit;
  font-size: 11.5px;
  color: var(--text);
  background: var(--by-panel2);
  border: 1px solid var(--border);
  border-radius: var(--by-r);
}

.by-mark__send {
  flex: 0 0 auto;
  padding: 4px 10px;
  font: inherit;
  font-size: 11.5px;
  color: var(--text);
  background: var(--by-panel3);
  border: 1px solid var(--border);
  border-radius: var(--by-r);
  cursor: pointer;
}

.by-mark__send[disabled] { opacity: .6; cursor: default; }
.by-mark__err { margin-top: 5px; font-size: 10.5px; color: var(--by-sell); }

/* Кнопка проверки документа в ленте чата. Габариты жёсткие: пузырь сообщения
   не должен менять высоту, когда кнопка сменит значок на результат. */
.by-msg__check {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin-left: 6px;
  padding: 0;
  font: inherit;
  font-size: 12px;
  line-height: 1;
  color: var(--by-mut);
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--by-r);
  cursor: pointer;
}

.by-msg__check:hover { color: var(--text); background: var(--by-panel3); }

/*
 * «Попросить чек файлом» под чужим скриншотом.
 *
 * Раньше это была та же квадратная кнопка с подписью «PDF?» — она читалась как
 * обрубок и спорила с пузырём. Теперь пилюля в общем стиле раздела: приглушённая
 * рамка, при наведении наливается акцентом. Высота фиксирована — пузырь не
 * должен менять габариты от наведения.
 */
.by-msg__ask {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 20px;
  margin-left: 6px;
  padding: 0 8px;
  font: inherit;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--by-mut);
  background: none;
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: color .13s ease, background-color .13s ease, border-color .13s ease;
}

/* Лист бумаги с загнутым углом — рисуем рамкой, без картинки: значок мелкий,
   и лишний файл ради двенадцати пикселей не нужен. */
.by-msg__ask__ico {
  width: 7px;
  height: 9px;
  border: 1px solid currentColor;
  border-radius: 1px;
  border-top-right-radius: 3px;
}

.by-msg__ask:hover {
  color: var(--by-acc);
  border-color: color-mix(in srgb, var(--by-acc) 60%, transparent);
  background: color-mix(in srgb, var(--by-acc) 12%, transparent);
}

.by-msg__ask:active { transform: scale(.96); }



/* Предупреждение о цене запроса. Не украшение: оператор должен видеть, что
   действие необратимо и оставляет наш след в чужой истории проверок. */

/* Значок «в реестре скамеров» у ника в списках.
   Размеры ЖЁСТКИЕ и line-height: 1 — иначе значок крупнее строки растянул бы
   line-box, и список подпрыгивал бы в момент его появления. По той же причине
   он не меняет габариты при наведении: скачок под курсором в прокручиваемом
   списке даёт самоподдерживающийся каскад. */
.by-scamMark {
  display: inline-block;
  width: 8px;
  height: 8px;
  /* Слева — на толщину ореола: контейнеры ника обрезают содержимое
     (overflow: hidden), и без отступа виден не кружок, а полукружие. */
  margin-left: 2px;
  margin-right: 4px;
  line-height: 1;
  vertical-align: middle;
  border-radius: 50%;
  background: var(--by-sell);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--by-sell) 22%, transparent);
}

/* Проверка номера по базе скамеров — строка под каждым реквизитом. */


/* ---------- действия ---------- */


.by-btn {
  width: 100%;
  height: 32px;
  padding: 0 12px;
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  border-radius: var(--by-r);
  border: 1px solid var(--border);
  background: var(--by-panel2);
  color: var(--text);
  cursor: pointer;
  transition: var(--transition);
}

.by-btn:hover { background: var(--by-panel3); }
.by-btn--ghost { color: var(--by-mut); }

/* ---------- чат ---------- */


.by-msg {
  max-width: 82%;
  padding: 5px 10px;
  font-size: 11.5px;
  line-height: 1.4;
  border-radius: 10px;
  overflow-wrap: anywhere;
}

.by-msg--them {
  align-self: flex-start;
  background: var(--by-panel3);
  border: 1px solid var(--border);
}

.by-msg--me {
  align-self: flex-end;
  background: color-mix(in srgb, var(--primary) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--primary) 28%, transparent);
}

/* Системные сообщения биржи — не переписка, поэтому без пузыря и во всю ширину */
.by-msg--sys {
  align-self: stretch;
  max-width: 100%;
  padding: 4px 0;
  font-size: 10px;
  color: var(--by-mut2);
  border-top: 1px solid var(--by-border2);
  border-radius: 0;
}

/* Незнакомое длинное системное сообщение: свёрнуто до первой строки, полный
   текст по клику. details/summary — без обработчиков, лента их не теряет. */
details.by-msg--sysLong summary {
  display: block;
  cursor: pointer;
  list-style: none;
}

details.by-msg--sysLong summary::-webkit-details-marker { display: none; }

.by-msg__more { font-weight: 600; color: var(--by-unread); white-space: nowrap; }
.by-msg__more::before { content: " ещё"; }

details.by-msg--sysLong[open] summary span { display: none; }
details.by-msg--sysLong[open] .by-msg__more::before { content: "свернуть"; }

.by-msg__full { margin-top: 3px; white-space: pre-wrap; }

/* Наше системное событие (апелляция, запрос на отмену). Биржа таких сообщений
   не шлёт — мы распознаём их сами по смене состояния ордера. В отличие от
   системных сообщений Bybit показываем со временем: по спору важно не только
   что произошло, но и когда. */
.by-msg--event {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  padding: 6px 0;
  color: var(--by-amber);
  border-top-color: color-mix(in srgb, var(--by-amber) 30%, transparent);
}

.by-msg__eventText { font-weight: 600; }
.by-msg__eventTime { color: var(--by-mut2); font-size: 9.5px; }


/* Два состояния ордера видно в списке не глядя на колонку статуса — заливкой
   строки и полосой слева. Жёлтый — запрос на отмену: требует ответа, но ордер
   жив. Красный — апелляция: спор уже идёт. Доли подобраны так, чтобы строка
   читалась, а не слепила: текст в ней остаётся основным. */


/* Апелляция серьёзнее — при совпадении цвет строки остаётся за ней
   (правило идёт ниже и перебивает жёлтый). */


/* Значок мерчанта перед ником. Эмодзи крупнее текста по своей природе,
   поэтому слегка уменьшаем — иначе строка в плотной таблице «распухает». */
.by-badge {
  margin-right: 3px;
  font-size: 0.9em;
  line-height: 1;
  cursor: help;
}

/* Вкладка со спорами, пока они есть: пропустить апелляцию дороже всего,
   поэтому она заметна даже когда открыт другой список. */
.by-ordTab.is-alarm {
  color: var(--by-sell);
  border-color: color-mix(in srgb, var(--by-sell) 45%, transparent);
  background: color-mix(in srgb, var(--by-sell) 12%, transparent);
}


/* Отсчёт рядом со статусом: срок оплаты, ожидание оплаты контрагентом или
   ответ на запрос отмены. Приглушён, чтобы не спорить с самим статусом. */
.by-ordLeft {
  flex: 0 0 auto; /* таймер не сжимается и не обрезается — режется текст статуса */
  font-size: 9.5px;
  font-weight: 400;
  color: var(--by-mut2);
  white-space: nowrap;
}

.by-ordLeft--warn { color: color-mix(in srgb, var(--by-amber) 85%, transparent); }
.by-ordLeft.is-urgent { color: var(--by-sell); font-weight: 700; }

/* Переводы строк в тексте сообщения видны как переводы строк. Свойство стоит
   на СПАНЕ с текстом, а не на пузыре: в разметке пузыря есть переносы и
   отступы, и pre-wrap на нём добавил бы пустые строки. */
.by-msg__text { white-space: pre-wrap; }

.by-msg__time { display: block; margin-top: 2px; font-size: 9.5px; color: var(--by-mut2); }

/* Галочки прочтения — только под НАШИМИ сообщениями (правило в chatView.js).
   Две зелёные — контрагент открыл переписку, одна серая — биржа отметку
   прочтения ещё не получила. Различаются формой И цветом: одним цветом смысл
   нести нельзя. Плотнее обычного — иначе «✓✓» читается как два значка. */
.by-msg__ticks { margin-left: 5px; font-size: 11px; letter-spacing: -1.5px; }
.by-msg__ticks.is-read { color: var(--by-acc); }
.by-msg__ticks.is-sent { color: var(--by-mut2); }

/* Новое сообщение всплывает снизу — видно, что оно именно пришло сейчас. */
@keyframes by-msgIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

.by-msg.is-appearing { animation: by-msgIn .26s cubic-bezier(.2, .7, .3, 1); }

/* Оператор читает переписку выше — прокрутку не дёргаем, а подсвечиваем низ
   ленты неоновым свечением: заметно, но не смещает ни строки. */


@keyframes by-chatGlowBlink {
  0%, 100% { opacity: 0; }
  50%      { opacity: 1; }
}


/* Смена содержимого правой колонки и панелей — мягким проявлением. */
.by-alert:not([hidden]),
.by-empty {
  animation: by-fadeIn .18s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .by-msg.is-appearing,
.by-viewer,
.by-alert:not([hidden]),
.by-empty {
    animation: none;
  }
  
}

/*
 * Значок отправки в кнопке `.by-icSend` (мини-композер под строкой списка).
 * Цветной (зелёный из файла), поэтому подложка у кнопки приглушённая: зелёное
 * на зелёном не читалось бы.
 */
.by-send__ico {
  width: 17px;
  height: 17px;
  background: url("/img/send.svg") center / contain no-repeat;
  /* Значок наклонён: у бумажного самолётика носом вперёд читается движение. */
  transform: rotate(45deg) translate(1px, -1px);
}

/* Панель прикреплённого (ещё не отправленного) файла над полем ввода */


@keyframes by-chipIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}


/* Вложения в чате */
.by-msg--file { padding: 4px; }

/* Пока картинка качается через backend, у обёртки нет содержимого —
   держим место, чтобы лента не прыгала при подстановке. */
.by-msg__imgWrap {
  display: block;
  min-width: 120px;
  min-height: 60px;
  border-radius: calc(var(--by-r) - 2px);
  background: var(--by-panel2);
  cursor: zoom-in;
  overflow: hidden;
}

/* Не загрузилось — говорим правду и не гасим курсор: обёртка кликабельна
   (data-viewer), клик качает файл заново и открывает просмотрщик. До
   20.08.2026 здесь стояло «Файл недоступен» с курсором-стрелкой, хотя файл
   прекрасно открывался по нажатию. */
.by-msg__imgWrap.is-failed {
  display: grid;
  place-items: center;
  padding: 10px;
  font-size: 11px;
  color: var(--by-mut2);
  cursor: pointer;
}

.by-msg__imgWrap.is-failed::after { content: "Не загрузилось — нажмите"; }

/* До загрузки в img стоит прозрачная заглушка — растягивать её не нужно,
   место держит сама обёртка. */
.by-msg__img {
  display: block;
  width: 1px;
  height: 1px;
  border-radius: calc(var(--by-r) - 2px);
}

.by-msg__imgWrap.is-loaded {
  min-width: 0;
  min-height: 0;
  background: none;
}

.by-msg__imgWrap.is-loaded .by-msg__img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 220px;
}

.by-msg__imgWrap.is-failed .by-msg__img { display: none; }

.by-msg__doc {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 11px;
  font: inherit;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--text);
  background: var(--by-panel2);
  border: 1px solid var(--border);
  border-radius: calc(var(--by-r) - 2px);
  cursor: pointer;
  text-decoration: none; /* .by-msg__doc бывает и ссылкой (фолбэк битого превью) */
  transition: var(--transition);
}

.by-msg__doc:hover { background: var(--by-panel3); border-color: var(--primary); }

/* Плашка файла, который ещё отправляется: открывать нечего, и вид обязан это
   говорить. Наведение не подсвечиваем — подсветка обещает клик. */
.by-msg__doc[disabled] { cursor: default; opacity: .8; }
.by-msg__doc[disabled]:hover { background: var(--by-panel2); border-color: var(--border); }

.by-msg__docIcon {
  width: 13px;
  height: 13px;
  flex: 0 0 auto;
  background: currentColor;
  -webkit-mask-image: url("../../img/skrepka.svg");
  mask-image: url("../../img/skrepka.svg");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* Для видео — треугольник плеера вместо скрепки */
.by-msg__docIcon--video {
  -webkit-mask-image: none;
  mask-image: none;
  background: none;
  width: auto;
  height: auto;
}

.by-msg__docIcon--video::before { content: "▶"; font-size: 10px; }

/* ---------- просмотрщик вложений ---------- */

.by-viewer {
  position: fixed;
  inset: 0;
  /* Выше всего на странице. Сайдбар с backdrop-filter создаёт собственный
     слой и при z-index 60 перекрывал заголовок окна слева. */
  z-index: 100000;
  animation: by-fadeIn .16s ease-out;
  display: flex;
  flex-direction: column;
  background: color-mix(in srgb, #000 78%, transparent);
  backdrop-filter: blur(4px);
  font-family: var(--font-ui);
}

.by-viewer__bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px;
}

.by-viewer__title { font-size: 12.5px; font-weight: 600; color: #fff; }

.by-viewer__open {
  margin-left: auto;
  font-size: 11.5px;
  color: color-mix(in srgb, #fff 75%, transparent);
  text-decoration: none;
}

.by-viewer__open:hover { color: #fff; text-decoration: underline; }

.by-viewer__close {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  font-size: 19px;
  line-height: 1;
  color: #fff;
  background: none;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  transition: var(--transition);
}

.by-viewer__close:hover { background: color-mix(in srgb, #fff 15%, transparent); }

.by-viewer__body {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  place-items: center;
  padding: 0 16px 16px;
  cursor: zoom-out;
  /* Если картинка всё же не влезла (очень узкая и длинная), пусть её можно
     прокрутить, а не обрезать молча. */
  overflow: auto;
}

/* Высоту ограничиваем экраном, а не процентами.
   `max-height: 100%` здесь не работал: строка грид-сетки авторазмерная, её
   высоту задаёт само содержимое — процент упирался сам в себя, ограничения не
   получалось, и длинные снимки (чеки из банковских приложений) уезжали вниз за
   край окна. 12.08.2026 из-за этого чек нельзя было рассмотреть целиком. */
.by-viewer__img,
.by-viewer__video {
  max-width: 100%;
  max-height: calc(100vh - 76px); /* полоса заголовка плюс отступы */
  max-height: calc(100dvh - 76px);
  object-fit: contain;
  border-radius: var(--by-r);
  cursor: default;
  box-shadow: 0 18px 60px rgba(0, 0, 0, .55);
}

.by-viewer__note {
  padding: 16px 20px;
  font-size: 12.5px;
  color: color-mix(in srgb, #fff 78%, transparent);
  cursor: default;
}

/* Просмотрщик с разбором — ДВЕ колонки.
   Только у PDF с контекстом: картинке и видео вторая колонка отнимала бы место
   ни за чем, а просмотрщик один на три типа.

   Сетка стоит на теле, но `data-viewer-close` остаётся на нём же — закрытие по
   фону работает как прежде, потому что клики по содержимому до него не доходят
   (у половин свои боксы). */
.by-viewer__body--split {
  grid-template-columns: minmax(0, 1.4fr) minmax(320px, 0.85fr);
  align-items: stretch;
  gap: 14px;
  place-items: stretch;
  cursor: default;
}

.by-viewer__body--split > * { min-height: 0; }

.by-viewer__main {
  display: grid;
  place-items: center;
  min-height: 0;
  min-width: 0;
}

/* Разбор прокручивается САМ. Докрутил до конца — страница под окном не едет:
   там живая лента ордеров, и уехать по ней посреди проверки очень легко. */
.by-viewer__side {
  overflow: auto;
  overscroll-behavior: contain;
  min-width: 0;
  border-radius: 12px;
}

/* В сплите документ занимает свою колонку целиком, а не 920 px по центру. */
.by-viewer__body--split .by-viewer__frame {
  width: 100%;
  height: 100%;
}

.by-viewer__frame {
  width: min(920px, 100%);
  /* По той же причине, что и у картинки: 100% в авторазмерной строке сетки
     ничего не ограничивает, и рамка PDF растягивалась за экран. */
  height: calc(100vh - 76px);
  height: calc(100dvh - 76px);
  border: none;
  border-radius: var(--by-r);
  background: #fff;
  cursor: default;
}


/* ============================================================
   Мои объявления: живой список, смена цены, вкл/выкл публикации
   ============================================================ */

.by-ads__list {
  overflow-y: auto;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Объявления в несколько колонок внутри карточки аккаунта — БЕЗ
   контейнер-запросов: auto-fill сам считает, сколько колонок влезает, а
   связка @container с зумом панели молча не срабатывала — второй ряд не
   появлялся (14.08.2026). Заполнение по рядам, слева направо.

   Колонки auto-fill 300–340px: узкий диапазон держит карточки почти одной
   ширины на любом зуме; min(300px, 100%) — чтобы совсем узкая панель не
   получала горизонтальный скролл. */
.by-adAcc__inner {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 340px));
  justify-content: start;
  gap: 8px;
  align-items: start;
}

/* Служебные строки — своей строкой, но не лентой во всю панель: та же
   максимальная ширина, что у карточек, и прижаты влево (решение владельца). */
.by-adAcc__inner > .by-adOffBar,
.by-adAcc__inner > .by-adPick,
.by-adAcc__inner > .by-adAcc__none {
  grid-column: 1 / -1;
  max-width: 340px;
  width: 100%;
  justify-self: start;
}

.by-adAcc__inner > .by-ad { min-width: 0; width: 100%; }

.by-ad {
  /* Потолок ширины ВСЕГДА, не только в сетке: полный редактор и панель выплат
     не должны расползаться во всю панель — свободное место справа честнее
     растянутой ленты. 340 CSS-px (решение владельца 14.08.2026): ряд из
     четырёх ячеек сумм помещается, а при масштабе панели потолок растёт
     вместе с ней — карточка держит один и тот же вид на любом зуме. */
  max-width: 340px;
  /* Грид-элемент с min-width:auto распирает трек своим min-content — из-за
     этого карточка выплат вылезала из колонки на всю панель. */
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--by-r);
  background: var(--by-panel);
  /* слева чуть больше: у левого края живёт полоска режима (see .by-ad__mode) */
  padding: 8px 9px 8px 13px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.by-ad__row {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.by-ad__row--meta {
  justify-content: space-between;
  font-size: 10.5px;
  color: var(--by-mut);
}

.by-ad__pair {
  font-size: 10.5px;
  color: var(--by-mut);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.by-ad__status {
  font-size: 10px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid var(--border);
  flex-shrink: 0;
}

.by-ad__status--on   { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.by-ad__status--off  { color: var(--by-mut); }
.by-ad__status--done { color: var(--by-mut); opacity: .7; }

/* Цена — кнопка: жирная, при наведении подсказывает, что она изменяемая */
.by-ad__price {
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  border-radius: 6px;
}

/* Курс НЕ переносим: рядом с ним появляется чип предела, и при нехватке места
   ломался именно он — «83.92» и «RUB» уезжали на разные строки, а высота
   карточки прыгала. Ужиматься есть чему другому: остаток объявления. */
.by-ad__price { white-space: nowrap; }

.by-ad__price small { font-weight: 500; color: var(--by-mut); }
.by-ad__price:hover { color: var(--primary); }

.by-ad__qty {
  margin-left: auto;
  font-size: 10.5px;
  color: var(--by-mut);
  white-space: nowrap;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Пока открыт чип предела, остаток уходит совсем.
   Ужимать его до многоточия мы уже пробовали: на узкой карточке от «49 943,72
   USDT» оставалась одна цифра — мусор, который читается как ошибка. Остаток —
   справка, правка длится секунды, и на это время место принадлежит органу
   управления. Прячем на всю строку, а не по ширине: «иногда исчезает» хуже,
   чем «исчезает всегда», — второе можно запомнить. */
.by-ad__row:has(.by-adPrice--top1) .by-ad__qty { display: none; }

.by-ad__actions { display: flex; gap: 6px; }

.by-btn--xs {
  width: auto;
  height: 24px;
  padding: 0 10px;
  font-size: 11px;
}

.by-ad__editor {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding-top: 2px;
}

.by-ad__editor[hidden] { display: none; }
.by-ad__editLabel { font-size: 10.5px; color: var(--by-mut); flex-basis: 100%; }

.by-input {
  font: inherit;
  color: var(--text);
  background: var(--by-panel2);
  border: 1px solid var(--border);
  border-radius: var(--by-r);
  padding: 0 8px;
  min-width: 0;
}

.by-input--sm { height: 24px; font-size: 12px; flex: 1 1 70px; }

/* Число ниже допустимого предела. Краснеет сразу при вводе: отказ по нажатию
   «Сохранить» приходит поздно — оператор к тому моменту уже смотрит в другое
   место. Правило общее для всех полей с data-min. */
.by-input.is-bad,
.by-adPrice__input.is-bad {
  color: var(--by-sell);
  border-color: color-mix(in srgb, var(--by-sell) 60%, var(--border));
  background: color-mix(in srgb, var(--by-sell) 10%, transparent);
}
.by-input:focus { outline: none; border-color: color-mix(in srgb, var(--primary) 55%, var(--border)); }

/* ---------- полный редактор: поля парами, числа как в быстром ----------
   Цена + объём и мин + макс лимиты — в одну строку: панель узкая, но по два
   числа помещаются, а редактор становится вдвое ниже. Само число оформлено
   как в шапке карточки: без рамки, подложка при наведении, подчёркивание в
   фокусе. */
.by-adEd__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 10px;
  align-items: end;
}

.by-adEd__wide { grid-column: 1 / -1; }

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

.by-adEd__lbl {
  font-size: 9.5px;
  color: var(--by-mut2);
  letter-spacing: .02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.by-adEd__num {
  width: 100%;
  padding: 2px 4px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--text);
  background: none;
  border: none;
  border-radius: 5px;
  outline: none;
  font-variant-numeric: tabular-nums;
  transition: background .13s ease, box-shadow .13s ease;
}

.by-adEd__num:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }

.by-adEd__num:focus {
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  box-shadow: inset 0 -1px 0 var(--primary);
}

.by-adEd__num.is-bad {
  color: var(--by-sell);
  background: color-mix(in srgb, var(--by-sell) 10%, transparent);
  box-shadow: inset 0 -1px 0 var(--by-sell);
}

.by-ad__hint {
  font-size: 10.5px;
  color: var(--by-mut);
  line-height: 1.35;
}

.by-ad__hint.is-bad { color: #e5484d; }

/* ---------- режим объявления: «Классика» / «БТ» ----------
   Полоска в самой левой части карточки. В классике — едва заметная, чтобы не
   шуметь; в БТ — акцентная: режим меняет поведение правок, и это должно быть
   видно с одного взгляда. Сама полоска — кнопка-переключатель. */
.by-ad { position: relative; }

.by-ad__mode {
  position: absolute;
  left: 0;
  top: 6px;
  bottom: 6px;
  width: 4px;
  padding: 0;
  background: color-mix(in srgb, var(--text) 14%, transparent);
  border: none;
  border-radius: 999px;
  cursor: pointer;
  transition: background .15s ease, width .12s ease, box-shadow .15s ease;
}

.by-ad__mode:hover { width: 6px; background: color-mix(in srgb, var(--text) 28%, transparent); }

/* Цвет полоски = режим. Три режима — три цвета, чтобы объявления
   различались боковым зрением, не вчитываясь. */
.by-ad.is-mode-bt .by-ad__mode {
  background: var(--by-acc);
  box-shadow: 0 0 6px color-mix(in srgb, var(--by-acc) 45%, transparent);
}

.by-ad.is-mode-payouts .by-ad__mode {
  background: var(--by-unread);
  box-shadow: 0 0 6px color-mix(in srgb, var(--by-unread) 45%, transparent);
}

.by-ad.is-mode-bt .by-ad__mode:hover,
.by-ad.is-mode-payouts .by-ad__mode:hover { width: 6px; }

/* ---------- режим «Выплаты»: панель прямо в карточке ----------
   Всё на виду: суммы, курс, лимиты, объём и подтверждение. Карточка от этого
   заметно выше — так и задумано, список выплат и есть её содержание.
   Ширина панели объявлений 320px, внутри карточки остаётся около 280 —
   поэтому поля мелкие, подписи короткие, ячейки переносятся. */
.by-payouts {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 6px;
  padding: 6px 7px 7px;
  border-radius: 9px;
  border: 1px solid color-mix(in srgb, var(--by-unread) 28%, transparent);
  background: color-mix(in srgb, var(--by-unread) 6%, transparent);
}

.by-payouts.is-busy { opacity: .6; pointer-events: none; }

/* Переключатель авто-снятия. Индикатор-точка, а не галочка: состояние должно
   читаться боковым зрением — включённый автомат меняет объявление сам. */
.by-payouts__auto {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 4px;
  padding: 2px 7px;
  font: inherit;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--by-mut2);
  background: none;
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: color .13s ease, border-color .13s ease, background .13s ease;
}

.by-payouts__autoDot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  opacity: .45;
}

.by-payouts__auto:hover { color: var(--text); border-color: var(--by-mut2); }

/* Включённый автомат — зелёным. Синий здесь тонул: им же покрашены и метки
   непрочитанного, и рамка карточки со своей версией, — состояние «объявление
   правится само» терялось среди них. */
.by-payouts__auto.is-on {
  color: var(--by-acc);
  border-color: color-mix(in srgb, var(--by-acc) 55%, transparent);
  background: color-mix(in srgb, var(--by-acc) 14%, transparent);
}

/* Точка мигает по-настоящему: автомат меняет объявление на бирже сам, и это
   должно ловиться боковым зрением, а не разглядыванием. Гаснет не в ноль —
   пропадающая точка читалась бы как «связь оборвалась». */
.by-payouts__auto.is-on .by-payouts__autoDot {
  background: var(--by-acc);
  animation: by-autoBlink 1.1s ease-in-out infinite;
}

@keyframes by-autoBlink {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--by-acc) 70%, transparent);
  }
  45% {
    opacity: .25;
    transform: scale(.72);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--by-acc) 0%, transparent);
  }
}

.by-payouts__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--by-mut);
}

.by-payouts__total {
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--by-mut2);
  font-variant-numeric: tabular-nums;
}

.by-payouts__cells { display: flex; flex-wrap: wrap; gap: 4px; }

/* Ячейка суммы: правится на месте, «−» рядом убирает именно её. */
.by-payoutCell {
  display: inline-flex;
  align-items: stretch;
  height: 22px;
  background: var(--by-panel2);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}

.by-payoutCell:focus-within { border-color: color-mix(in srgb, var(--primary) 55%, var(--border)); }

.by-payoutCell__input {
  width: 52px;
  padding: 0 5px;
  font: inherit;
  font-size: 11px;
  color: var(--text);
  background: none;
  border: none;
  outline: none;
  font-variant-numeric: tabular-nums;
}

.by-payoutCell__input::placeholder { color: var(--by-mut2); font-size: 9.5px; }

.by-payoutCell__del {
  width: 15px;
  font: inherit;
  font-size: 12px;
  line-height: 1;
  color: var(--by-mut2);
  background: none;
  border: none;
  border-left: 1px solid var(--border);
  cursor: pointer;
  transition: color .13s ease, background .13s ease;
}

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

.by-payoutCell.is-bad { border-color: color-mix(in srgb, var(--by-amber) 60%, transparent); }
.by-payoutCell.is-bad .by-payoutCell__input { color: var(--by-amber); }

.by-payoutCell__add {
  width: 22px;
  height: 22px;
  font: inherit;
  font-size: 13px;
  line-height: 1;
  color: var(--by-mut);
  background: none;
  border: 1px dashed var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: color .13s ease, border-color .13s ease;
}

.by-payoutCell__add:hover { color: var(--by-acc); border-color: color-mix(in srgb, var(--by-acc) 55%, var(--border)); }

.by-payouts__warn {
  font-size: 9.5px;
  color: var(--by-amber);
  font-variant-numeric: tabular-nums;
}

/* Курс и лимиты — в одну строку, подпись слева от поля. */
.by-payouts__fields { display: flex; gap: 4px; }


/* Объём, шаблон и галочка — одной строкой внизу. */
/* Условия — не «окошко» с прокруткой, а текст целиком: по обрезанному куску
   («…чека PDF. Оплата с любого…») невозможно проверить, то ли уйдёт. */
/* Лимиты в шапке: тире между полями с воздухом — иначе верхний лимит
   наезжает на него и читается как знак минус. */
.by-ad__limits .by-adPrice__input { text-align: center; }
.by-ad__limits { display: inline-flex; align-items: center; gap: 4px; }
.by-ad__limitsDash { color: var(--by-mut2); }

.by-payouts__previewWrap {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-top: 2px;
  border-top: 1px dashed color-mix(in srgb, var(--text) 12%, transparent);
}

.by-payouts__previewLabel {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--by-mut2);
}

.by-payouts__preview {
  font-size: 10px;
  line-height: 1.45;
  color: var(--by-mut);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.by-payouts__foot { display: flex; align-items: center; gap: 4px; }

.by-payouts__qty {
  flex: 0 0 auto;
  font-size: 10px;
  color: var(--by-mut2);
  font-variant-numeric: tabular-nums;
}

.by-payoutTpl {
  flex: 1 1 auto;
  min-width: 0;
  height: 22px;
  padding: 0 4px;
  font: inherit;
  font-size: 10px;
  color: var(--text);
  background: var(--by-panel2);
  border: 1px solid var(--border);
  border-radius: 6px;
}

/* Селект одет глобальным customSelect: его кнопка наследует классы селекта
   (by-payoutTpl, is-danger), поэтому компактные размеры и красная пульсация
   работают и на виджете. Ужимаем только каре — базовые 38px рассчитаны на
   полноразмерные поля. */
.by-payouts__foot .hc-selectWrap { flex: 1 1 auto; min-width: 0; }

.by-payouts__foot .hc-selectBtn.by-payoutTpl { padding-right: 20px !important; }

.by-payouts__foot .hc-selectBtn.by-payoutTpl::after {
  right: 7px;
  width: 6px;
  height: 6px;
  border-width: 1.5px;
}

/* Шаблонов нет — «условия не менять» единственный пункт, и это опасное
   состояние: суммы обновятся, а текст на бирже нет. Горим красным с мягкой
   пульсацией, пока оператор не заведёт шаблон. */
.by-payoutTpl.is-danger {
  color: var(--by-sell);
  border-color: color-mix(in srgb, var(--by-sell) 65%, var(--border));
  background: color-mix(in srgb, var(--by-sell) 10%, transparent);
  animation: by-tplDanger 2.2s ease-in-out infinite;
}

@keyframes by-tplDanger {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--by-sell) 35%, transparent); }
  50%      { box-shadow: 0 0 0 4px color-mix(in srgb, var(--by-sell) 0%, transparent); }
}

.by-payouts__ok {
  flex: 0 0 auto;
  width: 26px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--by-mut);
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: color .13s ease, border-color .13s ease, background .13s ease;
}

.by-payouts__ok svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.4; }

/* Пока есть несохранённое — галочка зовёт нажать. */
.by-payouts__ok.is-dirty {
  color: #08130d;
  background: var(--by-acc);
  border-color: var(--by-acc);
}

.by-payouts__ok:hover { border-color: var(--by-acc); color: var(--by-acc); }
.by-payouts__ok.is-dirty:hover { color: #08130d; background: color-mix(in srgb, var(--by-acc) 82%, #fff); }

/* Остаток правок в окне: показываем, только когда он близок к концу. */
.by-payouts__left {
  flex: 0 0 auto;
  font-size: 9.5px;
  color: var(--by-amber);
  font-variant-numeric: tabular-nums;
}

.by-payouts__note { font-size: 9.5px; color: var(--by-mut2); }
.by-payouts__note.is-bad { color: var(--by-sell); }

/* ---------- шаблоны условий: окно управления ----------
   Шаблоны общие для всех команд и разделены по типу объявления (Классика, БТ,
   Выплаты). Вариация — тот же шаблон под конкретный аккаунт. */
/* Окно шаблонов условий переехало в css/ui/template-editor.css: оно нужно не
   только объявлениям, и его цвета не должны зависеть от токенов этой страницы. */


/* Кнопка шестерёнки рядом с выбором шаблона. */
.by-payouts__tplBtn,
.by-ad__tplBtn {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  font: inherit;
  font-size: 11px;
  color: var(--by-mut);
  background: var(--by-panel2);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: color .13s ease, border-color .13s ease;
}

.by-payouts__tplBtn:hover,
.by-ad__tplBtn:hover { color: var(--by-acc); border-color: color-mix(in srgb, var(--by-acc) 55%, var(--border)); }

/* Выбор шаблона в полном редакторе — рядом с полем условий. */
.by-ad__tplPick { display: flex; gap: 5px; align-items: center; }
.by-ad__tplPick select { flex: 1 1 auto; min-width: 0; }
/* Селект одет глобальным customSelect: тянется его обёртка, а не сам select. */
.by-ad__tplPick .hc-selectWrap { flex: 1 1 auto; min-width: 0; }
.by-adEd__cell .hc-selectWrap { width: 100%; min-width: 0; }

/* ---------- меню выбора режима ----------
   Лежит в body (у карточки своя прокрутка и обрезка), поэтому позиционируется
   от координат полоски. */
.by-modeMenu {
  /* Меню висит в <body>: токены раздела объявлены на .bybit-page и сюда не
     доходят — цветные полоски БТ и Выплат из-за этого молча пропадали. */
  --by-acc: var(--primary);
  --by-unread: #2f81f7;
  --by-mut: var(--muted);
  --by-mut2: color-mix(in srgb, var(--text) 45%, transparent);
  --by-panel2: color-mix(in srgb, var(--text) 7%, transparent);
  --by-border2: color-mix(in srgb, var(--text) 7%, transparent);

  position: fixed;
  z-index: 90;
  min-width: 232px;
  padding: 6px;
  border-radius: 12px;
  border: 1px solid var(--by-border2);
  /* ПЛОТНЫЙ фон, как у карточки ордера. --by-panel здесь не годится: он
     полупрозрачный по замыслу (подложка поверх плотной поверхности), и
     всплывающее меню сквозило объявлением под собой. */
  background: var(--page-bg-2);
  box-shadow: 0 12px 34px rgba(0, 0, 0, .45);
  animation: by-modeMenuIn .14s ease-out;
}

@keyframes by-modeMenuIn {
  from { opacity: 0; transform: translateX(-4px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

.by-modeMenu__head {
  padding: 4px 8px 6px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--by-mut2);
}

.by-modeMenu__item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 8px;
  font: inherit;
  text-align: left;
  color: var(--text);
  background: none;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background .13s ease;
}

.by-modeMenu__item:hover { background: var(--by-panel2); }

/* Выбранный режим должен читаться сразу и однозначно: заливка, рамка слева в
   цвет режима и галочка. Раньше подсказкой служила только бледная заливка, а
   цветную метку рядом с названием принимали за указатель выбора. */
.by-modeMenu__item.is-active {
  background: color-mix(in srgb, var(--text) 9%, transparent);
  box-shadow: inset 2px 0 0 currentColor;
}

/* Метки режимов — сплошной цвет, а не градиент в прозрачность: на тёмном фоне
   растворявшаяся половина делала метку почти невидимой, и из трёх режимов
   заметным оставался только серый. */
.by-modeMenu__dot {
  flex: 0 0 auto;
  width: 5px;
  height: 28px;
  border-radius: 999px;
  /* Цвет обязателен у КАЖДОГО режима: по нему объявления различают в списке,
     и в меню он должен читаться так же однозначно. */
  background: #8b919b;
}

.by-modeMenu__dot--classic { background: #8b919b; }
.by-modeMenu__dot--bt { background: var(--by-acc); }
.by-modeMenu__dot--payouts { background: var(--by-unread); }

.by-modeMenu__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.by-modeMenu__text b { font-size: 12px; font-weight: 600; }
.by-modeMenu__text small { font-size: 10.5px; color: var(--by-mut2); }

/* Выбранный режим отмечаем галочкой справа — без неё активная строка читается
   как «наведён курсор». */
.by-modeMenu__item.is-active::after {
  content: "✓";
  margin-left: auto;
  font-size: 12px;
  color: var(--by-acc);
}

/* Цвет полосы слева у выбранной строки — цвет самого режима. */
.by-modeMenu__item.is-active { color: color-mix(in srgb, var(--text) 40%, transparent); }
.by-modeMenu__item.is-active:has(.by-modeMenu__dot--bt) { color: var(--by-acc); }
.by-modeMenu__item.is-active:has(.by-modeMenu__dot--payouts) { color: var(--by-unread); }
.by-modeMenu__item.is-active .by-modeMenu__text b { color: var(--text); }

/* Строка БТ: один лимит вместо пары и объём из него.
   Лимит — тем же шрифтом, цветом и размером, что курс (класс by-ad__price). */
.by-adBt { display: inline-flex; align-items: baseline; gap: 8px; min-width: 0; }

.by-adBt__qty {
  font-size: 11px;
  color: var(--by-mut2);
  white-space: nowrap;
}

/* ---------- правка цены на месте ----------
   Поле встаёт ровно туда, где было число; галочка подтверждения появляется
   только когда число изменили. Волчок и «лопанье» — состояния одной кнопки. */
.by-adPrice { display: inline-flex; align-items: center; gap: 5px; min-width: 0; }

/* Правка прямо в числе: поле выглядит как сам текст, «окошко» не появляется.
   Раньше на месте цены возникал ввод с рамкой и своим фоном — цифра прыгала,
   а взгляд каждый раз заново её искал. Теперь меняется только само число,
   а что оно редактируется, показывает мягкое подчёркивание. */
.by-adPrice__input {
  padding: 0 2px;
  font: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  color: var(--text);
  background: none;
  border: none;
  border-radius: 5px;
  outline: none;
  font-variant-numeric: tabular-nums;
  transition: background .13s ease, box-shadow .13s ease;
}

/* Что число правится, показываем подложкой при наведении и в фокусе —
   пунктир под цифрой смотрелся грязно. */
.by-adPrice__input:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }

.by-adPrice__input:focus {
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  box-shadow: inset 0 -1px 0 var(--primary);
}

/* Ширина по содержимому: длинная цена не должна обрезаться, короткая —
   растягивать строку. Значение ставит код (growInput) и обновляет по мере
   набора; min-width — страховка на случай пустого поля. */
.by-adPrice__input { min-width: 4ch; max-width: 12ch; }


.by-adPrice__input:focus { outline: none; border-color: var(--primary); }
.by-adPrice__input:disabled { opacity: .6; }
.by-adPrice__suffix { font-size: 11px; color: var(--by-mut2); }

/* Тумблер авто-проверки места — слева от предела, внутри того же поля.

   Виден ВСЕГДА, в отличие от галочки подтверждения: галочка появляется, когда
   есть что сохранять, а тумблер сам по себе и есть то, что сохраняют. Выключен
   — приглушён, а не перекрашен: это настройка, а не тревога, и красный тут
   спорил бы с красным «мы отрезаны» на самой кнопке.

   Высоту отбиваем адресно и ВНЕ media-запроса: mobile.css поднимает всем
   button min-height 40px ради тач-целей, и полоса высотой в строку курса
   превратилась бы на телефоне в блок. */
.by-adPrice__rev {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  padding: 0;
  display: grid;
  place-items: center;
  color: var(--by-mut2);
  background: none;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  opacity: .6;
  transition: color .13s ease, background .13s ease, opacity .13s ease;
}

.by-adPrice__rev svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Включённый тумблер — ЦВЕТОМ, без заливки: заливка делала из него второй
   зелёный кружок рядом с галочкой подтверждения, и взгляд не понимал, какой
   из них главный. Главный — галочка, она про действие. */
.by-adPrice__rev.is-on {
  opacity: 1;
  color: var(--by-acc);
}

.by-adPrice__rev:hover {
  opacity: 1;
  background: color-mix(in srgb, var(--text) 10%, transparent);
}

.by-adPrice__rev:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.by-ad .by-adPrice__rev { min-height: 18px; }

.by-adPrice__ok {
  width: 20px;
  height: 20px;
  padding: 0;
  display: none;
  place-items: center;
  color: var(--by-acc);
  background: color-mix(in srgb, var(--by-acc) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--by-acc) 45%, transparent);
  border-radius: 50%;
  cursor: pointer;
  transition: transform .12s ease, background .15s ease;
}

.by-adPrice.is-dirty .by-adPrice__ok,
.by-adPrice.is-busy .by-adPrice__ok,
.by-adPrice.is-done .by-adPrice__ok { display: grid; }

/* Круг — это круг только пока высота равна ширине. mobile.css поднимает всем
   кнопкам min-height 40px ради тач-целей, и на узком экране галочка
   подтверждения превращалась в эллипс 20×40 (замерено 27.08.2026). Отбиваем
   адресно и ВНЕ media-запроса, где выигрывает специфичность, а не порядок
   файлов, — то же правило, что у кнопки TOP1 ниже. */
.by-ad .by-adPrice__ok { min-height: 20px; }

.by-adPrice.is-dirty .by-adPrice__ok { animation: by-ok-in .16s ease-out; }
.by-adPrice__ok:hover { background: color-mix(in srgb, var(--by-acc) 22%, transparent); transform: scale(1.08); }

.by-adPrice__ok svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Запрос в полёте: галочка уступает место волчку. */
.by-adPrice.is-busy .by-adPrice__ok { pointer-events: none; animation: none; }
.by-adPrice.is-busy .by-adPrice__ok svg { display: none; }
.by-adPrice.is-busy .by-adPrice__ok::after {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--by-acc) 35%, transparent);
  border-top-color: var(--by-acc);
  animation: by-adPrice-spin .7s linear infinite;
}

/* Успех: галочка возвращается и «лопается» — раздувается и тает. */
.by-adPrice.is-done .by-adPrice__ok { pointer-events: none; animation: by-ok-pop .45s ease-out forwards; }
.by-adPrice.is-done .by-adPrice__ok::after { content: none; }
.by-adPrice.is-done .by-adPrice__ok svg { display: block; }

@keyframes by-ok-in { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
@keyframes by-adPrice-spin { to { transform: rotate(360deg); } }
@keyframes by-ok-pop {
  0%   { opacity: 1; transform: scale(1); }
  45%  { opacity: 1; transform: scale(1.45); }
  100% { opacity: 0; transform: scale(1.9); }
}

@media (prefers-reduced-motion: reduce) {
  .by-adPrice.is-dirty .by-adPrice__ok,
  .by-adPrice.is-done .by-adPrice__ok { animation: none; }
  .by-adPrice.is-busy .by-adPrice__ok::after { animation-duration: 1.4s; }
}

/* Строка-подсказка редактора: курс из процента и пределы пары.
   Редактор — flex с переносом, поэтому строка занимает ряд целиком. */
.by-adRef {
  flex: 1 0 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 2px 8px;
  align-items: baseline;
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--by-txt);
}

.by-adRef b { font-variant-numeric: tabular-nums; }
.by-adRef__muted { color: var(--by-mut); }
.by-adRef__bad { color: #e5484d; }
.by-adRef--muted { color: var(--by-mut); }
.by-adRef[hidden] { display: none; }

.by-ad__hint[hidden] { display: none; }

.by-ad__offToggle {
  font: inherit;
  font-size: 11px;
  color: var(--by-mut);
  background: none;
  border: 1px dashed var(--border);
  border-radius: var(--by-r);
  padding: 6px;
  cursor: pointer;
}

.by-ad__offToggle:hover { color: var(--text); background: var(--by-panel); }

.by-ad { cursor: pointer; }
.by-ad:hover { border-color: color-mix(in srgb, var(--primary) 30%, var(--border)); }
.by-ad__editor { cursor: default; }

.by-ad__status--priv {
  color: #f5a623;
  border-color: color-mix(in srgb, #f5a623 45%, var(--border));
}

.by-ad__editor { display: grid; grid-template-columns: 1fr; gap: 4px; padding-top: 4px; }
.by-ad__editor[hidden] { display: none; }
.by-ad__editBtns { display: flex; gap: 6px; padding-top: 4px; }

/* Карточка аккаунта в панели объявлений: подпись «чьё» + объявления внутри */
.by-adAcc {
  border: 1px solid var(--border);
  border-radius: var(--by-r);
  background: var(--by-panel2);
  padding: 7px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.by-adAcc__head {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 0 2px;
}

.by-adAcc__name {
  font-family: var(--font-heading);
  font-size: 11.5px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.by-adAcc__team {
  font-size: 10px;
  color: var(--by-mut);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 6px;
  flex-shrink: 0;
}

.by-adAcc__meta {
  margin-left: auto;
  font-size: 10.5px;
  color: var(--by-mut);
  white-space: nowrap;
}

.by-adAcc__none {
  font-size: 10.5px;
  color: var(--by-mut);
  padding: 2px;
}

/* Кнопки обновления памяти объявлений */
.by-adRefresh {
  width: 20px;
  height: 20px;
  padding: 0;
  font-size: 13px;
  line-height: 1;
  color: var(--by-mut);
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  flex-shrink: 0;
}

.by-adRefresh:hover { color: var(--text); background: var(--by-panel3); }

/* В шапке панели счётчик больше не прижат к краю — место занимает кнопка */
.by-ads__head .by-ads__count { margin-left: auto; }
.by-ads__head .by-adRefresh { margin-left: 0; }
.by-adAcc__head .by-adAcc__meta { margin-left: auto; }

/* Быстрые редакторы и полный редактор объявления */
.by-ad__limits {
  font: inherit;
  font-size: 10.5px;
  color: var(--by-mut);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  border-radius: 6px;
}

.by-ad__limits:hover { color: var(--primary); }
.by-ad__qty { cursor: context-menu; }
.by-ad__qty:hover { color: var(--text); }

.by-ad__remark {
  width: 100%;
  font-size: 11.5px;
  line-height: 1.35;
  padding: 6px 8px;
  resize: vertical;
  min-height: 46px;
  font-family: var(--font-ui);
}

select.by-input { cursor: pointer; }

.by-adPm { display: flex; flex-direction: column; gap: 4px; }

.by-adPm__item {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  cursor: pointer;
  padding: 3px 4px;
  border-radius: 6px;
}

.by-adPm__item:hover { background: var(--by-panel3); }
.by-adPm__item input { accent-color: var(--primary); }

/* ============================================================
   Мои объявления: сворачивание карточек и всей панели (с анимацией),
   системные шрифты вместо моноширинных
   ============================================================ */

/* Панель целиком уезжает вправо: ширину ведёт transition, содержимое гаснет.
   Внутренним блокам ширина зафиксирована — при анимации контент обрезается,
   а не сжимается (сжатие и даёт дёрганья). */
.by-ads {
  /* Ширину колонки ведёт СЕТКА .by-work (--by-ads-w на ней): панель просто
     занимает свою колонку. Сама — карточка, как колонки ордеров. */
  position: relative;
  min-width: 0;
  border-radius: 12px;
  background: var(--by-panel);
  overflow: hidden;
}

.by-ads__head,
.by-ads__list {
  box-sizing: border-box;
}

.by-ads__head,
.by-ads__list {
  transition: opacity .16s ease;
}

.by-ads.is-collapsed { border-radius: 10px; }
.by-ads.is-collapsed .by-ads__head,
.by-ads.is-collapsed .by-ads__list {
  opacity: 0;
  pointer-events: none;
}

/* Кнопка создания в свёрнутой полосе: текст в тридцать пикселей не влезает и
   мялся в кашу — остаётся круглый «+» внизу, поверх разворачивателя. Клик
   разворачивает панель и сразу открывает форму (см. ads.js). */
.by-ads.is-collapsed .by-adCreate {
  position: absolute;
  left: 50%;
  bottom: 10px;
  transform: translateX(-50%);
  z-index: 3;
  width: 22px;
  height: 22px;
  margin: 0;
  padding: 0;
  font-size: 0; /* прячем подпись, «+» живёт отдельным элементом */
  gap: 0;
  border-radius: 50%;
  border-style: solid;
}

.by-ads.is-collapsed .by-adCreate .by-adCreate__plus {
  font-size: 14px;
  line-height: 1;
}

.by-ads.is-collapsed .by-adCreate:hover {
  background: color-mix(in srgb, var(--primary) 22%, transparent);
  border-color: var(--primary);
}

/* Форму создания свёрнутая полоса показать не может — гасим вместе со списком. */
.by-ads.is-collapsed .by-adNew {
  opacity: 0;
  pointer-events: none;
}

/* Вертикальная кнопка-разворачиватель занимает всю свёрнутую полосу */
.by-ads__expander {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--by-panel);
  border: none;
  border-left: 1px solid var(--border);
  color: var(--by-mut);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease .12s, color .15s ease;
}

.by-ads__expander span {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--font-heading);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .4px;
}

.by-ads.is-collapsed .by-ads__expander {
  opacity: 1;
  pointer-events: auto;
}

.by-ads__expander:hover { color: var(--text); }

/* Карточка аккаунта сворачивается кликом по шапке: высоту тела анимирует
   grid-rows 1fr→0fr — работает с любой высотой содержимого без замеров. */
.by-adAcc { gap: 0; }
.by-adAcc__head { cursor: pointer; user-select: none; }

.by-adAcc__chev {
  font-size: 10px;
  color: var(--by-mut);
  flex-shrink: 0;
  transition: transform .25s ease;
}

.by-adAcc.is-collapsed .by-adAcc__chev { transform: rotate(-90deg); }

.by-adAcc__body {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows .28s cubic-bezier(.4, 0, .2, 1);
}

.by-adAcc__inner {
  /* Раскладку (grid-колонки) задаёт блок «Мои объявления» выше — здесь только
     сворачивание. display: flex отсюда молча перебивал грид: этот блок ПОЗЖЕ
     в каскаде, и второй ряд карточек не появлялся вовсе (14.08.2026). */
  overflow: hidden;
  min-height: 0;
  padding-top: 7px;
}

.by-adAcc.is-collapsed .by-adAcc__body { grid-template-rows: 0fr; }
.by-adAcc.is-collapsed .by-adAcc__inner { padding-top: 0; }

/* Шрифты блока — системные (--font-ui), моноширинный смотрелся чужеродно */
/* Шрифт панели задаётся общим правилом страницы (--by-mono теперь наш
   Inter), здесь остаются только табличные цифры для ровных колонок. */
.by-ads .mono,
.by-ads .by-input,
.by-ads .by-ad__price,
.by-ads .by-ad__qty,
.by-ads .by-ad__limits,
.by-ads .by-ad__pair {
  font-family: var(--font-ui);
  font-variant-numeric: tabular-nums;
}

.by-adAcc__inner { transition: padding-top .28s cubic-bezier(.4, 0, .2, 1); }

/* Тумблер онлайн/снято: ползунок и цвет дорожки едут одним translate/color —
   без layout-свойств, поэтому анимация плавная всегда */
.by-adToggle {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  flex-shrink: 0;
}

.by-adToggle input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.by-adToggle__track {
  width: 30px;
  height: 16px;
  border-radius: 999px;
  background: var(--by-panel3);
  border: 1px solid var(--border);
  position: relative;
  transition: background .22s cubic-bezier(.4, 0, .2, 1), border-color .22s ease;
}

.by-adToggle__knob {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--by-mut);
  transition: transform .22s cubic-bezier(.4, 0, .2, 1), background .22s ease;
}

.by-adToggle input:checked + .by-adToggle__track {
  background: color-mix(in srgb, var(--primary) 30%, var(--by-panel3));
  border-color: color-mix(in srgb, var(--primary) 55%, var(--border));
}

.by-adToggle input:checked + .by-adToggle__track .by-adToggle__knob {
  transform: translateX(14px);
  background: var(--primary);
}

.by-adToggle input:disabled + .by-adToggle__track { opacity: .55; }
.by-adToggle:hover .by-adToggle__track { border-color: color-mix(in srgb, var(--primary) 40%, var(--border)); }

/* Шапка панели объявлений нажимается (сворачивает панель) — подсветка при
   наведении делает это очевидным */
.by-ads__head {
  cursor: pointer;
  user-select: none;
  transition: background .15s ease, color .15s ease;
}

.by-ads__head:hover {
  background: var(--by-panel3);
  color: var(--primary);
}

/* ============================================================
   Ссылка и QR приватного объявления
   ============================================================ */

/* «приватное» — не кнопка, а подпись: рамка и фон тут только шумели.
   Нажимаемость показывает подсветка текста при наведении, как у курса. */
.by-ad__priv {
  font-size: 10px;
  font-weight: 600;
  color: #f5a623;
  cursor: pointer;
  flex-shrink: 0;
  transition: color .15s ease;
}

.by-ad__priv:hover { color: #ffc46b; }

/* У публичных объявлений на этом же месте — значок ссылки с тем же меню */
.by-ad__linkIcon {
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  opacity: .45;
  flex-shrink: 0;
  transition: opacity .15s ease, transform .15s ease;
}

.by-ad__linkIcon:hover { opacity: 1; transform: scale(1.15); }

.by-adShare {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 7px;
  border: 1px solid var(--border);
  border-radius: var(--by-r);
  background: var(--by-panel2);
  cursor: default;
  animation: by-share-in .2s cubic-bezier(.4, 0, .2, 1);
}

.by-adShare[hidden] { display: none; }

@keyframes by-share-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

.by-share__row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.by-share__row .by-input { flex: 1 1 120px; }

.by-share__empty {
  font-size: 10.5px;
  color: var(--by-mut);
  line-height: 1.35;
}

.by-share__qr {
  display: flex;
  justify-content: center;
  padding: 4px 0;
}

.by-share__qr canvas {
  border-radius: 8px;
  background: #fff;
  padding: 6px;
  box-shadow: var(--shadow);
  transition: transform .2s cubic-bezier(.4, 0, .2, 1);
}

.by-share__qr canvas:hover { transform: scale(1.04); }
.by-share__qr { cursor: pointer; }
.by-share__qr:active canvas { transform: scale(.97); }

.by-share__note { font-size: 10.5px; color: var(--primary); min-height: 13px; }
.by-share__note.is-bad { color: #e5484d; }

/* ============================================================
   Требования к контрагенту (сворачиваемый блок)
   ============================================================ */

.by-prefs {
  border-top: 1px solid var(--border);
  padding-top: 7px;
  margin-top: 3px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.by-prefs__head {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 4px 6px;
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--by-r);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}

.by-prefs__head:hover {
  background: var(--by-panel3);
  border-color: color-mix(in srgb, var(--primary) 35%, var(--border));
}

.by-prefs__chev {
  font-size: 9px;
  color: var(--by-mut);
  transition: transform .25s ease;
  transform: rotate(-90deg);
}

.by-prefs.is-open .by-prefs__chev { transform: none; }

.by-prefs__count {
  margin-left: auto;
  font-size: 10px;
  font-weight: 500;
  color: var(--by-mut);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 6px;
}

/* Сводка включённых требований — компактными тегами под кнопкой */
.by-prefs__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.by-prefs__tags:empty { display: none; }

.by-prefs__tag {
  font-size: 9.5px;
  line-height: 1.5;
  color: var(--primary);
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--primary) 30%, transparent);
  border-radius: 999px;
  padding: 1px 7px;
  animation: by-tag-in .18s cubic-bezier(.4, 0, .2, 1);
}

@keyframes by-tag-in {
  from { opacity: 0; transform: scale(.9); }
  to   { opacity: 1; transform: none; }
}

/* Тело раскрывается высотой (grid 1fr/0fr) — плавно при любом содержимом */
.by-prefs__body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .26s cubic-bezier(.4, 0, .2, 1);
}

.by-prefs.is-open .by-prefs__body { grid-template-rows: 1fr; }

.by-prefs__inner {
  overflow: hidden;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

/* Три колонки: галочка — подпись — значение. Сетка (а не flex) держит
   список значений на своём месте, даже если подпись перенеслась. */
.by-prefs__item {
  display: grid;
  grid-template-columns: auto 1fr 84px;
  align-items: center;
  gap: 8px;
  font-size: 10.5px;
  line-height: 1.3;
  padding: 4px;
  border-radius: 6px;
  cursor: pointer;
  transition: background .15s ease;
}

/* У требований без значения подпись занимает и третью колонку */
.by-prefs__item:not(:has(.by-prefs__val)) { grid-template-columns: auto 1fr; }

.by-prefs__item:hover { background: var(--by-panel3); }
.by-prefs__item input[type="checkbox"] { accent-color: var(--primary); }
.by-prefs__title { min-width: 0; }

.by-prefs__val {
  width: 100%;
  height: 24px;
  font-size: 11px;
  padding: 0 6px;
}

.by-prefs__val:disabled { opacity: .4; cursor: not-allowed; }

/* Запас для браузеров без :has() — там подпись просто не растянется на
   третью колонку, но налезания всё равно не будет. */
@supports not selector(:has(*)) {
  .by-prefs__item { grid-template-columns: auto 1fr 84px; }
}

/* Призрак карточки, улетающей в кнопку снятых объявлений */
.by-adGhost {
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  border: 1px solid color-mix(in srgb, var(--primary) 40%, var(--border));
  border-radius: var(--by-r);
  background: var(--by-panel);
  box-shadow: var(--shadow);
}

/* ---------- балансы аккаунта в шапке ----------
   Свободный и замороженный ордерами. Клик копирует голое число — их вставляют
   в чужие формы, где пробелы-разделители ломают разбор. */
.by-adAcc__bal { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; min-width: 0; }

.by-adAcc__balBtn {
  padding: 1px 5px;
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  /* Свободный баланс — в полную яркость, наравне с ником: это первое, на что
     смотрят, решая, потянет ли аккаунт сделку. */
  color: var(--text);
  background: none;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  transition: color .13s ease, background .13s ease;
}

.by-adAcc__balBtn:hover { background: color-mix(in srgb, var(--text) 9%, transparent); }

/* Замороженное — приглушённо: это справка, а не рабочее число. */
.by-adAcc__balBtn.is-frozen { color: var(--by-mut2); font-weight: 500; font-size: 10.5px; }
.by-adAcc__balBtn.is-frozen:hover { color: var(--by-unread); }

/* Подтверждение копирования — вспышкой самой кнопки: место в шапке дорогое,
   отдельной подсказке там не развернуться. */
.by-adAcc__balBtn.is-copied {
  color: var(--by-acc);
  background: color-mix(in srgb, var(--by-acc) 18%, transparent);
}

/* Возраст памяти объявлений — короткой подписью у кнопки обновления */
.by-adAcc__age {
  font-size: 9.5px;
  color: var(--by-mut2, var(--by-mut));
  white-space: nowrap;
  flex-shrink: 0;
}

/* ---------- закрепление объявления ----------
   Закреплённое не уходит в «снятые»: смена, которая весь день работает с одним
   объявлением, не должна лазить за ним в свёрнутый список. Булавка бледная,
   пока не нажата, — это редкое действие, шуметь ему незачем. */
.by-adPin {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  color: var(--by-mut2);
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  opacity: .55;
  transition: color .13s ease, background .13s ease, opacity .13s ease, transform .18s ease;
}

.by-adPin svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.by-adPin:hover { opacity: 1; color: var(--text); background: color-mix(in srgb, var(--text) 9%, transparent); }

.by-adPin.is-on {
  opacity: 1;
  color: var(--by-acc);
  transform: rotate(-20deg);
}

.by-adPin.is-on svg { fill: color-mix(in srgb, var(--by-acc) 25%, transparent); }

/* Закреплённое, но снятое с публикации: приглушаем карточку — она стоит среди
   активных, и без метки её приняли бы за работающую. */
.by-ad.is-pinnedOff { opacity: .72; }
.by-ad.is-pinnedOff:hover { opacity: 1; }

/* Кнопка снятых слегка «пружинит», принимая карточку */
.by-ad__offToggle { transition: background .15s ease, color .15s ease, border-color .15s ease; }

/* ============================================================
   Шапка аккаунта: онлайн-точка, возраст, вращение кнопки обновления
   ============================================================ */

/* Счётчик онлайна с «дышащей» точкой — виден в свёрнутой карточке */
.by-adAcc__live {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  color: var(--by-mut);
  flex-shrink: 0;
}

.by-adAcc__dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--primary);
  animation: by-live-pulse 2.4s ease-in-out infinite;
}

@keyframes by-live-pulse {
  0%, 100% { opacity: .45; }
  50%      { opacity: 1; }
}

/* В развёрнутой карточке счётчик не нужен: объявления и так перед глазами */
.by-adAcc:not(.is-collapsed) .by-adAcc__live { display: none; }

/* Возраст памяти прижат к кнопке обновления: сдвигать вправо должен именно
   он, а всё остальное в шапке — оставаться слева. Поэтому auto-отступ живёт
   на возрасте, а не на счётчике онлайна (тот в развёрнутой карточке скрыт,
   и отступ вместе с ним пропадал — подпись зависала посередине). */
/* Единственная распорка в шапке аккаунта — перед возрастом: всё до него
   слева, он сам и кнопка обновления справа. Второй auto-отступ (например на
   кнопке) делил бы свободное место пополам, и подпись зависала посередине. */
.by-adAcc__age {
  margin-left: auto;
  padding-right: 2px;
}

.by-adAcc__live { margin-left: 4px; }

/* Вращается только стрелка: сама рамка кнопки должна стоять на месте,
   иначе крутящийся квадрат перетягивает на себя всё внимание. */
.by-adRefresh { display: inline-flex; align-items: center; justify-content: center; }
.by-adRefresh__ico { display: inline-block; line-height: 1; }

.by-adRefresh.is-spinning {
  color: var(--primary);
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
}

.by-adRefresh.is-spinning .by-adRefresh__ico {
  animation: by-refresh-spin 1s linear infinite;
}

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

/* ============================================================
   Выбор снятых объявлений «убрать из панели»
   ============================================================ */

.by-adOffBar { display: flex; gap: 6px; align-items: center; }
.by-adOffBar .by-ad__offToggle { flex: 1; }

.by-adPick {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 6px;
  border: 1px dashed color-mix(in srgb, var(--primary) 40%, var(--border));
  border-radius: var(--by-r);
  background: color-mix(in srgb, var(--primary) 7%, transparent);
  animation: by-pick-in .2s cubic-bezier(.4, 0, .2, 1);
}

@keyframes by-pick-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

.by-adPick__count {
  flex: 1;
  font-size: 10px;
  color: var(--by-mut);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.by-adPick__btn {
  font: inherit;
  font-size: 12px;
  line-height: 1;
  height: 24px;
  min-width: 24px;
  padding: 0 7px;
  color: var(--by-mut);
  background: var(--by-panel2);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  flex-shrink: 0;
  transition: color .15s ease, background .15s ease, border-color .15s ease, transform .12s ease;
}

.by-adPick__btn:hover { color: var(--text); background: var(--by-panel3); }
.by-adPick__btn:active { transform: scale(.94); }

.by-adPick__btn--ok {
  color: var(--primary);
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
}

.by-adPick__btn--ok.is-confirm {
  color: #e5484d;
  border-color: color-mix(in srgb, #e5484d 55%, var(--border));
  background: color-mix(in srgb, #e5484d 12%, transparent);
  font-size: 10.5px;
  animation: by-confirm-pulse 1.6s ease-in-out infinite;
}

@keyframes by-confirm-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, #e5484d 35%, transparent); }
  50%      { box-shadow: 0 0 0 4px color-mix(in srgb, #e5484d 0%, transparent); }
}

/* «Выбрать все» — одна рисованная галка: системный символ выглядел чужеродно
   и менялся от шрифта к шрифту, а рамка вокруг только шумела. */
.by-adPick__btn--all { position: relative; }

.by-adPick__btn--all::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 46%;
  width: 6px;
  height: 11px;
  margin: -7px 0 0 -3px;
  border: solid currentColor;
  border-width: 0 2.2px 2.2px 0;
  border-radius: 1px;
  transform: rotate(45deg);
}

.by-adPick__btn--all:hover { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }

.by-adPick__btn--trash:hover {
  color: #e5484d;
  border-color: color-mix(in srgb, #e5484d 45%, var(--border));
}

/* Карточка в режиме выбора */
.by-ad.is-picking {
  cursor: pointer;
  transition: border-color .18s ease, background .18s ease, transform .12s ease;
}

.by-ad.is-picking:hover { border-color: color-mix(in srgb, var(--primary) 35%, var(--border)); }
.by-ad.is-picking:active { transform: scale(.99); }

.by-ad.is-picked {
  border-color: color-mix(in srgb, var(--primary) 55%, var(--border));
  background: color-mix(in srgb, var(--primary) 9%, var(--by-panel));
}

.by-adPick__box {
  accent-color: var(--primary);
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  cursor: pointer;
  animation: by-tag-in .18s cubic-bezier(.4, 0, .2, 1);
}

/* В режиме выбора действия внутри карточки не мешают отмечать */
.by-ad.is-picking .by-adToggle,
.by-ad.is-picking .by-ad__price,
.by-ad.is-picking .by-ad__limits,
.by-ad.is-picking .by-ad__priv,
.by-ad.is-picking .by-ad__linkIcon { pointer-events: none; opacity: .6; }

/* ============================================================
   Оповещения о событиях: колокольчик, настройки, всплывашки
   ============================================================ */

/* Кнопка оповещений переехала в боковое меню оболочки — её стили теперь в
   css/ui/notify-center.css. Панель микшера (.nmx ниже) осталась здесь: она
   принадлежит разделу, а окно ей даёт центр оповещений. */

/* ============================================================
   Микшер оповещений: профили, строки событий, подвал
   ============================================================ */

.nmx {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  width: 420px;
  padding: 12px;
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: 14px;
  /* Плотный фон: сквозь полупрозрачный просвечивал стакан и всё сливалось. */
  /* Непрозрачная основа + наша плёнка сверху: --by-panel сам по себе почти
     прозрачный (4% текста), он рассчитан на наложение поверх фона страницы,
     и для всплывающей панели его не хватало — сквозь неё просвечивал список. */
  background: linear-gradient(var(--by-panel), var(--by-panel)), var(--page-bg);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .6);
  color: var(--text);
  font-variant-numeric: tabular-nums;
  animation: by-cfg-in .18s cubic-bezier(.4, 0, .2, 1);
}

.nmx[hidden] { display: none; }
.nmx *, .nmx *::before, .nmx *::after { box-sizing: border-box; }
.nmx button { font: inherit; }
.nmx :focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* Профили — единый сегмент на подложке: сразу видно, что выбор один из трёх */
.nmx-top {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
}

.nmx-seg {
  display: flex;
  flex: 1;
  min-width: 0;
  gap: 3px;
  padding: 3px;
  background: var(--by-panel2);
  border-radius: 10px;
}

/* Показать примеры оповещений — рядом с профилями, чтобы не занимать подвал */
.nmx-demo {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  padding: 0;
  color: var(--by-mut);
  background: var(--by-panel2);
  border: 0;
  border-radius: 9px;
  cursor: pointer;
  transition: color .14s ease, background .14s ease;
}

.nmx-demo:hover { color: var(--primary); background: var(--by-panel3); }
.nmx-demo svg { width: 15px; height: 15px; }

.nmx-seg button {
  flex: 1;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 0 8px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--by-mut);
  font-size: 11px;
  white-space: nowrap;
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
}

.nmx-seg button:hover { color: var(--text); }

/* Выбранный профиль въезжает заливкой, а не появляется скачком: переключение
   меняет поведение половины списка, и переход должен быть виден. */
.nmx-seg button[aria-pressed="true"] {
  background: var(--primary);
  color: #06240f;
  font-weight: 600;
  animation: nmx-segPick .24s cubic-bezier(.2, .9, .3, 1.2);
}

@keyframes nmx-segPick {
  0%   { transform: scale(.94); }
  60%  { transform: scale(1.03); }
  100% { transform: scale(1); }
}

.nmx-ico { width: 15px; height: 15px; flex: none; }
.nmx-seg svg { width: 14px; height: 14px; flex: none; }

/* Заголовок группы */
.nmx-group {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 12px 2px 4px;
}

.nmx-group span {
  font-size: 10px;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--by-mut2, var(--by-mut));
  white-space: nowrap;
}

.nmx-group i { flex: 1; height: 1px; background: var(--border); }

/* Строка события: жёсткие колонки, чтобы 100% не толкало соседей */
.nmx-row {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) 104px 38px 26px 30px;
  align-items: center;
  gap: 9px;
  padding: 6px;
  border-radius: 10px;
  transition: background .14s ease, opacity .14s ease;
}

.nmx-row:hover { background: var(--by-panel3); }

/* Выключенное действительно выключено: не только бледнеет, но и не нажимается */
/* Приглушаем ТОЛЬКО звуковую часть строки: значок, подпись, ползунок и
   прослушивание. Тумблер отвечает за показ оповещения, а не за звук, и в
   «тишине» остаётся ярким — иначе профиль читался бы как «оповещений не
   будет вовсе». Гасить строку целиком (как было) нельзя ещё и потому, что
   прозрачность родителя не отменить прозрачностью ребёнка. */
.nmx-row[data-live="false"] .nmx-badge,
.nmx-row[data-live="false"] .nmx-text,
.nmx-row[data-live="false"] .nmx-range,
.nmx-row[data-live="false"] .nmx-val,
.nmx-row[data-live="false"] .nmx-play { opacity: .42; }

/* Запертое событие (автоматика) не гаснет никогда: выключить его нельзя, и
   выглядеть выключаемым оно не должно. */
.nmx-row[data-locked="true"] .nmx-switch { cursor: default; }

/* Подпись под профилями: что делает ползунок, а что тумблер. */
.nmx-legend {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin: 2px 2px 6px;
  font-size: 9.5px;
  line-height: 1.3;
  color: var(--by-mut2);
}

.nmx-badge {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9px;
  background: var(--by-panel2);
  color: var(--primary);
  transition: background .16s ease, color .16s ease;
}

.nmx-badge svg { width: 16px; height: 16px; }

.nmx-text { min-width: 0; }

.nmx-name,
.nmx-sub {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nmx-name { font-size: 11.5px; }
.nmx-sub { font-size: 10px; color: var(--by-mut); margin-top: 1px; }

.nmx-range {
  width: 100%;
  height: 18px;
  margin: 0;
  background: transparent;
  accent-color: var(--primary);
  cursor: pointer;
}

.nmx-range:disabled { cursor: default; }

.nmx-val {
  font-size: 11px;
  color: var(--by-mut);
  text-align: right;
}

.nmx-play {
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--by-mut);
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
}

.nmx-play:hover:not(:disabled) { background: var(--by-panel2); color: var(--primary); }
.nmx-play:disabled { cursor: default; }
.nmx-play svg { width: 14px; height: 14px; }

.nmx-switch {
  position: relative;
  width: 30px;
  height: 17px;
  padding: 0;
  border: 0;
  border-radius: 9px;
  background: var(--by-panel3);
  cursor: pointer;
  transition: background .16s cubic-bezier(.4, 0, .2, 1);
}

.nmx-switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--by-mut);
  transition: left .16s cubic-bezier(.4, 0, .2, 1), background .16s ease;
}

.nmx-switch[aria-checked="true"] { background: color-mix(in srgb, var(--primary) 35%, var(--by-panel3)); }
.nmx-switch[aria-checked="true"]::after { left: 16px; background: var(--primary); }

/* Пока тревога звонит — её строка светится: видно, что именно повторяется */
.nmx-row[data-ringing="true"] .nmx-badge {
  background: var(--primary);
  color: #06240f;
  animation: by-ring 1.2s ease-in-out infinite;
}

@keyframes by-ring {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 45%, transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--primary) 0%, transparent); }
}

/* prefers-reduced-motion гасит только украшения. Переходы строк оставляем: они
   не декорация, а объяснение — по ним видно, что профиль погасил часть событий,
   а не что панель сломалась. Ровно та же причина, по которой не выключается
   индикатор загрузки ордеров (см. выше). */
@media (prefers-reduced-motion: reduce) {
  .nmx { animation: none !important; }
  .nmx-row[data-ringing="true"] .nmx-badge { animation: none !important; }
}

/* Строка, приглушённая профилем: тускнеет плавно и заметно — переключение
   профиля должно читаться как действие, а не как поломка. */
.nmx-row[data-live="false"] .nmx-badge,
.nmx-row[data-live="false"] .nmx-text,
.nmx-row[data-live="false"] .nmx-range,
.nmx-row[data-live="false"] .nmx-val,
.nmx-row[data-live="false"] .nmx-play {
  transition: opacity .22s ease, filter .22s ease;
}

/* Подпись профиля — словами о том, что он делает. */
.nmx-profileHint {
  margin: 0 2px 8px;
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--by-mut2);
  min-height: 15px;
}

/* Всплывающие карточки — снизу справа, поверх всего */
.by-notifyHost {
  /* Токены раздела объявлены на .bybit-page, а контейнер висит в <body> —
     без этой строки фон карточек становился невалидным и просвечивал. */
  --by-panel: color-mix(in srgb, var(--text) 4%, transparent);
  --by-panel3: color-mix(in srgb, var(--text) 11%, transparent);
  --by-mut: var(--muted);
  --by-mut2: color-mix(in srgb, var(--text) 45%, transparent);
  --by-txt: var(--text);
  --by-unread: #2f81f7;

  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 100000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}

.by-notify {
  pointer-events: auto;
  width: 260px;
  padding: 10px 12px;
  border-radius: 12px;
  border: 1px solid var(--border);
  /* Сплошная основа + плёнка: сквозь карточку ничего не просвечивает. */
  background: linear-gradient(var(--by-panel), var(--by-panel)), var(--page-bg);
  box-shadow: 0 16px 38px rgba(0, 0, 0, .6);
  animation: by-notify-in .26s cubic-bezier(.34, 1.4, .64, 1);
}

@keyframes by-notify-in {
  from { opacity: 0; transform: translateX(24px) scale(.96); }
  to   { opacity: 1; transform: none; }
}

.by-notify.is-leaving {
  animation: by-notify-out .22s cubic-bezier(.4, 0, .2, 1) forwards;
}

@keyframes by-notify-out {
  to { opacity: 0; transform: translateX(24px) scale(.97); }
}

.by-notify { position: relative; }

.by-notify__close {
  position: absolute;
  top: 6px;
  right: 7px;
  width: 18px;
  height: 18px;
  padding: 0;
  font-size: 14px;
  line-height: 1;
  color: var(--by-mut);
  background: none;
  border: 0;
  border-radius: 5px;
  cursor: pointer;
  opacity: 0;
  transition: opacity .14s ease, color .14s ease, background .14s ease;
}

.by-notify:hover .by-notify__close { opacity: 1; }
.by-notify__close:hover { color: var(--text); background: var(--by-panel3); }

/* Демонстрационные карточки помечены и висят до закрытия */
.by-notify--demo .by-notify__close { opacity: .7; }

.by-notify__tag {
  position: absolute;
  top: 8px;
  right: 30px;
  font-size: 8.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--by-mut2, var(--by-mut));
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 6px;
  line-height: 14px;
}

.by-notify__title { font-size: 12px; font-weight: 700; margin-bottom: 2px; padding-right: 58px; }
.by-notify__text { font-size: 11px; color: var(--by-mut); line-height: 1.35; }
.by-notify--clickable { cursor: pointer; }
.by-notify--clickable:hover { border-color: color-mix(in srgb, var(--primary) 40%, var(--border)); }

/* Тревожные события (отмена, апелляция) — красной полосой слева */
.by-notify--alert {
  border-left: 3px solid #e5484d;
}

.by-notify--alert .by-notify__title { color: #e5484d; }

/* Обычные — зелёной */
.by-notify--info { border-left: 3px solid var(--primary); }

/* ============================================================
   Создание объявления: кнопка под списком и раскрывающаяся форма
   ============================================================ */

.by-adCreate {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  margin: 8px;
  height: 32px;
  flex-shrink: 0;
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--primary);
  background: color-mix(in srgb, var(--primary) 10%, transparent);
  border: 1px dashed color-mix(in srgb, var(--primary) 45%, var(--border));
  border-radius: var(--by-r);
  cursor: pointer;
  transition: background .16s ease, border-color .16s ease, color .16s ease;
}

.by-adCreate:hover {
  background: color-mix(in srgb, var(--primary) 18%, transparent);
  border-style: solid;
}

.by-adCreate__plus {
  font-size: 15px;
  line-height: 1;
  transition: transform .22s cubic-bezier(.4, 0, .2, 1);
}

/* Открытая форма — плюс становится крестиком поворотом */
.by-adCreate.is-open .by-adCreate__plus { transform: rotate(45deg); }

.by-adNew {
  margin: 0 8px 8px;
  padding: 9px;
  flex-shrink: 0;
  max-height: 46vh;
  overflow-y: auto;
  border: 1px solid color-mix(in srgb, var(--primary) 30%, var(--border));
  border-radius: var(--by-r);
  background: var(--by-panel2);
  animation: by-new-in .24s cubic-bezier(.4, 0, .2, 1);
}

.by-adNew[hidden] { display: none; }

@keyframes by-new-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.by-adNew__inner { display: flex; flex-direction: column; gap: 4px; }

/* Пара полей в строку: монета+фиат, мин+макс */
.by-adNew__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.by-adNew__pair .by-input { width: 100%; }

/* Переключатели направления и типа цены — тем же сегментом, что у профилей */
.by-adNew__seg {
  display: flex;
  gap: 3px;
  padding: 3px;
  background: var(--by-panel3);
  border-radius: 9px;
}

.by-adNew__segBtn {
  flex: 1;
  height: 26px;
  font: inherit;
  font-size: 11px;
  color: var(--by-mut);
  background: transparent;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
}

.by-adNew__segBtn:hover { color: var(--text); }

.by-adNew__segBtn.is-active {
  background: var(--primary);
  color: #06240f;
  font-weight: 600;
}

/* Продажа выделяется красным: перепутать сторону — дорого */
.by-adNew__segBtn[data-side="1"].is-active { background: var(--by-sell); color: #fff; }

/* Поля формы создания: высоту задаём явно — без этого они наследовали
   размеры textarea и растягивались на пол-экрана. */
.by-adNew .by-input--sm,
.by-adNew select.by-input {
  height: 28px;
  min-height: 28px;
  line-height: 28px;
  padding: 0 8px;
}

.by-adNew .by-ad__remark {
  height: auto;
  min-height: 42px;
  line-height: 1.35;
  padding: 6px 8px;
}

.by-adNew .by-ad__editLabel {
  margin-top: 2px;
  flex-basis: auto;
}

/* Обязательные незаполненные поля видно сразу: заливка и рамка вместо
   бледной подсказки, которую легко пропустить. */
.by-adNew__req {
  background: color-mix(in srgb, var(--by-amber) 10%, var(--by-panel2));
  border-color: color-mix(in srgb, var(--by-amber) 40%, var(--border));
}

.by-adNew__req::placeholder { color: color-mix(in srgb, var(--by-amber) 55%, transparent); }

/* Заполнили — подсветка гаснет: :not(:placeholder-shown) срабатывает, как
   только в поле появился текст. */
.by-adNew__req:not(:placeholder-shown) {
  background: var(--by-panel2);
  border-color: var(--border);
}

.by-adNew__req:not(:placeholder-shown):focus {
  border-color: color-mix(in srgb, var(--primary) 55%, var(--border));
}

/* Требования к контрагенту внутри формы создания — без верхней черты:
   она отделяла бы блок от «Способов оплаты» лишней линией. */
.by-adNew .by-prefs { border-top: 0; padding-top: 2px; }


/* Чат, раскрытый под строкой ордера (js/pages/bybit/orderChat.js). */
/* ---------- что прячется, когда колонка узкая ----------
   Панель объявлений раскрыта — колонка становится вдвое уже, и раньше
   схлопывался как раз ник, самое нужное. Убираем по одному и в понятном
   порядке: сначала подсказка и метка аккаунта, потом курс. */

@container (max-width: 470px) {
  .by-histAcc { display: none; }
  .by-ordMeta__acc { display: none; }
  .by-ordAct__acc { display: none; }
  .by-ordStatus__full { display: none; }
  .by-ordStatus__short { display: inline; }

  /* Три колонки, как у базовой строки: ужимается только статус. Реликтовая
     четырёхколоночная сетка (84px 80px …) заталкивала весь средний блок в
     бывшую колонку суммы шириной 80px — ник исчезал, номер резался, «Чат»
     прилипал к курсу (скриншоты владельца, 17.08.2026). */
  .by-ordRow { grid-template-columns: 84px minmax(0, 1fr) auto; }
  .by-ordRow--hist { grid-template-columns: 32px 76px 40px minmax(0, 1fr) auto; }
  .by-ordTab { padding: 4px 6px; font-size: 10.5px; }
}

@container (max-width: 360px) {
  .by-histRate { display: none; }
  .by-ordMeta__rate { display: none; }
  /* Курс спрятался — его точка-разделитель у ника больше не нужна. */
  .by-ordMeta__cp::before { content: none; }
  .by-ordAct__sum { font-size: 15px; }

  .by-ordRow--hist { grid-template-columns: 32px 72px minmax(0, 1fr) auto; }
  .by-ordRow { grid-template-columns: 84px minmax(0, 1fr) auto; }
  /* Правило «мета на всю ширину» умерло вместе с колонкой меты: она теперь
     внутри флекс-блока .by-ordMid, grid-column там не работает. */
}

/* ---------- чат под строкой ---------- */
.by-ordChat[hidden] { display: none; }

.by-icBody {
  border-top: 1px solid var(--border);
  animation: by-ic-open .3s cubic-bezier(.4, 0, .2, 1);
}

@keyframes by-ic-open {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

.by-icReqs {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--by-panel2);
}

.by-icReqs__label {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--by-mut2);
}

.by-icReqs__empty { font-size: 11px; color: var(--by-mut2); }

/* Состояния проверок подморожены: показаны прошлые, а выглядят как свежие.
   Янтарным, а не приглушённым: это не подпись, а оговорка про деньги. */
.by-icReqs__stale { font-size: 11px; color: var(--by-amber); }

/* Несвежесть переписки в панели под строкой: связь потеряна или биржа не
   отдаёт деталь. Тем же янтарным и тем же смыслом, что у оговорки выше:
   старая лента, показанная как свежая, — разговор про деньги. Своего display
   нет намеренно — атрибут hidden обязан прятать узел сам. */
.by-icStale { font-size: 11px; color: var(--by-amber); padding: 4px 10px 0; }

.by-icReq {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 9px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  background: var(--by-panel3);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: border-color .15s ease;
}

.by-icReq:hover { border-color: var(--by-mut2); }
.by-icReq__meta { font-size: 10.5px; font-weight: 400; color: var(--by-mut2); }
.by-icReq.is-copied { border-color: var(--by-acc); }
.by-icReq.is-mine { opacity: .75; }

/* Контрольная сумма не сошлась — платить по такому номеру нельзя. */
.by-icReq.is-doubt {
  color: var(--by-sell);
  border-color: color-mix(in srgb, var(--by-sell) 45%, transparent);
  background: color-mix(in srgb, var(--by-sell) 10%, transparent);
}

.by-icReq.is-doubt .by-icReq__meta { color: var(--by-sell); }

.by-icReqAdd__input {
  width: 110px;
  padding: 4px 9px;
  font: inherit;
  font-size: 12px;
  color: var(--text);
  background: var(--by-panel3);
  border: 1px dashed var(--border);
  border-radius: 6px;
}

.by-icReqAdd__input:focus { outline: none; border-style: solid; border-color: var(--by-acc); }

.by-icFeed {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* 300px было мало: одна картинка занимала почти всё поле (доклад владельца
     19.08.2026). Полторы прежних высоты — переписка читается без прокрутки. */
  height: 450px;
  overflow-y: auto;
  padding: 12px;
}

.by-icForm {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
}

.by-icAttach {
  font-size: 15px;
  line-height: 1;
  padding: 2px 4px;
  background: none;
  border: none;
  color: var(--by-mut);
  cursor: pointer;
}

.by-icAttach:hover { color: var(--text); }

.by-icInput {
  display: block;
  flex: 1;
  min-width: 0;
  max-height: 40vh;
  padding: 8px 12px;
  resize: none;
  overflow-y: hidden;
  font: inherit;
  font-size: 13px;
  /* См. .by-chatInput: line-height только после шортката font. */
  line-height: 1.35;
  color: var(--text);
  background: var(--by-panel2);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.by-icInput:focus { outline: none; border-color: color-mix(in srgb, var(--primary) 55%, var(--border)); }
.by-icCount { font-size: 10px; color: var(--by-mut2); font-variant-numeric: tabular-nums; }

/* Тот же значок, что и в карточке: действие одно, и выглядеть оно обязано
   одинаково в обоих местах. Размер свой — здесь строка крупнее. */
.by-icSend {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 35px;
  height: 35px;
  padding: 0;
  background: color-mix(in srgb, var(--by-acc) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--by-acc) 45%, transparent);
  border-radius: 8px;
  cursor: pointer;
  transition: background-color .13s ease, border-color .13s ease, transform .09s ease;
}

.by-icSend .by-send__ico { width: 19px; height: 19px; }

.by-icSend:hover {
  background: color-mix(in srgb, var(--by-acc) 30%, transparent);
  border-color: var(--by-acc);
}

.by-icSend:active { transform: scale(.95); }

/* Подсветка сообщения при переходе из реквизита. 2.2 с — владелец попросил
   держать на секунду дольше прежнего (17.08.2026); тайм-ауты снятия класса в
   окно ордера и orderChat должны быть НЕ короче этой длительности. */
.by-msg.is-flash { animation: by-msg-flash 2.2s ease-out; }

@keyframes by-msg-flash {
  0%, 40% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--by-acc) 60%, transparent); }
  100%    { box-shadow: 0 0 0 0 transparent; }
}

/* ---------- история: дни, компактные строки, фильтры ---------- */

@media (prefers-reduced-motion: reduce) {
  .by-icBody { animation: none; }
  .by-msg.is-flash { animation: none; }
}

/* ============================================================
   ИСТОРИЯ СДЕЛОК С КОНТРАГЕНТОМ (19.08.2026)
   Виджет в колонке контрагента карточки ордера + окно полной истории
   поверх карточки + вторая карточка поверх окна.
   ============================================================ */

/* ---------- строка сделки в окне истории контрагента ---------- */

.by-cpHistRow {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  padding: 4px 7px;
  font: inherit;
  font-size: 10.5px;
  color: var(--by-txt);
  text-align: left;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  background: transparent;
}
.by-cpHistRow.is-buy  { background: color-mix(in srgb, var(--by-acc) 5%, transparent); }
.by-cpHistRow.is-sell { background: color-mix(in srgb, var(--by-sell) 5%, transparent); }
/* Отменённые — серые: цветная подложка стороны читалась как «состоявшаяся
   сделка», и отмены сливались с завершёнными (владелец, 19.08.2026).
   Маркер B/S остаётся цветным, сумма приглушается. */
.by-cpHistRow.is-cancelled,
.by-cpHistRow.is-sell.is-cancelled,
.by-cpHistRow.is-buy.is-cancelled { background: color-mix(in srgb, var(--by-txt) 5%, transparent); }
.by-cpHistRow.is-cancelled .by-cpHistRow__amount { color: var(--by-mut); }
.by-cpHistRow:hover { outline: 1px solid color-mix(in srgb, var(--by-acc) 40%, transparent); }

.by-cpHistRow__side {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  display: grid;
  place-items: center;
  border-radius: 5px;
  font-size: 9px;
  font-weight: 800;
}
.by-cpHistRow.is-buy  .by-cpHistRow__side { color: var(--by-acc);  background: color-mix(in srgb, var(--by-acc) 18%, transparent); }
.by-cpHistRow.is-sell .by-cpHistRow__side { color: var(--by-sell); background: color-mix(in srgb, var(--by-sell) 18%, transparent); }

.by-cpHistRow__date { color: var(--by-mut2); }
.by-cpHistRow__amount { font-weight: 800; }
.by-cpHistRow__rate { color: var(--by-mut2); }
.by-cpHistRow__appeal { color: #a855f7; font-size: 11px; }

/* Наш аккаунт в сделке (окно полной истории; в мини-списке карточки подпись
   не включается — там 358 px на строку). Растягивается САМ и тем съедает
   пустоту между курсом и статусом: второго `margin-left: auto` рядом с
   `__status` быть не должно — две авто-margin делят свободное место пополам,
   и подпись повисает в середине строки вместо своей колонки.
   `min-width: 0` здесь разрешает сжатие самой подписи; одного этого мало —
   строку тоже приходится отпускать, см. `.by-cpwin .by-cpHistRow` ниже. */
.by-cpHistRow__acc {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  overflow: hidden;
  color: var(--by-mut2);
}
/* Режется ИМЯ, а не код команды: имя бывает длинным логином, код — от одной
   до пяти букв, и обрезанный наполовину значок команды читается как сбой
   вёрстки. Поэтому подпись — свой флекс, а не один текстовый узел. */
.by-cpHistRow__accName {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.by-cpHistRow__team {
  flex: none;
  padding: 1px 4px;
  border-radius: 4px;
  font-size: 9px;
  font-weight: 700;
  color: var(--by-mut);
  background: color-mix(in srgb, var(--by-txt) 8%, transparent);
}
.by-cpHistRow__status { margin-left: auto; flex: 0 0 auto; font-size: 10px; font-weight: 600; }

/* Колонка перед подписью аккаунта выравнивается ТОЛЬКО в окне: пока после
   курса не стояло ничего, разная ширина сумм («3 000 ₽» против «12 000 ₽»)
   была не видна, а теперь она сдвигает начало подписи от строки к строке.
   Ширины заданы под окно (560 px) и в мини-список карточки не лезут — там
   358 px, и отобранные под запас пиксели пришлось бы отнять у суммы. */
.by-cpwin .by-cpHistRow__amount { min-width: 62px; }
.by-cpwin .by-cpHistRow__rate { min-width: 38px; }

/* `min-width: 0` строке — не украшение, а условие, при котором работает
   многоточие у подписи. Лента окна — GRID, а у грид-ребёнка автоматический
   минимум равен его min-content: `min-width: 0` внутри самой подписи строку
   не спасает, она всё равно не имеет права стать уже своего содержимого.
   Замерено: логин в 42 знака растягивал строку до 532 px в ленте шириной
   509 — вместо обрезки появлялась горизонтальная прокрутка, а статус уезжал
   за край. */
.by-cpwin .by-cpHistRow { min-width: 0; }

.by-cpHistRow.is-denied { opacity: 0.55; cursor: default; }
.by-cpHistRow.is-denied:hover { outline: none; }
/* Открытый сейчас ордер подсвечен: оператор сразу видит, откуда пришёл. */
.by-cpHistRow.is-current {
  cursor: default;
  outline: 1px solid color-mix(in srgb, var(--by-acc) 55%, transparent);
  background: color-mix(in srgb, var(--by-acc) 12%, transparent) !important;
}
.by-cpHistRow.is-current .by-cpHistRow__date { color: var(--by-txt); }
.by-cpHistRow.is-deniedFlash { animation: by-cpDeny 0.3s ease; }

@keyframes by-cpDeny {
  0%, 100% { transform: translateX(0); }
  30% { transform: translateX(-3px); }
  60% { transform: translateX(3px); }
}

/* ---------- окно полной истории поверх карточки ---------- */

/* Этаж слоя. Рабочий z ставит layers.js инлайном (растёт с глубиной стека);
   здесь — страховочное значение. Над сайдбаром (z 10000), под просмотрщиком и
   тостами (z 100000). ВАЖНО: <select> внутри этих слоёв не работает — портал
   меню customSelect живёт на z 90. */
.by-cpwin {
  position: fixed;
  inset: 0;
  z-index: 10030;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
}

.by-cpwin__panel {
  width: min(560px, calc(100vw - 48px));
  max-height: 82vh;
  display: flex;
  flex-direction: column;
  /* Фон тем же токеном, что у карточки ордера: var(--bg) в проекте не
     существует, и панель стояла прозрачной (доклад владельца 19.08.2026). */
  background: var(--page-bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.by-cpwin__head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--by-border2);
  font-size: 12.5px;
}
/* Заголовок растягивается — кнопки справа при любом их составе. */
.by-cpwin__title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.by-cpwin__xh {
  padding: 4px 9px;
  font: inherit;
  font-size: 10.5px;
  color: var(--by-txt);
  background: var(--by-panel2);
  border: 1px solid var(--by-border2);
  border-radius: 7px;
  cursor: pointer;
  white-space: nowrap;
}
.by-cpwin__xh:hover { border-color: var(--by-acc); color: var(--by-acc); }

.by-cpwin__stats {
  padding: 8px 12px;
  border-bottom: 1px solid var(--by-border2);
  display: grid;
  gap: 3px;
}

.by-cpwin__list {
  overflow-y: auto;
  min-height: 0;
  display: grid;
  gap: 2px;
  padding: 6px;
  scrollbar-width: thin;
}

.by-cpwin__foot {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px 9px;
  border-top: 1px solid var(--by-border2);
}
.by-cpwin__more {
  padding: 4px 10px;
  font: inherit;
  font-size: 10.5px;
  color: var(--by-txt);
  background: var(--by-panel2);
  border: 1px solid var(--by-border2);
  border-radius: 7px;
  cursor: pointer;
}
.by-cpwin__more:hover { border-color: var(--by-acc); }
.by-cpwin__legend { margin-left: auto; font-size: 9.5px; color: var(--by-mut2); }



/* =========================================================
   Авто-TOP1 — переключатель удержания первого места в стакане.
   Только иконка, без подписи: кнопка стоит в строке курса, где
   каждый лишний символ отнимает место у самого курса.

   Язык у неё тот же, что у булавки рядом (.by-adPin): 22 пикселя, без рамки
   и без подложки в покое. Прежний вариант — квадрат 28×28 с рамкой, заливкой
   и светящимся кольцом — был единственным «тяжёлым» элементом карточки и
   перетягивал взгляд с курса, ради которого карточка и заведена.

   Цвета — ТОКЕНЫ РАЗДЕЛА, а не свои значения. Стояли #639922 и #ba7517:
   оливковый и коричневый, которых на странице больше нет нигде, — оттого
   кнопка и читалась как чужая. Работает — акцент раздела (--by-acc), упёрлись
   в предел — янтарь (--by-amber), тот же, которым раздел уже говорит
   «внимание». Тема здесь ни при чём: оба токена живут в обеих, и своих
   тёмных правил у кнопки больше нет — их не было ни у одного соседа.

   Пульсации нет. Она мигала прозрачностью раз в 1,6 секунды, и «мигать»
   значило ровно то же, что уже сказано цветом: зелёная — работает, янтарная —
   ждёт у потолка. Запрет на вспышки в интерфейсе (решение владельца
   19.08.2026) в силе, а движение здесь ничего не добавляло к смыслу.
   ========================================================= */
.by-top1 {
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  color: var(--by-mut2);
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  opacity: .55;
  transition: color .13s ease, background .13s ease, opacity .13s ease;
}

.by-top1 svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.by-top1:hover {
  opacity: 1;
  color: var(--by-txt);
  background: color-mix(in srgb, var(--text) 9%, transparent);
}

/* Включено: механизм держит курс. */
.by-top1.is-on {
  opacity: 1;
  color: var(--by-acc);
  background: color-mix(in srgb, var(--by-acc) 14%, transparent);
}

.by-top1.is-on:hover {
  color: var(--by-acc);
  background: color-mix(in srgb, var(--by-acc) 24%, transparent);
}

/* Режим включён, но цена упёрлась в предел: механизм ждёт, а не работает. */
.by-top1.is-stopped {
  opacity: 1;
  color: var(--by-amber);
  background: color-mix(in srgb, var(--by-amber) 16%, transparent);
}

.by-top1.is-stopped:hover {
  color: var(--by-amber);
  background: color-mix(in srgb, var(--by-amber) 26%, transparent);
}

/* Место в стакане: объявление ушло в отрезанную часть книги.

   Ниже янтарного по файлу намеренно — при равной специфичности выигрывает
   порядок, а «нас не видно» важнее, чем «упёрлись в предел»: второе про
   недополученную выгоду, первое про отсутствие сделок вовсе.

   Цвет — токен раздела --by-sell, тот же, которым горит тревога у вкладки
   ордеров. Своего хекса здесь не заводим: он читался бы как чужой, ровно как
   читались оливковый и коричневый до правки 27.08.2026. */
.by-top1.is-sunk,
.by-top1.is-stuck {
  opacity: 1;
  color: var(--by-sell);
  background: color-mix(in srgb, var(--by-sell) 16%, transparent);
}

.by-top1.is-sunk:hover,
.by-top1.is-stuck:hover {
  color: var(--by-sell);
  background: color-mix(in srgb, var(--by-sell) 26%, transparent);
}

/* Механизм сдался и выключил режим: та же беда, но чинить её теперь человеку.
   Отличаем рамкой, а не вторым цветом и не миганием — вспышки в интерфейсе
   запрещены (решение владельца 19.08.2026), а второй красный рядом с первым
   различался бы только на память. */
.by-top1.is-stuck {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--by-sell) 55%, transparent);
}

.by-top1:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Правило проекта: mobile.css поднимает всем кнопкам min-height 40px ради
   тач-целей, и квадрат превратился бы в прямоугольник. Отбиваем адресно
   и ВНЕ media-запроса, где выигрывает специфичность, а не порядок файлов. */
.by-ad .by-top1 { min-height: 22px; }

/* ---------- предел цены TOP1: поле на месте кнопки ----------
   Разметка та же, что у правки курса (.by-adPrice), поэтому здесь только
   отличия. Число мельче и легче курса намеренно: в строке их теперь два, и
   спутать «сколько платим» с «дороже не платим» нельзя. Галочка видна сразу,
   а не по изменению: предел, равный текущему курсу, — законная настройка,
   и подтверждать её надо тем же нажатием, что и любую другую. */
/* Поле предела — ЧИП, а не текст в строке курса.

   До 28.08.2026 у него не было ни фона, ни рамки, и рядом с крупным курсом
   получалась каша: «83,92 RUB» и тут же мелкие ≤ 94 RUB ✓ вперемешку с
   остатком объявления — три разные величины подряд, ни одна не отделена от
   соседней. Своя подложка отделяет ОРГАН УПРАВЛЕНИЯ от чисел, среди которых
   он стоит; отступ слева — от самого курса, чтобы они не слипались. */
.by-adPrice--top1 {
  /* Не ужимаемся НИКОГДА: на узкой карточке чип сжимался первым, и число
     предела обрезалось до «102.» — поле ввода, в котором не видно, что вводишь.
     Уступать место обязан остаток объявления, это справка. */
  flex: 0 0 auto;
  gap: 4px;
  margin-left: 6px;
  padding: 2px 5px;
  height: 24px;
  font-size: 12px;
  font-weight: 600;
  color: var(--by-mut);
  background: var(--by-panel2);
  border: 1px solid color-mix(in srgb, var(--text) 14%, transparent);
  border-radius: 8px;
  /* Появление — ДВИЖЕНИЕ от кнопки, на месте которой чип возник, а не вспышка:
     мигание прозрачностью в интерфейсе запрещено (решение владельца
     19.08.2026), направленное раскрытие показывает, ОТКУДА взялось поле. */
  transform-origin: left center;
  animation: by-top1-open .16s cubic-bezier(.2, .7, .3, 1);
}

@keyframes by-top1-open {
  from { opacity: 0; transform: translateX(-5px) scaleX(.9); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .by-adPrice--top1 { animation: none; }
}

/* Тонкая черта отделяет НАСТРОЙКУ (проверять ли место) от ЗНАЧЕНИЯ (предел
   цены). Без неё круговая стрелка и «≤ 94» читались одной группой, и тумблер
   выглядел частью числа. */
.by-adPrice--top1 .by-adPrice__rev {
  padding-right: 5px;
  margin-right: 1px;
  width: 23px;
  border-right: 1px solid color-mix(in srgb, var(--text) 14%, transparent);
  border-radius: 5px 0 0 5px;
}

/* Число внутри чипа — единственное, что читается как значение. Табличные
   цифры, чтобы ширина поля не дёргалась при наборе. */
.by-adPrice--top1 .by-adPrice__input {
  flex: 0 0 auto;
  color: var(--by-txt);
  font-variant-numeric: tabular-nums;
}

/* Валюты в чипе НЕТ намеренно: она уже стоит в курсе слева, а предел всегда в
   ней же. Дубль съедал место, и при длинном пределе (102.55) строка курса
   ломалась на две — замерено на стенде 28.08.2026. */
.by-adPrice--top1 .by-adPrice__pre {
  color: var(--by-mut2);
  font-weight: 500;
}

/* Галочка — ЕДИНСТВЕННЫЙ акцент в чипе: она про действие, всё остальное про
   значение. Поэтому тумблер рядом живёт цветом без заливки (см. ниже), иначе
   два зелёных кружка спорили бы за внимание. */
.by-adPrice--top1 .by-adPrice__ok {
  display: grid;
  width: 18px;
  height: 18px;
}

.by-adPrice--top1 .by-adPrice__ok svg { width: 11px; height: 11px; }

/* ============================================================
   ЛЕНТА СОБЫТИЙ (02.09.2026)

   Узкая полоса под колонками ордеров: завершившиеся покупки и отменившиеся
   продажи по мере того, как они происходят. Разметка — html/bybit.html,
   поведение — js/pages/bybit/feed.js.

   Полоса живёт ВНУТРИ .by-ords (та уже flex-колонка), поэтому места у
   объявлений не отнимает и сеткой .by-work не управляет вовсе.
   ============================================================ */

.by-feed {
  /* Высота — единственное число раскладки, и оно здесь одно на оба состояния:
     свёрнутая полоса меняет только его. */
  --by-feed-h: 66px;
  --by-feed-card-w: 178px;

  flex: 0 0 auto;
  height: var(--by-feed-h);
  display: flex;
  align-items: stretch;
  min-width: 0;
  overflow: hidden;
  background: var(--by-panel);
  border: 1px solid var(--by-border2);
  border-radius: var(--by-r);
  transition: height 0.18s ease;
}

.by-feed.is-collapsed { --by-feed-h: 26px; }

/* Ползунок и кнопка возврата лежат слоями поверх полосы. */
.by-feed { position: relative; }

/* ---------- ползунок положения ----------
   Своя полоска в 3 px, а не системный скроллбар: тот занимает место ВНУТРИ
   ленты и на узком экране отрезал карточке третью строку с ником и аккаунтом.
   Эта высоты не отнимает вовсе и заодно показывает, где мы в ленте. */
.by-feed__bar {
  position: absolute;
  left: 64px;
  right: 6px;
  bottom: 2px;
  height: 3px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--text) 8%, transparent);
  cursor: pointer;
  touch-action: none;
}

.by-feed__bar > i {
  position: absolute;
  top: -1px;
  height: 5px;
  min-width: 18px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--text) 30%, transparent);
  transition: background 0.15s ease;
}

.by-feed__bar:hover > i { background: color-mix(in srgb, var(--text) 46%, transparent); }

/* Лента в начале — ползунок прижат влево, и это сам по себе ответ на вопрос
   «увижу ли я новое событие»: свежее приходит слева. */
.by-feed.is-atStart .by-feed__bar > i { background: color-mix(in srgb, var(--by-acc) 55%, transparent); }

.by-feed.is-collapsed .by-feed__bar,
/* Свёрнутая полоса: ни ползунка, ни ручки — показывать нечего. */
.by-feed.is-collapsed .by-feed__bar,
.by-feed.is-collapsed .by-feed__back { display: none; }

/* ---------- дорога назад к свежим ----------
   Появляется, только когда лента отмотана И слева накопилось новое.

   Ручка ВПЛОТНУЮ к шапке и во всю высоту полосы, а не пилюля поверх ленты:
   пилюля ложилась на сумму первой карточки и читалась как значок на ней —
   проверено глазами на стенде 02.09.2026. Непрозрачная и с тенью вправо: так
   она выглядит продолжением шапки, а лента честно уходит под неё. */
.by-feed__back {
  min-height: 0;
  position: absolute;
  left: 59px;
  top: 1px;
  bottom: 1px;
  z-index: 2;
  width: 26px;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  border: 0;
  border-radius: 0 8px 8px 0;
  /* Фон НЕПРОЗРАЧНЫЙ: токены --by-panel* — это color-mix с прозрачностью, и
     сквозь ручку просвечивала сумма карточки (поймано глазами на стенде).
     Берём фон страницы, он сплошной в обеих темах. */
  background: var(--page-bg-2);
  border-right: 1px solid var(--by-border2);
  box-shadow: 7px 0 14px -6px rgb(0 0 0 / 0.55);
  color: var(--by-acc);
  cursor: pointer;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
}

.by-feed__back:hover { background: color-mix(in srgb, var(--by-acc) 16%, var(--page-bg-2)); }

.by-feed__backArrow { font-size: 15px; line-height: 1; }

.by-feed__backNum { font-variant-numeric: tabular-nums; }

/* Шапка — она же кнопка сворачивания. Плашка слева, а не строка сверху:
   строка сверху съела бы вторую высоту у полосы, ради узости которой всё и
   затевалось. */
.by-feed__head {
  /* mobile.css поднимает ВСЕМ button min-height до 40px ради тач-целей —
     здесь это разорвало бы полосу в 66px. Отбито адресно и ВНЕ media-запроса:
     выигрывает специфичность, а не порядок файлов. */
  min-height: 0;
  flex: 0 0 auto;
  width: 58px;
  padding: 0 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: var(--by-panel2);
  border: 0;
  border-right: 1px solid var(--by-border2);
  color: var(--by-mut);
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.09em;
  transition: color 0.15s ease, background 0.15s ease;
}

.by-feed__head:hover { color: var(--by-txt); }

.by-feed__bolt {
  font-size: 12px;
  line-height: 1;
  color: var(--by-amber);
}

/* Свёрнуто: те же элементы выстраиваются в строку, полоса карточек уходит.
   Название и счётчик остаются — по ним и разворачивают обратно. */
.by-feed.is-collapsed .by-feed__head {
  flex-direction: row;
  width: 100%;
  gap: 7px;
  justify-content: flex-start;
  border-right: 0;
  background: transparent;
}

.by-feed.is-collapsed .by-feed__strip { display: none; }

/* Сколько событий прошло, пока полоса свёрнута. Янтарный, а не зелёный: это
   «посмотри», а не «всё хорошо». */
.by-feed__new {
  padding: 0 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--by-amber) 22%, transparent);
  color: var(--by-amber);
  font-size: 9px;
  font-weight: 700;
  line-height: 14px;
}

/* Полоса карточек. Прокрутка вбок — колесом (обработчик в feed.js) и
   перетаскиванием полосы прокрутки; вертикальной у неё нет вовсе. */
.by-feed__strip {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: stretch;
  gap: 6px;
  padding: 6px;
  overflow-x: auto;
  overflow-y: hidden;
  /* Полосы прокрутки НЕТ намеренно. Классическая занимает 6-8 px ВНУТРИ полосы,
     и карточка (align-items: stretch) на столько же сжималась — на узком экране
     у неё отрезало третью строку с ником и аккаунтом. Ради шести пикселей
     наращивать высоту всей ленты незачем: листают её колесом (обработчик в
     feed.js) и пальцем, а о том, что лента продолжается, говорит затухание у
     края — и только когда продолжение действительно есть (.has-more). */
  scrollbar-width: none;
}

.by-feed__strip::-webkit-scrollbar { display: none; }

/* Затухание у края: лента продолжается за ним. Правил три, потому что края
   независимы — доехав до конца, правое затухание обязано погаснуть, иначе оно
   обещает события, которых нет. */
.by-feed__strip.has-more {
  mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent 100%);
}

.by-feed__strip.has-back {
  mask-image: linear-gradient(to right, transparent 0, #000 26px);
}

.by-feed__strip.has-back.has-more {
  mask-image: linear-gradient(to right, transparent 0, #000 26px, #000 calc(100% - 26px), transparent 100%);
}

.by-feed__empty {
  align-self: center;
  padding-left: 4px;
  color: var(--by-mut2);
  font-size: 11px;
}

/* ---------- карточка события ---------- */

.by-feedEv {
  /* Та же грабля тач-высоты, что у шапки: карточка — кнопка. */
  min-height: 0;
  flex: 0 0 auto;
  width: var(--by-feed-card-w);
  padding: 5px 8px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  text-align: left;
  background: var(--by-panel2);
  border: 1px solid transparent;
  border-radius: 8px;
  color: var(--by-txt);
  cursor: pointer;
  overflow: hidden;
  transition: background 0.15s ease, border-color 0.4s ease;
}

.by-feedEv:hover { background: var(--by-panel3); }

.by-feedEv__top,
.by-feedEv__mid {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  min-width: 0;
}

/* Сторона и исход — одной строкой и цветом исхода (решение владельца
   02.09.2026): сторона названа СЛОВОМ, а не только краской. */
.by-feedEv__kind {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.by-feedEv__kind.is-done { color: var(--by-buy); }
.by-feedEv__kind.is-cancel { color: var(--by-sell); }
/* «Сгорела» — янтарный, ПОДМЕШАННЫЙ основным текстом: чистый --by-amber на
   молочном фоне светлой темы даёт контраст около 1.9:1, а это подпись в 9 px.
   Подмешивание тема-агностично: в тёмной теме оно осветляет, в светлой
   затемняет, и правила под конкретную тему в разделе заводить не пришлось. */
.by-feedEv__kind.is-burn { color: color-mix(in srgb, var(--by-amber) 76%, var(--text)); }

.by-feedEv__time {
  flex: 0 0 auto;
  color: var(--by-mut2);
  font-size: 9px;
}

.by-feedEv__sum {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.by-feedEv__rate {
  flex: 0 0 auto;
  color: var(--by-mut2);
  font-size: 10px;
}

/* Ник и аккаунт — одной строкой: обрезаем ник, а не метку аккаунта, она
   короткая и отвечает на вопрос «где это случилось».
   Значок переписки стоит СПРАВА в этой же строке и не сжимается: обрезаться
   имеет право текст, а не цифра — она и есть повод открыть карточку. */
.by-feedEv__cp {
  display: flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  color: var(--by-mut);
  font-size: 10px;
  line-height: 1.2;
}

.by-feedEv__nick {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Неразобранная переписка — тем же синим и той же формой, что бейдж в кнопке
   «Чат» строки списка: смысл один, и разводить его двумя видами нельзя.
   Высота задана строкой, а не паддингом: пилюля не имеет права растянуть
   line-box карточки — она появляется на живой ленте, и карточка дёрнулась бы
   в момент появления. */
.by-feedEv__msg {
  flex: 0 0 auto;
  min-width: 15px;
  height: 13px;
  padding: 0 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--by-unread);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
}

/* Свежее событие держит цветную рамку 20 секунд (feed.js). Цвет — по исходу:
   зелёная рамка у отменённой продажи говорила бы обратное содержанию. */
.by-feedEv--done.is-fresh {
  border-color: color-mix(in srgb, var(--by-buy) 55%, transparent);
  background: color-mix(in srgb, var(--by-buy) 10%, var(--by-panel2));
}

.by-feedEv--cancel.is-fresh {
  border-color: color-mix(in srgb, var(--by-sell) 55%, transparent);
  background: color-mix(in srgb, var(--by-sell) 10%, var(--by-panel2));
}

/* Въезд слева: карточка раздвигает соседей, а не подменяет их рывком.
   Анимируется margin-right (не max-width): именно он двигает СОСЕДЕЙ, а
   ширина самой карточки при этом остаётся заданной — текст внутри не
   сжимается и не переносится на время анимации. */
@keyframes byFeedIn {
  from {
    opacity: 0;
    transform: translateX(-12px);
    margin-right: calc(-1 * (var(--by-feed-card-w) + 6px));
  }
  to {
    opacity: 1;
    transform: none;
    margin-right: 0;
  }
}

.by-feedEv.is-in { animation: byFeedIn 0.38s ease; }

/* Системная настройка «убрать анимацию» — уважаем: движение здесь украшение,
   а не носитель смысла (свежесть говорит рамкой). */
@media (prefers-reduced-motion: reduce) {
  .by-feedEv.is-in { animation: none; }
  .by-feed { transition: none; }
}
