/* Соя ДВ — интерфейс под телефон в поле: крупно, контрастно, без лишнего. */

/* Палитра снята с логотипа: зелень хохломского письма, охра бобов,
   червлёный красный и бумажный кремовый фон. */
:root {
  --ground: #f2f4f5;
  --surface: #ffffff;
  --surface-2: #eef1f2;
  --ink: #101418;
  --ink-2: #3c464f;
  --muted: #6d7780;
  --line: #e3e7ea;
  --line-soft: #eef1f3;

  /* Зелёный поля — действие. Всё, что нажимают, зелёное; больше ничего.
     --on-* это цвет текста ПОВЕРХ заливки: в тёмной теме заливка светлеет,
     и белые надписи на ней перестали бы читаться. */
  --ru: #1f9d3d;
  --ru-soft: #e2f5e6;
  --ru-ink: #14702b;
  --on-ru: #ffffff;

  /* Красный Китая — цена и китайская сторона. На 1688 цена именно красная,
     и китайскому закупщику так привычнее всего. */
  --cn: #d7261e;
  --cn-soft: #fde8e6;
  --cn-ink: #a81a13;
  --on-cn: #ffffff;

  /* Золото зерна — третий и последний цвет: им отмечают подтверждённое. */
  --gold: #f5b500;
  --gold-soft: #fff2cc;

  /* Переписка: своё сообщение сплошной зеленью, чужое — белым. */
  --bub-out: #1f9d3d;
  --bub-out-ink: #ffffff;
  --bub-in: #ffffff;
  --thread-bg: #e8ecef;
  --warn: #b57400;
  --warn-soft: #fff2cc;
  --bad: #d7261e;
  --bad-soft: #fde8e6;

  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB",
    "Microsoft YaHei", "Noto Sans SC", "Noto Sans", Roboto, Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  /* Типографика: пять ступеней и ни одной больше. Раньше в файле жили
     34 размера — от этого экран выглядит грязным, даже когда всё правильно.
     Мельче 13px не опускаемся: читают на солнце и в перчатках. */
  --t-xs: 0.8125rem;   /* 13px — метки, время, единицы */
  --t-sm: 0.9375rem;   /* 15px — вспомогательный текст */
  --t-md: 1.0625rem;   /* 17px — основной, совпадает с телом страницы */
  --t-lg: 1.25rem;     /* 20px — заголовок блока, крупное число */
  --t-xl: 1.5rem;      /* 24px — заголовок страницы */
  --lh: 1.5;
  --lh-tight: 1.25;   /* заголовки и подписи в две строки */

  /* Глифы кнопок — стрелка, крестик, микрофон. Это знак, а не текст:
     его размер задаётся кнопкой, а не читаемостью строки. */
  --g-sm: 1.25rem;
  --g-md: 1.5rem;

  /* Три насыщенности. 650 и 800 системные шрифты рисуют так же, как 600 и 700:
     разница была задумана, но на экране её нет. */
  --w-reg: 400;
  --w-mid: 600;
  --w-bold: 700;

  /* Три радиуса вместо десяти: 9px, 11px и 3px были ручной подгонкой. */
  --r-sm: 8px;
  --r: 14px;
  --r-lg: 16px;
  --r-pill: 999px;
  --r-tail: 4px;   /* хвостик пузыря переписки */

  --tap: 48px;
  --pad: 16px;
}

/* Тёмной темы у площадки нет намеренно.
   Соя, зерно, накладные — это дневная работа, и заказчик хочет один вид
   на всех экранах: светлый. Автоматическое переключение по системной
   настройке телефона дало бы половине людей вид, которого никто не
   утверждал, и разговор «почему у меня всё чёрное» вместо разговора о деле.
   Поэтому цвета заданы один раз, выше, и не переопределяются. */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-md);
  line-height: var(--lh);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

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

   Волны лежат отдельным закреплённым слоем, а не фоном самой страницы.
   Это не украшательство, а необходимость: background-attachment: fixed
   заставляет браузер перерисовывать градиенты на каждом кадре прокрутки,
   и лента партий начинала подтормаживать. Отдельный слой видеокарта держит
   готовым и при прокрутке просто оставляет на месте — рисовать нечего. */
body:not(.land)::before {
  content: '';
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(1200px 700px at 4% -12%, #d5ebd4 0%, rgb(213 235 212 / 0%) 64%),
    radial-gradient(900px 560px at 100% 0%, #f2ead0 0%, rgb(242 234 208 / 0%) 60%),
    radial-gradient(1000px 620px at 92% 108%, #dfeedd 0%, rgb(223 238 221 / 0%) 62%);
}

a { color: inherit; }

h1, h2, h3 { margin: 0; font-weight: var(--w-bold); letter-spacing: -0.02em; line-height: var(--lh-tight); text-wrap: balance; }
h1 { font-size: var(--t-xl); }
h2 { font-size: var(--t-lg); }
h3 { font-size: var(--t-md); letter-spacing: -0.012em; }
p { margin: 0; }

/* ——— шапка ——— */

/* Шапка уезжает при прокрутке, вкладки остаются. Прилипать к одной точке
   они не могут — вкладки просто спрячутся под шапкой, и на телефоне человек
   после первой же прокрутки останется без навигации. Язык меняют раз в жизни,
   а по вкладкам ходят постоянно, поэтому остаются вкладки. */
.top {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding-top: env(safe-area-inset-top);
}
.top__in {
  max-width: 62rem;
  margin: 0 auto;
  padding: 10px var(--pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.brand { display: flex; align-items: center; gap: 9px; text-decoration: none; }
.brand__mark { width: 28px; height: 28px; flex: none; display: block; }
.brand__text {
  font-weight: var(--w-bold); letter-spacing: -0.02em; font-size: var(--t-md);
  white-space: nowrap;   /* «Соя ДВ» не должна ломаться на две строки */
}

/* Тот же знак крупно — на экране входа. */
.emblem { width: 84px; height: 84px; display: block; margin: 0 auto 4px; }

.langs { display: flex; gap: 2px; }
.lang {
  /* Раньше на узком экране был крупнее, чем на широком, и высотой 34px —
     мимо собственного правила проекта в 48px. По 中文 промахивались. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--t-sm);
  padding: 0 10px;
  border-radius: var(--r-sm);
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}
.lang--on { background: var(--surface-2); color: var(--ink); font-weight: var(--w-mid); }

/* ——— вкладки ——— */

.tabs {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  position: sticky;
  top: 0;
  z-index: 15;
  /* У оператора восемь вкладок и они не влезают. Тень справа показывает,
     что список продолжается, — иначе про остальные просто не узнают. */
  background-image: linear-gradient(to left, var(--ground), transparent 24px);
  background-repeat: no-repeat;
  background-position: right center;
  background-size: 24px 100%;
  background-attachment: local, scroll;
}
/* Прилипшие вкладки должны отделяться от контента, который под них уезжает. */
.tabs::after { content: ''; }
.tabs { box-shadow: 0 1px 0 var(--line); }
.tabs::-webkit-scrollbar { display: none; }
.tabs__in { max-width: 62rem; margin: 0 auto; display: flex; padding: 0 8px; }
.tab {
  padding: 13px 12px;
  font-size: var(--t-sm);
  font-weight: var(--w-mid);
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  display: flex; align-items: center; gap: 6px;
}
.tab--on { color: var(--ink); border-bottom-color: var(--ru); }
.tab__n {
  background: var(--ru); color: var(--on-ru); font-size: var(--t-xs); font-weight: var(--w-bold);
  min-width: 18px; height: 18px; border-radius: var(--r);
  display: inline-flex; align-items: center; justify-content: center; padding: 0 5px;
}

/* ——— каркас ——— */

.main {
  flex: 1;
  width: 100%;
  max-width: 42rem;
  margin: 0 auto;
  padding: 20px var(--pad) 48px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.main--wide { max-width: 62rem; }

.back {
  font-size: var(--t-sm); color: var(--muted); text-decoration: none;
  align-self: flex-start; padding: 4px 0;
}

.foot {
  border-top: 1px solid var(--line);
  padding: 16px var(--pad) calc(16px + env(safe-area-inset-bottom));
  font-size: var(--t-sm);
  color: var(--muted);
  display: flex; justify-content: space-between; gap: 12px;
  max-width: 62rem; margin: 0 auto; width: 100%;
}

.head { display: flex; flex-direction: column; gap: 4px; }
.head__sub { color: var(--ink-2); font-size: var(--t-sm); }

/* ——— формы ——— */

form { display: contents; }
.form { display: flex; flex-direction: column; gap: 14px; }

.field { display: flex; flex-direction: column; gap: 6px; }
/* Без этой строки hidden на поле не работает: у .field собственный display,
   а он сильнее, чем [hidden] из встроенных правил браузера. Ровно на этом
   уже один раз осталась на экране кнопка, которую скрипт «прятал». */
.field[hidden] { display: none; }
.field__label { font-size: var(--t-sm); font-weight: var(--w-mid); color: var(--ink-2); }
.field__hint { font-size: var(--t-sm); color: var(--muted);  }
.field__error { font-size: var(--t-sm); color: var(--bad); font-weight: var(--w-mid); }
.field--error .input { border-color: var(--bad); }

.input {
  font: inherit;
  font-size: var(--t-md); /* < 16px заставляет iOS зумить при фокусе */
  color: var(--ink);
  background: var(--surface);
  border: 1.5px solid var(--line);
  border-radius: var(--r);
  padding: 0 14px;
  height: var(--tap);
  width: 100%;
  appearance: none;
}
textarea.input { height: auto; min-height: 96px; padding: 12px 14px;  resize: vertical; }
select.input {
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: right 18px center, right 12px center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 34px;
}
.input:focus-visible { outline: 3px solid var(--ru); outline-offset: 1px; border-color: var(--ru); }
.input[type="file"] { padding: 11px 12px; height: auto; }
.input::placeholder { color: var(--muted); }
.input:disabled { background: var(--surface-2); color: var(--muted); }

.row { display: grid; gap: 10px; grid-template-columns: 1fr 1fr; }
.row-3 { display: grid; gap: 10px; grid-template-columns: repeat(3, 1fr); }
@media (max-width: 380px) { .row-3 { grid-template-columns: 1fr 1fr; } }
/* длинные подписи фильтров не влезают в половину узкого экрана */
@media (max-width: 460px) { .filters .row { grid-template-columns: 1fr; } }
/* Пара полей с длинными подписями на узком экране лучше читается в столбик. */
.row--long { grid-template-columns: 1fr; }
@media (min-width: 30rem) { .row--long { grid-template-columns: 1fr 1fr; } }

.check {
  display: flex; align-items: center; gap: 11px;
  min-height: var(--tap); cursor: pointer; font-size: var(--t-sm);
}
.check input { width: 22px; height: 22px; accent-color: var(--ru); flex: none; }

/* ——— кнопки ——— */

.btn {
  font: inherit; font-weight: var(--w-bold); font-size: var(--t-md); letter-spacing: -0.01em;
  min-height: var(--tap);
  padding: 0 20px;
  border-radius: var(--r);
  border: 1.5px solid transparent;
  background: var(--ru);
  color: var(--on-ru);
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  text-decoration: none;
  text-align: center;
}
.btn:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.btn--block { width: 100%; }
.btn--cn { background: var(--cn); color: var(--on-cn); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--quiet { background: var(--surface-2); color: var(--ink); font-weight: var(--w-mid); }
.btn--sm { min-height: 38px; font-size: var(--t-sm); padding: 0 14px; border-radius: var(--r); }
.btn--danger { background: transparent; color: var(--bad); border-color: var(--line); }

.btns { display: flex; gap: 10px; flex-wrap: wrap; }
.btns--end { justify-content: flex-end; }

/* ——— карточки ——— */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 15px;
  display: flex; flex-direction: column; gap: 11px;
  text-decoration: none;
  color: inherit;
}
.card--link { transition: border-color 0.12s ease, transform 0.08s ease; }
.card--link:active { border-color: var(--ru); transform: scale(0.995); }
@media (hover: hover) { .card--link:hover { border-color: var(--ru); } }
.cards { display: flex; flex-direction: column; gap: 11px; }

.card__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.card__title { font-weight: var(--w-bold); font-size: var(--t-md); letter-spacing: -0.015em; }
.card__place { font-size: var(--t-sm); color: var(--ink-2); }
/* Длинная почта в заголовке переносить себя не даёт — в ней нет ни пробелов,
   ни дефисов, — и на телефоне выдавливала плашку за край карточки. Колонке
   разрешаем сжиматься, слову — переноситься, плашке — не ужиматься. */
.card__top > :first-child { min-width: 0; }
.card__top > .badge { flex: none; }
.card__title { overflow-wrap: anywhere; }

.specs {
  /* Характеристики — одной строкой через точку, а не россыпью цветных плашек.
     На площадке строка = позиция: глаз идёт по одной линии, а не прыгает
     по семи прямоугольникам разного цвета. */
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 6px;
  color: var(--ink-2);
  font-size: var(--t-sm);
}
.spec {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-size: var(--t-sm);
}
.spec + .spec::before { content: "·"; color: var(--line); margin-right: 6px; }
.spec b { font-weight: var(--w-bold); }
.spec--hi { color: var(--ink); }

.thumb {
  width: 100%; height: 128px; object-fit: cover;
  border-radius: var(--r); background: var(--surface-2); display: block;
}
.thumb--ph {
  display: flex; align-items: center; justify-content: center;
  height: 160px; overflow: hidden;
  background: linear-gradient(180deg, var(--gold-soft), var(--surface-2));
}
.thumb__pic { max-width: 78%; max-height: 128px; object-fit: contain; display: block; }

/* ——— деньги ——— */

.price { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
/* Цена — главное число на карточке, поэтому крупнее и плотнее остального. */
.price__main {
  font-size: var(--t-xl); font-weight: var(--w-bold); letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.price__unit { font-size: var(--t-sm); color: var(--muted); }
.price__alt { font-size: var(--t-sm); color: var(--muted); font-variant-numeric: tabular-nums; }
.price--ask { font-size: var(--t-md); font-weight: var(--w-bold); color: var(--ink-2); }

/* ——— закрытая цена ——— */

.price--locked { align-items: center; gap: 12px; }
.price__lock {
  font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--ru);
  background: var(--ru-soft); border-radius: var(--r-sm); padding: 4px 9px;
  white-space: nowrap;
}
/* ——— «требует внимания» ——— */

.attn {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden;
  display: flex; flex-direction: column;
}
.attn__row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: var(--tap); padding: 0 14px;
  text-decoration: none; color: var(--ink);
  border-bottom: 1px solid var(--line-soft);
  border-left: 3px solid transparent;
}
.attn__row:last-child { border-bottom: 0; }
.attn__row--urgent { border-left-color: var(--ru); }
.attn__row--info { border-left-color: var(--line); }
.attn__row:active { background: var(--surface-2); }
@media (hover: hover) { .attn__row:hover { background: var(--surface-2); } }
.attn__text { font-size: var(--t-sm); font-weight: var(--w-mid); }

/* Слова самого человека — ответ «зачем вам площадка». Ради него и задавали
   вопрос, поэтому в карточке это не строка среди реквизитов, а цитата
   с полосой слева: глаз находит её раньше, чем ИНН. */
/* Документ: длинный связный текст, который читают подряд, а не сканируют.
   Строка уже, чем на остальных страницах, — так глаз не теряет начало
   следующей; между абзацами воздух, заголовки отделены сверху. */
.doc { display: flex; flex-direction: column; gap: 10px; max-width: 42rem; }
.doc h2 { margin-top: 12px; font-size: var(--t-lg); }
.doc p { font-size: var(--t-md); color: var(--ink-2); line-height: 1.62; }

/* Экран ожидания. Человек здесь ничего не нарушил — он просто ждёт,
   поэтому не жёлтая плашка тревоги, а спокойная карточка. */
.waitbox {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
  padding: 17px; display: flex; flex-direction: column; gap: 9px;
  font-size: var(--t-md); color: var(--ink-2);
}
.waitbox__lead { font-size: var(--t-lg); font-weight: var(--w-bold); color: var(--ink); letter-spacing: -0.02em; }
.waitbox__where { color: var(--ink); font-weight: var(--w-mid); }
.waitbox__eta { font-size: var(--t-sm); color: var(--muted); }

.said { border-left: 3px solid var(--line); padding: 2px 0 2px 11px; }
.said__h { display: block; font-size: var(--t-xs); color: var(--muted); margin-bottom: 3px; }
.said__t { font-size: var(--t-sm); color: var(--ink); white-space: pre-wrap; }
.attn__n {
  min-width: 24px; height: 24px; border-radius: var(--r); padding: 0 7px;
  background: var(--ru-soft); color: var(--ru-ink);
  font-size: var(--t-sm); font-weight: var(--w-bold);
  display: inline-flex; align-items: center; justify-content: center;
  font-variant-numeric: tabular-nums; flex: none;
}
.attn__row--info .attn__n { background: var(--surface-2); color: var(--ink-2); }

.cta {
  background: var(--ru); color: var(--on-ru);
  border-radius: var(--r); padding: 15px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
}
.cta__text { display: flex; flex-direction: column; gap: 2px; min-width: 12rem; flex: 1; }
.cta__text b { font-size: var(--t-md); letter-spacing: -0.015em; }
.cta__text span { font-size: var(--t-sm); opacity: 0.85; }
.cta .btn { background: var(--on-ru); color: #2e4620; border-color: var(--on-ru); }
.cta .btn:focus-visible { outline-color: var(--on-ru); }

/* карточка без действия — видна, но не тянет на себя внимание */
.card--dim { opacity: 0.62; }

.delivered {
  background: var(--ru-soft); color: var(--ru);
  border-radius: var(--r); padding: 9px 11px;
  font-size: var(--t-sm); font-weight: var(--w-mid);
  display: flex; flex-direction: column; gap: 2px;
  font-variant-numeric: tabular-nums;
}
.delivered__row {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
}
.delivered b { font-size: var(--t-md); white-space: nowrap; }
.delivered small { font-weight: var(--w-mid); opacity: 0.8; font-size: var(--t-xs); }
/* строка «набрано / не хватает» в заявке остаётся в одну линию */
.delivered:not(:has(.delivered__row)) { flex-direction: row; justify-content: space-between; align-items: baseline; }

.calc { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.calc__head {
  padding: 12px 15px; background: var(--surface-2);
  font-weight: var(--w-bold); font-size: var(--t-sm); letter-spacing: -0.01em;
  display: flex; justify-content: space-between; gap: 10px; align-items: center;
}
.calc__row {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 11px 15px; font-size: var(--t-sm);
  border-top: 1px solid var(--line-soft);
}
.calc__row span:last-child { font-variant-numeric: tabular-nums; white-space: nowrap; }
.calc__row--sub { font-size: var(--t-sm); color: var(--muted); padding-top: 7px; padding-bottom: 7px; }
.calc__row--sub span:last-child { color: var(--muted); }
.calc__row--total {
  background: var(--ru-soft); color: var(--ru-ink); font-weight: var(--w-bold); border-top-color: transparent;
}
.calc__note { padding: 11px 15px; font-size: var(--t-sm); color: var(--muted); border-top: 1px solid var(--line-soft); }

/* ——— значки и плашки ——— */

.badge {
  font-size: var(--t-xs); font-weight: var(--w-bold); letter-spacing: 0.01em;
  padding: 4px 8px; border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink-2);
  white-space: nowrap;
}
.badge--ok { background: var(--ru-soft); color: var(--ru); }
.badge--warn { background: var(--warn-soft); color: var(--warn); }
.badge--bad { background: var(--bad-soft); color: var(--bad); }
.badge--cn { background: var(--cn-soft); color: var(--cn-ink); }
.badge--ru { background: var(--ru-soft); color: var(--ru-ink); }
/* в колоночном flex значок иначе растягивается на всю ширину карточки */
.card > .badge, .stack > .badge { align-self: flex-start; }

/* Кнопка «Заполнить» — под полем ИНН, а не внутри него: field() заворачивает
   содержимое в <label>, и кнопка внутри нажималась бы вместе с полем.
   На телефоне тянем на всю ширину: кнопка шириной в слово рядом с полем
   шириной в экран читается как случайно уехавшая. */
.field__act { margin: -6px 0 4px; display: flex; }
.field__act .btn { flex: 1 1 auto; }
@media (min-width: 480px) {
  .field__act { justify-content: flex-start; }
  .field__act .btn { flex: 0 0 auto; }
}

/* Карточка «нашли в реестре» — под полем ИНН. Появляется только когда
   есть что показать: пустая рамка «здесь будет компания» это шум.
   Намеренно тихая — это не сообщение об успехе, а подтверждение факта. */
.regcard {
  margin: 2px 0 4px; padding: 10px 12px;
  border-radius: var(--r); background: var(--surface-2);
  display: flex; flex-direction: column; gap: 3px;
}
.regcard[hidden] { display: none; }
/* Ликвидируется, банкротится, реорганизуется — оператор всё равно должен
   видеть, кто подавался, поэтому не прячем, а окрашиваем. */
.regcard--warn { background: var(--warn-soft); }
.regcard__w { color: var(--warn); font-weight: var(--w-mid); }
.regcard__r { font-size: var(--t-sm); color: var(--ink); }
.regcard__k { color: var(--muted); }
.regcard__k::after { content: ' — '; }
.regcard__n { font-weight: var(--w-mid); }
.regcard__a { color: var(--muted); font-size: var(--t-xs); }

.alert {
  border-radius: var(--r); padding: 13px 15px; font-size: var(--t-md); 
  border: 1px solid var(--line); background: var(--surface);
}
.alert--ok { background: var(--ru-soft); border-color: transparent; color: var(--ru); font-weight: var(--w-mid); }
.alert--warn { background: var(--warn-soft); border-color: transparent; color: var(--warn); }
.alert--bad { background: var(--bad-soft); border-color: transparent; color: var(--bad); }
.alert b { font-weight: var(--w-bold); }

.empty {
  text-align: center; padding: 44px 20px;
  color: var(--muted);
  display: flex; flex-direction: column; gap: 16px; align-items: center;
}
/* Картинку рисуем настоящим изображением, а не фоном у ::before:
   объёмный рендер должен масштабироваться и грузиться отложенно. */
.empty__pic {
  /* Знак, а не картинка: пустому месту нечего иллюстрировать, а рисунок там
     всегда читается не так, как задумано. Размер сдержанный — это подпись
     к строке текста, а не сама новость. */
  width: 72px; height: 72px; object-fit: contain; opacity: 0.65;
}
/* ——— фильтры ——— */

/* Панель фильтров свёрнута по умолчанию — партии видны сразу, без прокрутки. */
.fbox {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
}
.fbox__sum {
  list-style: none; cursor: pointer;
  min-height: var(--tap); padding: 0 14px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.fbox__sum::-webkit-details-marker { display: none; }
.fbox__sum:focus-visible { outline: 3px solid var(--ru); outline-offset: -3px; border-radius: var(--r); }
.fbox__digest {
  font-size: var(--t-sm); font-weight: var(--w-mid); color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fbox__chev {
  width: 9px; height: 9px; flex: none;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(45deg) translate(-2px, -2px);
}
.fbox[open] .fbox__chev { transform: rotate(225deg) translate(-2px, -2px); }
.fbox[open] .fbox__sum { border-bottom: 1px solid var(--line-soft); }
/* Содержимое раскрывашки — с полями внутри, а не впритык к рамке: без этого
   подписи стояли у самого края и «вот-вот уедут за бока». */
.fbox__body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 14px; }

.filters {
  padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 10px;
}

/* ——— ползунки ——— */




.count { font-size: var(--t-sm); color: var(--muted); }

/* ——— полоса этапов сделки ——— */

/* линия между кружками */

/* ——— переписка ———
   Пузыри, лента и композер собраны в одном месте: раньше .thread, .msg__time
   и .msg__img были заданы по два раза в разных концах файла, и правка
   попадала не туда. */

.msg__orig { display: block; font-size: var(--t-xs); color: var(--muted); margin-top: 5px; font-family: var(--mono); }
/* Исходник под переводом в своём пузыре — тоже светлым, а не серым. */
.msg--me .msg__orig { color: rgb(255 255 255 / 72%); }
.msg--me .msg__also { color: rgb(255 255 255 / 82%); }
/* Единица прямо в поле ввода: цена на площадке всегда за тонну, и человек
   должен видеть это, пока набирает, а не догадываться по плейсхолдеру. */
.unit { position: relative; display: block; }
.unit .input { padding-right: 4.2rem; }
.unit__tag {
  position: absolute; top: 50%; right: 12px; transform: translateY(-50%);
  color: var(--muted); font-size: var(--t-sm); pointer-events: none;
  font-variant-numeric: tabular-nums;
}

/* Маршрут без денег: пока ставка ориентировочная, в карточке остаётся
   только «куда и сколько километров». Тише цены, но на своей строке. */
.route {
  /* Маршрут — такая же вспомогательная строка, как характеристики.
     Раньше это была зелёная плашка: третий цветной прямоугольник в карточке. */
  color: var(--ink-2);
  font-size: var(--t-sm);
}

/* Попытки обхода: что человек пробовал передать, читаемо и с переносами. */
.tries { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.tries li {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px; border-radius: var(--r); background: var(--warn-soft);
  font-size: var(--t-sm); overflow-wrap: anywhere;
}
.tries b { font-family: var(--mono); color: var(--warn); }
.tries .muted { font-size: var(--t-xs); }

/* Спрятанный контакт: обе стороны видят, что здесь что-то было, и почему. */
.msg__hid {
  display: inline-block; margin-top: 6px; padding: 2px 8px; border-radius: var(--r-pill);
  font-size: var(--t-xs); background: var(--warn-soft); color: var(--warn);
}
/* Та же пилюля, но живая: кнопка «Перевести» под сообщением без перевода.
   Зелёная, как всё нажимаемое на площадке, и с полем под палец. */
.msg__trbtn {
  border: 0; cursor: pointer; font: inherit;
  font-size: var(--t-xs); font-weight: var(--w-mid);
  padding: 4px 12px; background: var(--ru-soft); color: var(--ru-ink);
}
.msg__trbtn:disabled { cursor: default; opacity: 0.7; }
.msg__trbtn:focus-visible { outline: 2px solid var(--ru); outline-offset: 1px; }

/* ——— таблицы оператора ——— */

.tablewrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); }
table { border-collapse: collapse; width: 100%; font-size: var(--t-sm); }
th, td { padding: 11px 13px; text-align: left; border-bottom: 1px solid var(--line-soft); white-space: nowrap; }
th { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: var(--w-bold); }
tr:last-child td { border-bottom: 0; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--mono); }

/* ——— мелочи ——— */

.stack { display: flex; flex-direction: column; gap: 12px; }
.muted { color: var(--muted); font-size: var(--t-sm); }
.sep { height: 1px; background: var(--line); border: 0; margin: 4px 0; }
.hint { font-size: var(--t-sm); color: var(--muted);  }

.pick__opt:has(input:checked) .pick__h,

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ——— плавность ———
   Заказчик: «сделай сайт плавнее». Всё — короткие переходы (120–200 мс),
   без библиотек; кому анимация мешает, у того она выключена блоком выше. */

/* Переход между страницами: короткое затухание вместо белой вспышки.
   Работает там, где браузер умеет (Chrome, Safari 18+), остальным — как было. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: 120ms ease-out both vt-out; }
::view-transition-new(root) { animation: 160ms ease-out both vt-in; }
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; } }

/* Новое сообщение в ленте поднимается снизу, а не возникает рывком. */
@keyframes msg-in { from { opacity: 0; translate: 0 8px; } }
.msg--in { animation: msg-in 0.18s ease-out; }

/* Раскрытие панелей: сделка, «в ответ на», подсказки. */
@keyframes rise { from { opacity: 0; translate: 0 -6px; } }
.deal[open] .deal__in, .replybar:not([hidden]), .note { animation: rise 0.2s ease-out; }

/* Кнопки и карточки отвечают на нажатие. */
.btn { transition: transform 0.1s ease, background-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease; }
.btn:active { transform: scale(0.98); }
.card, .dlg { transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease; }
.tab, .bottom__a, .chtab, .lang { transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease; }
.vm__wave i { transition: opacity 0.12s ease; }
.msg__reply, .say__send, .say__mic, .say__clip { transition: background-color 0.15s ease, opacity 0.15s ease, transform 0.1s ease; }
.say__send:active, .say__mic:active, .say__clip:active { transform: scale(0.94); }

/* Форма отправлена — кнопка показывает «идёт», а не молчит до перезагрузки.
   Класс ставит nav.js на любой форме сайта. */
.btn--busy { opacity: 0.75; pointer-events: none; }
.btn--busy::after {
  content: ''; display: inline-block; width: 14px; height: 14px; margin-left: 8px;
  vertical-align: -2px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Готовые фразы — основной способ написать; свои слова спрятаны под «details»,
   потому что переводчика нет и такое сообщение уйдёт как есть. */
.composer--phrase { gap: 12px; }
.composer--phrase .field { margin: 0; }

/* ——— мессенджер ——— */

/* Список разговоров: имя, обрывок последнего сообщения, непрочитанное.
   Всё, по чему человек узнаёт диалог, не открывая его. */
.dialogs { display: flex; flex-direction: column; gap: 2px; }
.dlg {
  display: flex; flex-direction: column; gap: 3px;
  padding: 12px 14px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line);
  text-decoration: none; min-height: var(--tap);
}
.dlg--new { border-color: var(--ru); background: var(--ru-soft); }
.dlg__top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.dlg__name {
  font-weight: var(--w-mid); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dlg__time { font-size: var(--t-xs); color: var(--muted); white-space: nowrap; }
.dlg__bottom { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.dlg__last {
  color: var(--ink-2); font-size: var(--t-sm); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dlg--new .dlg__last { color: var(--ink); }
.dlg__n {
  flex: none; background: var(--ru); color: var(--on-ru);
  font-size: var(--t-xs); font-weight: var(--w-bold); min-width: 20px; height: 20px;
  border-radius: var(--r); display: inline-flex; align-items: center; justify-content: center; padding: 0 6px;
}
.dlg__lot { font-size: var(--t-xs); color: var(--muted); }

/* Лента прокручивается вместе со страницей, а не внутри своей рамки:
   вложенная прокрутка на телефоне всегда промахивается мимо пальца.
   На месте остаётся поле ввода — оно прилипает к низу экрана.

   Своя подложка у ленты — чтобы пузыри читались как разговор, а не как
   карточки на общем фоне страницы. */
.thread {
  display: flex; flex-direction: column; gap: 10px;
  min-height: 34vh;
  margin: 0 -14px; padding: 12px 14px;
  /* Обои: еле заметные стручки сои — лента читается как мессенджер,
     а не как серый лист. Плитка бесшовная, рисунок на 11% прозрачности. */
  background: var(--thread-bg) url(/chat-bg.png) center / 320px repeat;
}

/* Пузырь. Свой — зелёный, как привык китайский покупатель в WeChat;
   чужой — белый лист. Разница видна на солнце и на дешёвом экране. */
.msg {
  max-width: 76%; padding: 7px 11px 5px; border-radius: var(--r);
  font-size: var(--t-md);
  -webkit-touch-callout: none;   /* долгое касание — наш жест «ответить» */
}
/* Объём у пузырей — тенью и лёгким градиентом, а не картинками: разговор
   должен читаться, а не разглядываться. Пузырь лежит НА подложке ленты,
   и тень говорит об этом лучше рамки. */
.msg--them {
  background: var(--bub-in); border: 1px solid var(--line-soft);
  align-self: flex-start; border-bottom-left-radius: var(--r-tail);
  box-shadow: 0 1px 2px rgb(16 20 24 / 7%);
}
.msg--me {
  background: linear-gradient(175deg, #27ac47, var(--bub-out) 62%);
  color: var(--bub-out-ink);
  align-self: flex-end; border-bottom-right-radius: var(--r-tail);
  box-shadow: 0 1px 2px rgb(20 110 45 / 22%), 0 4px 10px -4px rgb(20 110 45 / 30%);
}
/* Подряд идущие сообщения одного автора — одной группой, без хвостика. */
.msg--cont { margin-top: -7px; }
.msg--cont.msg--them { border-bottom-left-radius: var(--r); border-top-left-radius: var(--r-tail); }
.msg--cont.msg--me { border-bottom-right-radius: var(--r); border-top-right-radius: var(--r-tail); }

/* Системная запись — не пузырь, а отметка посередине: цена, проба, событие. */
.msg--sys {
  align-self: center; max-width: 92%;
  background: var(--surface-2); color: var(--ink-2);
  font-size: var(--t-sm); text-align: center; border-radius: var(--r);
  padding: 8px 12px;
}
/* Событие сделки — со значком слева: рукопожатие про цену, грузовик про
   перевозку. Видно, что произошло, ещё до чтения строки. */
.msg--sys--ico {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  gap: 10px; text-align: left; padding: 8px 14px 8px 10px;
  background: var(--surface);
  box-shadow: 0 1px 2px rgb(16 20 24 / 7%);
}
.msg__sysico { width: 26px; height: 26px; display: block; object-fit: contain; grid-row: span 2; }
.msg--sys--ico .msg__meta { justify-content: flex-start; margin-top: 1px; }
.msg--sys .msg__meta { justify-content: center; }

/* Разделитель: день или большой перерыв в разговоре. */
.thread__sep {
  align-self: center; margin: 6px 0 2px;
  font-size: var(--t-xs); color: var(--muted);
  background: var(--surface-2); border-radius: var(--r-pill); padding: 3px 12px;
}

.msg__text { display: block; white-space: pre-wrap; overflow-wrap: anywhere; }
.msg__img {
  display: block; max-width: 100%; border-radius: var(--r); margin-bottom: 6px;
}
/* Пузырь с фото: снимок до самых краёв, как в мессенджерах, — рамка 3px
   вместо полей, остальное содержимое сдвинуто внутрь на те же поля. */
.msg--pic { padding: 3px 3px 5px; }
.msg--pic .msg__img { border-radius: var(--r-sm); margin: 0 0 4px; width: 100%; }
.msg--pic .msg__quote { margin: 4px 8px 6px; }
.msg--pic .msg__text, .msg--pic .msg__also, .msg--pic .msg__orig,
.msg--pic .msg__hid, .msg--pic .msg__who, .msg--pic .msg__meta { margin-left: 8px; margin-right: 8px; }
/* Кто пишет — над первым пузырём группы, когда в канале больше двух голосов. */
.msg__who { display: block; font-size: var(--t-xs); font-weight: var(--w-bold); color: var(--ru-ink); margin-bottom: 2px; }
.msg__time { font-size: var(--t-xs); color: var(--muted); line-height: 1; }
.msg--me .msg__time { color: var(--bub-out-ink); opacity: 0.7; }
/* Время и галочки — мелко, в правом нижнем углу, как в мессенджерах. */
.msg__meta { display: flex; align-items: center; gap: 4px; margin-top: 3px; justify-content: flex-end; }

/* Композер — фразы, цитата и поле ввода одним липким блоком НАД нижней
   панелью. Раньше .say липла сама по себе с z-index ниже панели и на
   прокрутке уезжала под «Торговля / Переписка / Новости». */
.composer {
  position: sticky;
  bottom: calc(var(--bottom-h, 0px) + env(safe-area-inset-bottom));
  z-index: 17;
  display: flex; flex-direction: column; gap: 8px;
  padding: 8px 0 10px;
  background: var(--ground);
  box-shadow: 0 -10px 18px -12px rgba(0, 0, 0, 0.35);
}

/* Строка ввода: скрепка, поле, кнопка. Ничего лишнего между пальцем и «отправить». */
.say {
  display: flex; align-items: flex-end; gap: 6px;
  padding: 5px; border-radius: var(--r-pill);
  background: var(--surface); border: 1px solid var(--line);
}
textarea.say__text {
  flex: 1; min-height: 44px; height: 44px; max-height: 33vh;
  border: 0; background: transparent; padding: 11px 4px; resize: none;
  border-radius: 0;
}
.say__text:focus-visible { outline: none; }
.say__clip {
  flex: none; width: 42px; height: 42px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: var(--t-lg); background: var(--surface-2);
}
.say__clip input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.say__send {
  flex: none; width: 42px; height: 42px; border: 0; border-radius: 50%;
  background: var(--ru-soft); line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  box-shadow: var(--lift-btn);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
}
/* Значки-«пластилин» в кнопках строки ввода: те же, что в меню, а не эмодзи. */
.say__ic { width: 26px; height: 26px; display: block; pointer-events: none; }
.say__send:active { transform: translateY(1px); box-shadow: 0 1px 2px rgb(20 110 45 / 30%); }
.say__send:focus-visible { outline: 3px solid var(--ru); outline-offset: 2px; }

/* Быстрые фразы: для тех, у кого другой язык. Свёрнуты, чтобы не мешать. */
.quick[open] > summary::before { content: '– '; }
.chip {
  font: inherit; font-size: var(--t-sm); cursor: pointer;
  padding: 8px 12px; border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--ink); border: 1px solid var(--line);
}
.chip:active { background: var(--ru-soft); }

/* Перевозка — то, ради чего площадка существует. Поэтому она над перепиской,
   а не спрятана в меню. */
.ship {
  background: var(--cn-soft); border: 1px solid var(--cn); border-radius: var(--r);
  padding: 12px 14px; display: flex; flex-direction: column; gap: 6px;
}
.ship__top { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.ship--ask > summary {
  cursor: pointer; font-weight: var(--w-bold); color: var(--cn-ink); list-style: none;
}
.ship--ask > summary::-webkit-details-marker { display: none; }
.ship--ask > summary::after { content: ' →'; }

.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* ——— выбор роли при регистрации ——— */
/* Плашка для гостя на витрине: главное действие — регистрация, вход рядом
   ссылкой. Гость пришёл смотреть товар, а не входить, и кнопка «Войти»
   первой отпугивает того, у кого учётной записи ещё нет. */
.cta__act { display: flex; align-items: center; gap: 14px; flex: none; }
/* Ссылка лежит на зелёной плашке, поэтому берёт её же цвет текста, а не
   общий тёмный: тёмно-серое на зелёном не прочитать. Приглушаем прозрачностью,
   чтобы «Войти» не спорило с главной кнопкой «Смотреть цены». */
.cta__in {
  font-size: var(--t-sm); white-space: nowrap;
  color: var(--on-ru); opacity: 0.85;
}
.cta__in:hover { opacity: 1; }

/* ——— регистрация ——— */

/* Подпись под формой: «Уже зарегистрированы?», «Письма нет — посмотрите спам».
   Не подсказка внутри поля, а спокойная строка под всей формой. */
.formfoot {
  margin-top: 14px; text-align: center;
  font-size: var(--t-sm); color: var(--muted);
}
.formfoot a { color: var(--ru-ink); }

/* Два действия рядом: «Отправить ещё раз» и «Попросить код другим способом».
   На узком экране складываются в столбик — на телефоне два мелких действия
   в одну строку попадают мимо пальца. */
.formrow {
  display: flex; flex-wrap: wrap; gap: 8px 20px;
  justify-content: center; margin-top: 10px;
}

/* Предупреждение прямо на карточке роли: русская компания должна узнать
   про разрешение ДО того, как заполнит анкету, а не после. */

.rolecards { display: flex; flex-direction: column; gap: 14px; }
/* Крупные кнопки: выбор роли — первое решение человека на площадке,
   и промахнуться в нём нельзя. Поэтому картинка, а не значок. */
.rolecard {
  width: 100%; font: inherit; text-align: center; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 26px 18px; border-radius: var(--r-lg);
  background: var(--surface); border: 2px solid var(--line); color: var(--ink);
}
/* Карточка стала ссылкой, а не кнопкой формы — и потянула за собой
   подчёркивание из общего правила для ссылок. Здесь оно лишнее: подчёркнутый
   заголовок карточки читается как сломанная вёрстка. */
.rolecard, .rolecard:hover { text-decoration: none; }
.rolecard:hover { border-color: var(--ru); }
.rolecard:active { background: var(--ru-soft); border-color: var(--ru); }
.rolecard:focus-visible { outline: 3px solid var(--ru); outline-offset: 2px; }
.rolecard__img { width: 88px; height: 88px; display: block; }
.rolecard__t { font-weight: var(--w-bold); font-size: var(--t-lg); letter-spacing: -0.015em; }
.rolecard__h { font-size: var(--t-sm); color: var(--muted); }
/* На широком экране три кнопки встают в ряд. */
@media (min-width: 46rem) {
  .rolecards { flex-direction: row; }
  .rolecards > form { flex: 1; display: flex; }
}

/* ——— мессенджер: голос, цитаты, ответ ——— */
.msg { position: relative; }
/* Цитата: на что отвечают.
   Дважды была нечитаемой. Сначала серой на зелёном, потом белой с
   прозрачностью 78% поверх осветлённого фона — то есть светлым по светлому.
   На насыщённом зелёном работает наоборот: подложку ЗАТЕМНЯЕМ, а текст
   оставляем чистым белым. Тогда цитата отделяется от пузыря и читается. */
.msg__quote {
  display: block; font-size: var(--t-sm); line-height: var(--lh-tight);
  color: var(--ink-2);
  background: rgb(16 20 24 / 5%);
  border-left: 3px solid var(--ru);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 5px 9px; margin-bottom: 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
.msg--me .msg__quote {
  color: #fff;
  background: rgb(0 0 0 / 20%);
  border-left-color: rgb(255 255 255 / 90%);
}
/* Плеер шире прежних 220px: на айфоне у встроенного плеера при узкой ширине
   остаётся один значок без шкалы. Запасная ссылка — когда плеер не смог. */
/* Голосовое: кнопка, волна, длительность — свой плеер вместо системного.
   <audio> внутри спрятан; играет он, а рисуем мы. Столбики — 40 <i>, высота
   из --h (1–9), сыгранные подсвечены. */
.vm { display: flex; align-items: center; gap: 8px; width: 240px; max-width: 100%; margin: 2px 0; }
.vm audio { display: none; }
.vm__play {
  flex: none; width: 36px; height: 36px; border: 0; border-radius: 50%; padding: 0;
  background: var(--ru); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.msg--me .vm__play { background: #fff; color: var(--ru); }
.vm__ic { width: 18px; height: 18px; display: block; }
.vm__wave { flex: 1; display: flex; align-items: center; gap: 2px; height: 32px; cursor: pointer; color: var(--ru-ink); }
.msg--me .vm__wave { color: #fff; }
.vm__wave i { flex: 1; min-width: 2px; max-width: 4px; height: calc(4px + var(--h, 3) * 2.6px); border-radius: var(--r-pill); background: currentColor; opacity: 0.35; }
.vm__wave i.on { opacity: 1; }
.vm__t { flex: none; font-size: var(--t-xs); font-variant-numeric: tabular-nums; color: var(--muted); min-width: 32px; text-align: right; }
.msg--me .vm__t { color: #fff; opacity: 0.8; }
.msg__voice { display: block; width: 260px; max-width: 100%; height: 40px; margin: 2px 0; }
.msg__voicelink {
  display: inline-block; margin: 2px 0; padding: 8px 14px; border-radius: var(--r);
  background: var(--surface-2); color: var(--ink); font-weight: var(--w-mid); text-decoration: none;
}
.msg--me .msg__voicelink { background: rgb(255 255 255 / 22%); color: var(--bub-out-ink); }
.msg__vt { font-size: var(--t-xs); color: var(--muted); }
/* Ответить: стрелка в строке времени, серая на белом пузыре, белая на
   зелёном. Цель под палец 30px, сам значок 16. */
.msg__reply {
  border: 0; background: transparent; cursor: pointer; color: var(--muted);
  width: 30px; height: 30px; margin: -7px 0 -7px -6px; padding: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.msg__reply:hover, .msg__reply:active { background: rgb(16 20 24 / 6%); color: var(--ink); }
.msg--me .msg__reply { color: var(--bub-out-ink); opacity: 0.85; }
.msg--me .msg__reply:hover, .msg--me .msg__reply:active { background: rgb(255 255 255 / 18%); opacity: 1; }
.msg__reply-ic { width: 16px; height: 16px; display: block; pointer-events: none; }

/* [hidden] у элемента с display:flex не работает — правило автора сильнее
   браузерного. Без этой строки плашка «В ответ на» висит пустой. */
.replybar[hidden] { display: none; }
.replybar {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-radius: var(--r) var(--r) 0 0;
  background: var(--surface-2); font-size: var(--t-sm);
  border: 1px solid var(--line); border-bottom: 0;
}
.replybar__t { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.replybar__x {
  border: 0; background: transparent; font-size: var(--g-sm); line-height: 1;
  cursor: pointer; color: var(--muted); padding: 0 4px;
}

.say__mic {
  flex: none; width: 42px; height: 42px; border: 0; border-radius: 50%;
  background: var(--surface-2); font-size: var(--g-sm); cursor: pointer; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.say__mic--on { background: var(--cn); color: var(--on-cn); animation: pulse 1s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: 0.55; } }
@media (prefers-reduced-motion: reduce) { .say__mic--on { animation: none; } }

/* Поле ИНН на время запроса в ЕГРЮЛ. */
.input--loading { background-image: linear-gradient(90deg, transparent, var(--ru-soft), transparent); background-size: 200% 100%; animation: shine 1s linear infinite; }
@keyframes shine { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .input--loading { animation: none; } }

/* ——— лента уведомлений ——— */
.feed { display: flex; flex-direction: column; gap: 2px; }
.ev {
  display: flex; gap: 12px; align-items: center;
  padding: 12px 14px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line);
  text-decoration: none; min-height: var(--tap);
}
.ev--new { border-color: var(--ru); background: var(--ru-soft); }
.ev__icon { flex: none; display: block; object-fit: contain; }
.ev__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ev__text { color: var(--ink); font-size: var(--t-sm); }
.ev__time { color: var(--muted); font-size: var(--t-xs); }

/* ——— отзывы на профиле ——— */
.rep { display: flex; gap: 16px; font-size: var(--t-md); font-weight: var(--w-bold); }
.rep__good { color: var(--ru); }
.rep__bad { color: var(--bad); }
.rev-pick { display: flex; gap: 10px; }
.rev-opt { flex: 1; }
.rev-opt input { position: absolute; opacity: 0; }
.rev-opt span {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 12px; border-radius: var(--r); border: 1.5px solid var(--line);
  background: var(--surface); cursor: pointer; font-weight: var(--w-mid);
}
.rev-opt input:checked + span { border-color: var(--ru); background: var(--ru-soft); color: var(--ru-ink); }

/* ——— новости ——— */
/* Лента новостей: карточками, как в обычной ленте, а не сплошным текстом. */
.news { display: flex; flex-direction: column; gap: 10px; }
.news__item {
  display: block;
  padding: 14px 16px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line);
  text-decoration: none;
}
.news__item:hover { border-color: var(--ru); }
.news__title {
  display: block; color: var(--ink); font-weight: var(--w-mid);
  font-size: var(--t-md);  margin-bottom: 8px;
  text-decoration: none;
}
.news__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  color: var(--muted); font-size: var(--t-sm);
}
/* Источник обязателен: заголовки чужие, авторство должно быть видно. */
.news__src {
  background: var(--surface-2); color: var(--ink-2);
  padding: 2px 8px; border-radius: var(--r-pill); font-weight: var(--w-mid);
}

/* ——— колокольчик уведомлений в шапке ——— */
.top__right { display: flex; align-items: center; gap: 10px; }
.bell {
  position: relative; display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--r); text-decoration: none;
  flex: none;
}
.bell:active { background: var(--surface-2); }
.bell__ico { display: block; object-fit: contain; }
/* Значки — объёмные, цветные и одинаково яркие. Чтобы было видно, где ты
   сейчас, приглушаем невыбранные, а не подкрашиваем выбранный. */
.bell__ico { opacity: .75; filter: saturate(.7); transition: opacity .12s, filter .12s; }
.bell:hover .bell__ico { opacity: 1; filter: none; }
/* Есть непрочитанное — колокольчик оживает и получает счётчик. */
.bell--on .bell__ico { opacity: 1; filter: none; }
.bell__n {
  position: absolute; top: 1px; right: 0;
  background: var(--cn); color: var(--on-cn);
  font-size: var(--t-xs); font-weight: var(--w-bold); line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 5px; border-radius: var(--r-pill);
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid var(--surface);
}

/* ——— документы на проверку ——— */
.docs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.doc {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line);
}
.doc__name { color: var(--ink); text-decoration: none; font-size: var(--t-sm); }
.doc__x {
  border: 0; background: transparent; cursor: pointer; color: var(--muted);
  font-size: var(--g-md); line-height: 1; padding: 0 6px;
}
.doc__x:hover { color: var(--bad); }

/* Документы стоят выше формы профиля и отделены рамкой, чтобы не сливаться
   с реквизитами: это разные действия и разные формы. */
.docsbox {
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px; border-radius: var(--r);
  background: var(--surface-2); border: 1px solid var(--line);
}

/* ——— просмотр фото из переписки ——— */
.msg__img { cursor: zoom-in; }
.lightbox {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0, 0, 0, 0.9);
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
}
.lightbox[hidden] { display: none; }
.lightbox__img {
  max-width: 100%; max-height: 100%;
  border-radius: var(--r); object-fit: contain;
}
/* Крестик крупный и в безопасной зоне — на телефоне под чёлкой не спрячется. */
.lightbox__x {
  position: absolute; top: calc(12px + env(safe-area-inset-top)); right: 12px;
  width: 48px; height: 48px; border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, 0.16); color: #fff;
  font-size: var(--g-md); line-height: 1; cursor: pointer;
}
.lightbox__x:active { background: rgba(255, 255, 255, 0.3); }

/* Продавец на карточке партии: имя, значок проверки и вход в отзывы. */
.seller { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: var(--t-sm); }
.seller__name { color: var(--ink-2); font-weight: var(--w-mid); }
.seller__rev { color: var(--ru); font-size: var(--t-sm); text-decoration: none; }
.seller__rev:hover { text-decoration: underline; }
.head__link { text-decoration: none; }
.head__link:hover { text-decoration: underline; }

/* Документы: строка «что за документ — одна кнопка». Раньше здесь стояли
   три элемента подряд («Выбрать файл», «файл не выбран», «Добавить»), и
   человек, выбрав скан, уходил, ничего не отправив. Теперь одна кнопка:
   поле выбора лежит под ней и отправляет форму само. */
.docrow {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px 12px;
  align-items: center;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}
.docrow__label { font-weight: var(--w-mid); min-width: 0; overflow-wrap: anywhere; }
/* Поле выбора не убрано из разметки, а спрятано: убрать нельзя — форму
   отправляет именно оно, а display:none отнял бы у него фокус с клавиатуры. */
.vh {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}
.docrow__pick { white-space: nowrap; justify-self: end; }
/* Обводка при работе с клавиатуры: поле спрятано, значит кольцо должно
   появляться на кнопке, иначе не видно, где ты находишься. */
.docrow__pick:focus-within { outline: 3px solid var(--ru); outline-offset: 2px; }
.docrow--busy .docrow__pick { opacity: 0.6; pointer-events: none; }

/* Кружок «i» у цены: из чего сложилась цена под ключ. Раскрывается и по
   наведению, и по тапу — на телефоне наведения нет. */

/* Живой пересчёт на форме партии: своя цена, доставка, итог под ключ. */
.turnkey {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface-2);
  padding: 10px 12px;
  margin: -4px 0 4px;
}
.turnkey__row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 3px 0;
  font-size: var(--t-sm);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.turnkey__row b { color: var(--ink); }
.turnkey__row--total { border-top: 1px solid var(--line); margin-top: 4px; padding-top: 6px; }

/* ——— Две главные плашки: покупка и продажа сои ———
   Это первое, что видно на экране, и первое, что человек выбирает:
   смотреть, кто покупает, или смотреть, кто продаёт. Цветом разделены,
   как на площадках, — глаз находит нужную сторону без чтения. */

/* ——— Нижняя панель: своё, разговор, новости ———
   Прижата книзу и всегда под большим пальцем. Всё, что относится
   к рынку, живёт наверху; здесь — только личное. */
.bottom {
  position: sticky;
  bottom: 0;
  z-index: 16;
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
.bottom__in {
  max-width: 62rem;
  margin: 0 auto;
  display: flex;
  justify-content: space-around;
}
.bnav {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 4px 10px;
  color: var(--muted);
  text-decoration: none;
  font-size: var(--t-xs);
  font-weight: var(--w-mid);
  position: relative;
}
.bnav__ico {
  display: block; object-fit: contain;
  opacity: .55; filter: saturate(.5);
  transition: opacity .12s, filter .12s;
}
.bnav:hover .bnav__ico { opacity: .8; filter: saturate(.8); }
.bnav--on { color: var(--ink); }
.bnav--on .bnav__ico { opacity: 1; filter: none; }
.bnav__n {
  position: absolute;
  top: 4px;
  left: 50%;
  margin-left: 4px;
  min-width: 17px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--ru);
  color: #fff;
  font-size: var(--t-xs);
  line-height: 1;
  text-align: center;
}

/* На телефоне в шапке колокольчик, профиль и языки. Вместе с именем шапке
   нужно 410 пикселей, поэтому на обычном телефоне имя прячем — иначе языки
   уезжают за край и до 中文 не дотянуться. На широких телефонах (430 и больше)
   место есть, и знак снова стоит с именем. */
@media (max-width: 420px) {
  .brand__text { display: none; }
}
@media (max-width: 480px) {
  .top__right { gap: 6px; }
  .langs { gap: 2px; }
  .lang { padding: 0 8px; }
  .bell { padding: 4px 6px; }
}

/* ——— Компьютер: раскладка как на площадках ———
   Крупные плашки и нижняя панель — это телефон. На широком экране нижняя
   панель уезжает наверх строкой ссылок, а «покупка / продажа» становится
   компактным переключателем над списком. Порядок блоков меняем flex-order,
   разметка одна на оба случая. */
@media (min-width: 720px) {
  body { display: flex; flex-direction: column; min-height: 100vh; }
  .top    { order: 1; }
  .bottom { order: 2; }
  .tabs   { order: 3; }
  .main   { order: 5; }
  .foot   { order: 6; margin-top: auto; }

  /* «Моё» — строка ссылок под шапкой */
  .bottom {
    position: static;
    border-top: none;
    border-bottom: 1px solid var(--line);
    padding-bottom: 0;
  }
  .bottom__in { justify-content: flex-start; gap: 2px; padding: 0 12px; }
  .bnav {
    flex: 0 0 auto;
    flex-direction: row;
    gap: 8px;
    padding: 13px 14px;
    font-size: var(--t-sm);
    border-bottom: 2px solid transparent;
  }
  .bnav__ico { width: 24px; height: 24px; }
  .bnav--on { border-bottom-color: var(--ru); }
  .bnav__n { position: static; margin: 0; }

  /* Покупка / продажа — один компактный переключатель */
}

/* Строка быстрых фильтров над списком: сколько тонн и через какой город.
   Два поля, с которых начинается разговор о партии. */
.qrow {
  display: flex;
  gap: 8px;
  align-items: center;
  margin: 0 0 12px;
  flex-wrap: wrap;
}
.qrow .input { flex: 1 1 130px; min-width: 0; }
.qrow .btn { flex: 0 0 auto; }

/* Подпись на карточке: продажа или покупка. Цвета те же, что у переключателя
   наверху, — карточка сразу читается как «эту сою продают» / «эту ищут». */
.badge--sell { background: var(--cn-soft); color: var(--cn-ink); }
.badge--buy  { background: var(--ru-soft); color: var(--ru-ink); }

/* Что площадка добавляет к цене фермера. Отдельным блоком, но некрупно:
   это пояснение к полю цены, а не главный элемент экрана. */
.addon {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2px 12px;
  align-items: center;
  margin: 2px 0 10px;
  padding: 9px 12px;
  border: 1px solid var(--ru);
  border-left-width: 3px;
  border-radius: var(--r);
  background: var(--ru-soft);
}
.addon__sum {
  grid-row: span 2;
  font-size: var(--t-md);
  font-weight: var(--w-bold);
  color: var(--ru-ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.addon__text { display: flex; flex-direction: column; }
.addon__text b { font-size: var(--t-sm); color: var(--ink); }
.addon__text span { font-size: var(--t-xs); color: var(--ink-2); }
.addon__list {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 5px;
}
.addon__item {
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: var(--t-xs);
  color: var(--ink-2);
}
@media (max-width: 460px) {
  .addon { grid-template-columns: 1fr; }
  .addon__sum { grid-row: auto; }
}

/* Проба — такая же зелёная плашка, как белок: это признак партии,
   а не выкрик. Отличается только тем, что стоит не у всех. */
.spec--ok { color: var(--ru-ink); font-weight: var(--w-mid); }
.spec--off { color: var(--muted); }

/* Покупатель вписывает свой объём прямо в расчёте. */
.calc__buy { align-items: center; gap: 10px; }
.calc__take { display: flex; align-items: center; gap: 8px; color: var(--ink-2); flex-wrap: wrap; }
.calc__take .input { width: 7.5em; padding: 6px 10px; font-size: var(--t-sm); text-align: right; }
.calc__note--warn { color: var(--warn); }

/* Панель фильтров: галочки в одну строку и без лишнего воздуха —
   это уточнения к полям выше, а не самостоятельный блок. */
.filters .checks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 22px;
  margin: -2px 0 2px;
}
.filters .check { min-height: 0; padding: 6px 0; font-size: var(--t-sm); }
.filters .check input { width: 18px; height: 18px; }
.filters { gap: 12px; }

/* Цена одобрена — зелёная плашка: это главный результат разговора. */

/* Предложение ждёт ответа — та же карточка, но нейтральная. */

/* Итог расчёта — крупнее и заметнее остальных строк. */
.turnkey__row--total {
  margin: 6px -12px -10px;
  padding: 11px 12px;
  border-top: none;
  border-radius: 0 0 var(--r) var(--r);
  background: var(--ru-soft);
  color: var(--ru-ink);
  font-size: var(--t-md);
  font-weight: var(--w-bold);
}
.turnkey__row--total b { color: var(--ru-ink); }

/* Действия по сделке — компактной строкой над ценой, справа. */

/* Две кнопки сделки одной строкой: цена занимает ширину, проба — сбоку.
   На узком экране встают друг под друга. */
@media (max-width: 560px) {
}

/* Высота нижней панели — композер прилипает точно над ней. */
:root { --bottom-h: 0px; }
@media (max-width: 719px) { :root { --bottom-h: 62px; } }

/* Партия, о которой идёт разговор: липкой строкой под шапкой. */

/* ——— переписка: список слева, разговор справа ———

   На широком экране одна колонка выглядела бедно: разговор жался посередине,
   а чтобы перейти к другому собеседнику, надо было возвращаться назад.
   Две колонки — то, как устроен любой почтовый ящик и любой мессенджер, и
   человеку не приходится этому учиться.

   На телефоне колонок нет: остаётся ровно та половина, за которой пришли —
   на /deals список, в разговоре сам разговор. Переключает их не скрипт,
   а класс на обёртке: mail--list или mail--chat. */
.mail {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}
.mail__side { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.mail__sideh {
  font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--muted);
  letter-spacing: 0.04em; text-transform: uppercase;
}
.mail__view { display: flex; flex-direction: column; gap: 14px; min-width: 0; position: relative; }
/* «Добавьте на экран Домой» — одна строка над полем ввода, только Safari на айфоне. */
.a2hs {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 10px 8px 12px; border-radius: var(--r);
  background: var(--ru-soft); color: var(--ru-ink); font-size: var(--t-xs); line-height: var(--lh-tight);
}
.a2hs[hidden] { display: none; }
.a2hs__t { flex: 1; }
.a2hs__x { border: 0; background: transparent; color: inherit; font-size: var(--g-sm); line-height: 1; cursor: pointer; padding: 0 2px; }
body.kbd .a2hs { display: none; }

/* Короткая подсказка над строкой ввода: «запись слишком короткая», «нет
   микрофона», «потяните сообщение вправо». Сама уходит через несколько секунд. */
.note {
  position: absolute; left: 12px; right: 12px; bottom: var(--down-b, 96px);
  z-index: 18; margin: 0 auto; width: fit-content; max-width: min(100%, 380px);
  padding: 10px 16px; border-radius: var(--r);
  background: var(--ink); color: #fff; font-size: var(--t-sm);
  line-height: var(--lh-tight); text-align: center; text-wrap: balance;
  box-shadow: var(--lift-2); opacity: 1; transition: opacity 0.3s ease;
}
.note--out { opacity: 0; }

/* «К последним»: круглая кнопка над строкой ввода, пока лента отмотана вверх. */
.thread__down {
  position: absolute; right: 12px; bottom: var(--down-b, 96px); z-index: 16;
  width: 40px; height: 40px; border: 0; border-radius: 50%; padding: 0;
  background: var(--surface); color: var(--ink-2); box-shadow: var(--lift-btn);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.thread__down[hidden] { display: none; }
.thread__down .ic { width: 22px; height: 22px; }
.mail__pick { padding: 40px 0; }

/* Список прилипает: в длинном разговоре он иначе остаётся где-то вверху,
   и до соседней переписки надо прокручивать обратно. */
@media (min-width: 861px) {
  .mail__side {
    position: sticky; top: 16px;
    max-height: calc(100vh - 120px); overflow-y: auto;
    padding-right: 4px;
  }
  /* Переписке нужна вся ширина: 62rem на две колонки — это узкий разговор
     рядом с узким списком, ради чего огород и не городили. */
  .main--mail { max-width: 78rem; }
  /* Слева и так список — стрелка «← Переписка» здесь лишняя. */
  .main--mail > .back { display: none; }
  /* Внутри своей колонки лента не должна вылезать за её края. */
  .mail .thread { margin: 0; border-radius: var(--r); }
  .mail .composer { bottom: 0; }
  /* Страница-приложение: сама она не едет, едет только лента сообщений.
     Раньше прокручивалось всё разом — шапка с именем, карточка сделки и поле
     ввода уползали вверх вместе с разговором, а при переходе в соседнюю
     переписку страница прыгала вниз, к последнему сообщению. Теперь на месте
     стоят и шапка, и сделка, и поле ввода, а прыгать нечему. */
  body.app { height: 100dvh; min-height: 0; overflow: hidden; }
  body.app .main--mail {
    flex: 1; min-height: 0; overflow: hidden;
    padding-top: 14px; padding-bottom: 14px;
  }
  body.app .mail { height: 100%; min-height: 0; }
  body.app .mail__side { position: static; max-height: 100%; overflow-y: auto; }
  body.app .mail__view { height: 100%; min-height: 0; }
  body.app .mail__view .thread { flex: 1; min-height: 0; overflow-y: auto; }
  /* Липкость больше не нужна: поле ввода и так стоит в самом низу колонки. */
  body.app .composer { position: static; box-shadow: none; }
}

/* Плашка для встроенного браузера WeChat: там хуже со звуком и с
   уведомлениями, и человеку надо один раз сказать, как открыть Safari. */
.wxbar {
  background: var(--warn-soft); color: var(--warn);
  font-size: var(--t-sm); font-weight: var(--w-mid);
  padding: 10px 14px; text-align: center;
}

/* Переключатель разговоров одной сделки: стороны между собой и личные
   каналы с площадкой. Появляется вместе с фиксацией цены. */
.chtabs { display: flex; gap: 6px; margin: 0 0 8px; }
.chtab {
  flex: 1; min-width: 0; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 10px; border-radius: var(--r); border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); text-decoration: none;
  font-size: var(--t-sm); font-weight: var(--w-mid); white-space: nowrap;
}
.chtab--on { background: var(--ru-soft); border-color: var(--ru); color: var(--ru-ink); }
.opsnote { margin: 0 0 8px; font-size: var(--t-sm); color: var(--muted); }
.dlg__n--ops { background: var(--surface-2); color: var(--ink); }
.msg__go { display: block; margin-top: 6px; color: var(--ru-ink); font-weight: var(--w-mid); text-decoration: none; }

/* Закреплённая строка одобрения — только на телефоне; на широком экране
   панель и так стоит на месте, там строка была бы дублем кнопки. */
.pin { display: none; }
.dl__hint { margin: 0 0 8px; }

@media (max-width: 860px) {
  /* Именно minmax(0, 1fr), а не 1fr: у голого 1fr нижняя граница равна
     ширине содержимого, и одна длинная строка в списке переписок растягивала
     колонку шире экрана — страница ехала вбок. */
  .mail { grid-template-columns: minmax(0, 1fr); gap: 0; }

  /* Сделка закреплена под вкладками. Жалоба заказчика: «когда много сообщений,
     надо листать вверх, чтоб одобрить». На телефоне прокручивается вся
     страница, и панель уезжала вместе с ней. Обёртка растянута на всю ширину
     ленты и закрашена, чтобы пузыри под ней не просвечивали. Ниже вкладок
     (z 15), но выше пузырей; поле ввода (17) остаётся главнее. */
  .dealbox {
    position: sticky; top: 0; z-index: 14;
    margin: 0 -14px; padding: 4px 14px 6px;
    background: var(--ground);
  }
  /* У оператора над лентой стоят прилипшие вкладки (52px на телефоне) —
     панель встаёт под них. У фермера и покупателя вкладок на телефоне нет,
     их «Моё» живёт в нижней панели, и панель прилипает к самому верху. */
  .tabs ~ .main .dealbox { top: 52px; }
  .pin {
    display: flex; align-items: center; gap: 10px;
    margin: 0 0 8px; padding: 8px 10px 8px 14px;
    border-radius: var(--r); background: var(--ru-soft); border: 1px solid var(--ru);
  }
  .pin__t {
    flex: 1; min-width: 0; font-weight: var(--w-mid); font-size: var(--t-sm); color: var(--ru-ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .pin__btn { flex: none; }
  /* Прокрутка к непрочитанному не должна прятать его под закреплённую панель. */
  .msg, .thread__sep { scroll-margin-top: 140px; }

  /* Переписка на телефоне — экран-приложение, как и на компьютере.
     Жалобы заказчика: «между Переписка и Написать расстояние» — это были
     48px нижнего отступа .main, торчавшие между полем ввода и нижней панелью;
     и «включаешь чат — переписка вверх лезет» — iPhone при открытии клавиатуры
     прокручивал всю страницу. Теперь страница стоит, высота — видимая область
     (public/chat.js подгоняет её под клавиатуру через visualViewport),
     прокручивается только лента, поле ввода прижато к панели без зазора. */
  /* min-height: 0 обязателен: у body в базе стоит min-height: 100dvh, а
     min-height сильнее height. Без этой строки высота, которую chat.js ставит
     под клавиатуру айфона, молча игнорировалась — поле ввода уходило под
     клавиатуру, а ленту нельзя было долистать до низа. */
  body.app { display: flex; flex-direction: column; height: 100dvh; min-height: 0; overflow: hidden; }
  body.app > .top, body.app > .tabs, body.app > .bottom, body.app > .wxbar { flex: none; }
  body.app .main--mail { flex: 1; min-height: 0; overflow: hidden; padding: 8px var(--pad) 0; gap: 8px; }
  body.app .mail { height: 100%; min-height: 0; }
  body.app .mail__side { max-height: 100%; overflow-y: auto; }
  body.app .mail__view { height: 100%; min-height: 0; gap: 8px; }
  body.app .mail__view .thread { flex: 1; min-height: 0; overflow-y: auto; }
  body.app .composer { position: relative; bottom: auto; box-shadow: none; padding-bottom: 8px; }
  /* Панель всех фраз ложится ПОВЕРХ ленты, а не в колонку: в колонке она
     выталкивала поле ввода за нижнюю панель, и до конца не листалась.
     Теперь поле ввода стоит на месте, панель — над ним, внутри прокручивается. */
  body.app .plus {
    position: absolute; left: 0; right: 0; bottom: 100%; z-index: 18;
    max-height: 55vh; box-shadow: var(--lift-2);
  }

  /* Шапка разговора: на телефоне каждый пиксель — это строка переписки.
     Имя меньше, партия одной строкой с многоточием, «на каком языке читает»
     убрано (оно есть в подсказке под пузырём). */
  body.app .chathead { gap: 2px; }
  body.app .chathead__name { font-size: var(--t-lg); }
  body.app .chathead__lot { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  body.app .chathead__lang { display: none; }
  body.app .back { padding: 0; }
  body.app .opsnote { margin: 0 0 4px; font-size: var(--t-xs); }

  /* Панель сделки на телефоне раскрывается поверх ленты, а не раздвигает
     её: раскрытая «Перевозка» съедала весь экран и переписка исчезала. */
  body.app .dealbox { position: relative; z-index: 14; }
  body.app .deal { overflow: visible; position: relative; margin-bottom: 6px; }
  body.app .deal__in {
    position: absolute; left: -1px; right: -1px; top: calc(100% + 4px);
    max-height: 60vh; overflow-y: auto;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
    box-shadow: var(--lift-2); padding: 10px 12px 12px;
  }
  /* Панель сделки стоит над лентой сама — липкость больше не нужна. */
  body.app .dealbox { position: static; }
  body.app .bottom { position: static; }
  /* Экран разговора: нижняя панель убрана, выход — «← Переписка» в шапке. */
  body.app--focus > .bottom { display: none; }
  /* Клавиатура открыта (класс ставит chat.js): всё, что не лента и не поле
     ввода, уходит — как в мессенджерах, где при наборе видно только разговор. */
  body.kbd > .top, body.kbd .chathead__lot, body.kbd .dealbox { display: none; }
  /* «← Переписка» и имя собеседника остаются — одной тонкой строкой, как
     шапка чата в мессенджере; пропадать целиком они не должны. */
  body.kbd .chathead__name { font-size: var(--t-md); }
  body.kbd .main--mail { padding-top: 4px; gap: 4px; }
  body.kbd .mail__view { gap: 4px; }
  /* Клавиатура закрывает «полоску» айфона — отступ под неё не нужен, иначе
     между полем и клавиатурой пустая полоса. */
  body.kbd .composer { padding-bottom: 4px; }
  /* Без нижней панели поле ввода само упирается в край экрана — отступ
     под «полоску» айфона теперь его. */
  body.app--focus .composer { padding-bottom: calc(8px + env(safe-area-inset-bottom)); }
  .mail--chat .mail__side { display: none; }
  .mail--list .mail__view { display: none; }
  .mail__sideh { display: none; }
}

.dlg--on {
  border-color: var(--ru);
  background: var(--ru-soft);
}
.dlg--on .dlg__name { color: var(--ru-ink); }

/* Шапка разговора: с кем говорим и о какой партии. */
.chathead { display: flex; flex-direction: column; gap: 4px; }
.chathead__name {
  font-size: var(--t-xl); font-weight: var(--w-bold); color: var(--ink);
  text-decoration: none; line-height: var(--lh-tight);
}
.chathead__name:hover { text-decoration: underline; }
.chathead__lot {
  font-size: var(--t-sm); color: var(--muted); text-decoration: none;
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
}
.chathead__lot b { color: var(--ink); font-weight: var(--w-mid); }
.chathead__lot:hover { color: var(--ink-2); }
.chathead__go { color: var(--muted); }
.chathead__lang { font-size: var(--t-xs); color: var(--muted); }

/* На каком языке читает собеседник — одна строка вместо извинения
   за отсутствующий перевод под полем ввода в каждой переписке. */
.head__lang { color: var(--muted); font-size: var(--t-sm); }

/* Пустая переписка: с чего начать разговор с иностранцем. */
.starters { padding: 6px 0 2px; display: flex; flex-direction: column; align-items: center; }
.starters__pic { width: 220px; max-width: 70%; height: auto; display: block; opacity: 0.9; }
.starters__grid { width: 100%; }
.starters__t { color: var(--muted); font-size: var(--t-sm); margin: 0 0 8px; text-align: center; }
.starters__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.starter {
  font: inherit; cursor: pointer; width: 100%; min-height: 62px;
  display: flex; flex-direction: column; gap: 3px; justify-content: center;
  padding: 10px 12px; border-radius: var(--r); text-align: left;
  background: var(--surface); border: 1px solid var(--line); color: var(--ink);
}
.starter:active { background: var(--ru-soft); }
.starter__a { font-weight: var(--w-mid); font-size: var(--t-sm); }
.starter__b { color: var(--muted); font-size: var(--t-sm); }

/* Готовая фраза на языке собеседника — прямо под своим пузырём. */
.msg__also {
  display: block; margin-top: 5px; padding-top: 5px;
  border-top: 1px dashed rgb(128 128 128 / 35%);
  font-size: var(--t-sm); opacity: 0.75;
}

/* ——— полоса быстрых фраз ———
   Она над полем ввода и всегда видна: для половины участников это
   единственный способ написать на языке собеседника. */
.quickbar { display: flex; flex-direction: column; gap: 6px; }
.quickbar__row {
  display: flex; gap: 6px; overflow-x: auto; padding-bottom: 2px;
  scrollbar-width: none; scroll-snap-type: x proximity;
}
.quickbar__row::-webkit-scrollbar { display: none; }
.quickbar__f { flex: none; }
.quickbar .chip { white-space: nowrap; min-height: 38px; scroll-snap-align: start; }
.chip--slot { border-style: dashed; }
.chip--more { background: var(--ru-soft); color: var(--ru-ink); border-color: var(--ru-soft); font-weight: var(--w-mid); }

/* [hidden] у элемента с display:flex не работает — правило автора сильнее
   браузерного. Без этих строк поле числа и панель «Ещё» висят раскрытыми. */
.say[hidden], .plus[hidden], .quickbar__row[hidden] { display: none; }

/* Одно поле для числа или даты — вместо списка на чужом языке. */
/* Фраза с числом: та же таблетка, что «Написать…». Крестик слева на месте
   скрепки, начало фразы серым, число, единица, «отправить» справа. */
.say--slot { align-items: center; }
.say__x {
  flex: none; width: 42px; height: 42px; border: 0; border-radius: 50%;
  background: var(--surface-2); color: var(--ink-2); font-size: var(--g-sm); line-height: 1; cursor: pointer;
}
.say__slotl { flex: none; max-width: 40%; padding-left: 6px; font-size: var(--t-sm); color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.say__num {
  flex: 1; min-width: 0; border: 0; background: transparent; font: inherit; font-size: var(--t-md);
  padding: 11px 4px; text-align: right; font-variant-numeric: tabular-nums;
}
.say__num:focus-visible { outline: none; }
.say__unit { flex: none; padding-right: 6px; font-size: var(--t-sm); color: var(--muted); }

/* Все фразы по группам — поверх ленты, не сдвигая её. */
.plus {
  max-height: 46vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 10px;
  padding: 10px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line);
}
.plus__t {
  position: sticky; top: -10px; z-index: 1;
  background: var(--surface); padding: 2px 0 4px;
  font-size: var(--t-xs); color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em;
}
.plus__row { display: flex; flex-wrap: wrap; gap: 6px; }

/* Ответы на последнюю чужую фразу — под её пузырём, слева. */
.answers { display: flex; flex-wrap: wrap; gap: 6px; align-self: flex-start; margin: -4px 0 2px; }
.answers .chip { min-height: 36px; font-size: var(--t-sm); }

/* На узком экране подпись состояния уводит строку цены в два ряда —
   название важнее, состояние видно по раскрытому блоку. */
@media (max-width: 430px) {
}

/* Сообщение в пути и сообщение, которое не ушло. Второе — кликабельно:
   тап повторяет отправку, потому что «связь моргнула» это норма в поле. */
.msg--pending { opacity: 0.55; }
.msg--failed { opacity: 1; border: 1px solid var(--bad); cursor: pointer; }
.msg--failed::after {
  content: '!'; display: inline-block; margin-left: 8px;
  color: var(--bad); font-weight: var(--w-bold);
}
.say__send:disabled { opacity: 0.4; cursor: default; }

/* Выбранное фото до отправки: видно, что уходит, и можно передумать. */
.photobar {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: var(--r);
  background: var(--surface); border: 1px solid var(--line);
  font-size: var(--t-sm); color: var(--ink-2);
}
.photobar img { width: 40px; height: 40px; object-fit: cover; border-radius: var(--r); }
.photobar span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.photobar__x {
  border: 0; background: var(--surface-2); color: var(--ink); cursor: pointer;
  width: 32px; height: 32px; border-radius: var(--r); font-size: var(--g-sm); line-height: 1;
}

/* Подпись «Доставлено / Прочитано» под последним своим сообщением.
   Живёт внутри .msg__meta рядом со временем: отдельным узлом в .thread
   она стала бы элементом флекс-колонки и уехала влево. */
.msg__st {
  width: 16px; height: 16px; flex: none;
  color: var(--muted);
}
.msg--me .msg__st { color: var(--bub-out-ink); opacity: 0.7; }
.msg--me .msg__st--seen { opacity: 1; }

/* Черта «отсюда непрочитанное». По образцу разделителя дней, но с чертой
   во всю ширину — она должна читаться как граница, а не как ещё одна дата. */
.thread__sep--new {
  align-self: stretch;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 6px 0 2px;
  color: var(--ru);
  font-weight: var(--w-mid);
  font-size: var(--t-xs);
  background: none;
  padding: 0;
}
.thread__sep--new::before,
.thread__sep--new::after {
  content: "";
  flex: 1;
  height: 1px;
  background: currentColor;
  opacity: 0.35;
}

/* Плашка «включить уведомления». Живёт над перепиской и уходит навсегда,
   как только человек ответил — второй раз браузер спросить не даст. */
.pushbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  margin: 0 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface-2);
}
.pushbar[hidden] { display: none; }   /* у флекса атрибут сам по себе не работает */
.pushbar__t { flex: 1 1 200px; font-size: var(--t-sm); }
.pushbar__btns { display: flex; gap: 8px; }

/* ——— панель сделки ———
   Одна строка над разговором. Раньше цена, проба и перевозка стояли тремя
   блоками подряд и выдавливали ленту за нижний край: человек открывал
   переписку и видел формы вместо сообщений. */
.deal {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  margin: 0 0 10px;
  overflow: hidden;
}
.deal__sum {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 36px;
  padding: 5px 12px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.deal__sum::-webkit-details-marker { display: none; }
.deal__ic { width: 26px; height: 26px; flex: none; display: block; object-fit: contain; }
.deal__t { font-weight: var(--w-bold); white-space: nowrap; }
.deal__state {
  flex: 1;
  min-width: 0;
  color: var(--muted);
  font-size: var(--t-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Ход за человеком — говорим об этом цветом, а не ещё одной плашкой. */
.deal__state--act { color: var(--ru); font-weight: var(--w-mid); }
.deal__chev {
  width: 10px; height: 10px; flex: none;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(45deg);
  transition: transform 0.15s ease;
}
.deal[open] .deal__chev { transform: rotate(-135deg); }
.deal__in {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 12px 10px;
}
/* Внутри панели блоки уже не спорят за внимание — снимаем их собственные
   рамки и фон, чтобы не было коробки в коробке. */

/* Содержимое панели сделки: строки «подпись → число» и одна кнопка.
   Раньше внутри панели стояли ещё две карточки со своими рамками и фоном —
   коробка в коробке, из-за чего экран выглядел заваленным. */
.dl { display: flex; flex-direction: column; gap: 2px; }
.dl__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 7px 0;
  font-size: var(--t-sm);
}
.dl__row span { color: var(--muted); }
.dl__row b { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Итог отделён чертой и крупнее: это то число, о котором договариваются. */
/* Черты сверху больше нет: она отделяла итог от слагаемых, а слагаемое
   осталось одно — и черта повисла под заголовком панели сама по себе. */
.dl__row--sum {
  padding-top: 4px;
  font-size: var(--t-md);
}
.dl__row--sum b { font-size: var(--t-lg); font-weight: var(--w-bold); }
.dl__note { padding: 7px 0; color: var(--muted); font-size: var(--t-sm); }
.dl form { margin-top: 10px; }
.dl .hint { margin: 8px 0 0; }

/* Третье действие в панели — не кнопка, а строка: просьба о пробе не должна
   выглядеть так же весомо, как согласие на три миллиона. */
/* ——— строка цены: столько за тонну × столько тонн = столько всего ———
   Раньше это были два поля с подписями сверху и отдельный ряд с итогом —
   три этажа вместо одного, а сказано ровно то же самое. */
.fixrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fixrow__f { flex: 1 1 130px; min-width: 0; }
.fixrow__f--nar { flex: 0 1 96px; }
.fixrow__f .input { height: 40px; padding: 0 10px; }
.fixrow__x, .fixrow__eq { color: var(--muted); flex: none; }
.fixrow__sum {
  margin-left: auto;
  font-size: var(--t-lg); font-weight: var(--w-bold);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
@media (max-width: 420px) {
  /* На узком экране «= сумма» уезжает на свою строку, а не жмёт поля. */
  .fixrow__eq { display: none; }
  .fixrow__sum { flex: 1 0 100%; margin: 0; text-align: right; }
}
.form--fix { gap: 8px; }

/* ——— «Дальше — наша работа» ———
   Логистика, таможня и склад — то, чего покупатель не купит ни у фермера,
   ни сам, и то, ради чего площадка существует. Поэтому не серой строкой внизу,
   а тёплой плашкой прямо над кнопкой: это читают перед нажатием. */
.wedo {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: var(--r);
  background: var(--gold-soft);
}
.wedo__ic { width: 32px; height: 32px; flex: none; display: block; object-fit: contain; }
.wedo__txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* Слева перечень работ, справа — то, что человек получает. Правая часть
   темнее и жирнее: именно она отвечает на вопрос «а мне-то что». */
.wedo__eq {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  font-size: var(--t-sm); font-weight: var(--w-mid); color: var(--ink-2);
  line-height: var(--lh-tight);
}
.wedo__eq i { font-style: normal; color: var(--muted); }
.wedo__eq em { font-style: normal; font-weight: var(--w-bold); color: #8a5d00; }
.wedo__when { font-size: var(--t-xs); color: var(--muted); line-height: var(--lh-tight); }

.dl__minor { display: flex; justify-content: center; margin-top: 2px; }

/* Цена согласована — короткая зелёная строка над суммой. */
.dl__agreed {
  color: var(--ru-ink);
  font-size: var(--t-sm);
  font-weight: var(--w-bold);
}
/* Что делает площадка прямо сейчас. Стоит сразу под согласованной суммой:
   после согласия человек смотрит именно сюда. */
.dl__ship {
  display: flex; flex-direction: column; gap: 2px;
  margin-top: 8px; padding: 10px 12px;
  border-radius: var(--r);
  background: var(--ru-soft);
}
.dl__ship b { color: var(--ru-ink); }
.dl__ship span { color: var(--ink-2); font-size: var(--t-sm); line-height: var(--lh); }
.dl__where { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.dl__where .field { margin: 0; width: 100%; }

/* Обещание под кнопкой: что произойдёт после нажатия. Тихим текстом, но
   на самом видном месте — прямо под тем, что человек собирается нажать.
   Это единственное место, где покупателю говорят, ради чего вся площадка. */
.dl__promise {
  margin: 8px 0 0;
  color: var(--ink-2);
  font-size: var(--t-sm);
  line-height: var(--lh);
}
/* Цена согласована — короткая зелёная строка над суммой. */
.dl__agreed {
  color: var(--ru-ink);
  font-size: var(--t-sm);
  font-weight: var(--w-bold);
}
/* Что делает площадка прямо сейчас. Стоит сразу под согласованной суммой:
   после согласия человек смотрит именно сюда. */
.dl__ship {
  display: flex; flex-direction: column; gap: 2px;
  margin-top: 8px; padding: 10px 12px;
  border-radius: var(--r);
  background: var(--ru-soft);
}
.dl__ship b { color: var(--ru-ink); }
.dl__ship span { color: var(--ink-2); font-size: var(--t-sm); line-height: var(--lh); }
.dl__where { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.dl__where .field { margin: 0; width: 100%; }
.linkbtn {
  font: inherit;
  font-size: var(--t-sm);
  color: var(--muted);
  background: none;
  border: 0;
  padding: 10px 12px;
  min-height: var(--tap);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line);
}
.linkbtn:hover { color: var(--ink); text-decoration-color: currentColor; }

/* Ссылка-кнопка «Отклонить и предложить свою цену» в панели сделки:
   ведёт в ту же плашку, где цифры сменяются полями. Отдельная выпадающая
   коробка под ценой читалась как второй экран внутри первого. */
.dl .btn--ghost { margin-top: 8px; }
.dl .turnkey { margin: 12px 0 0; }
.dl .form { margin: 0; }
.dl .form .row { margin-bottom: 0; }
.dl > .linkbtn { align-self: center; margin-top: 4px; }

/* Когда в расчёте одна строка — итог, — коробка вокруг неё лишняя:
   сверху оставалась пустая белая полоска в высоту исчезнувших строк. */
.turnkey:has(> .turnkey__row--total:only-child) {
  padding: 0;
  border: 0;
  background: none;
}
.turnkey:has(> .turnkey__row--total:only-child) > .turnkey__row--total {
  margin: 0;
  border-radius: var(--r);
}

/* Оценка в отзыве — словом и цветом, а не эмодзи: эмодзи рисует шрифт
   устройства, и на дешёвом Android половина выходит квадратом. */
.rev__mark {
  font-size: var(--t-xs);
  font-weight: var(--w-mid);
  padding: 3px 9px;
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.rev__mark--good { background: var(--ru-soft); color: var(--ru-ink); }
.rev__mark--bad { background: var(--bad-soft); color: var(--bad); }

/* Таймер записи поверх значка микрофона — отдельной подписью: писать его
   в саму кнопку нельзя, там теперь рисунок, а не буква. */
.say__mic { position: relative; }
.say__mic-t {
  position: absolute;
  inset: auto 0 2px 0;
  font-size: var(--t-xs);
  font-weight: var(--w-bold);
  font-variant-numeric: tabular-nums;
}
.say__mic--on .say__ic { opacity: 0.35; }

/* Значок в строке текста: размер наследуется от кнопки, цвет — от текста,
   поэтому тёмная тема подхватывается сама. */
.ic { width: 1.25em; height: 1.25em; flex: none; }
.bnav__ico, .bell__ico { width: 26px; height: 26px; }
.ev__icon { width: 28px; height: 28px; flex: none; }

/* ——— отзывы: звёзды, факты о человеке, ответ ———
   Оценку показываем словом и звёздами, а не числом с запятой: при двух-пяти
   сделках за сезон «4,6» — не статистика, а видимость точности. */
.stars { display: inline-flex; gap: 2px; vertical-align: -2px; }
.stars__s { width: 16px; height: 16px; fill: var(--line); }
.stars__s--on { fill: var(--gold); }

.rep { display: flex; align-items: center; gap: 10px; margin: 0 0 4px; }
.rep__avg { font-size: var(--t-lg); font-weight: var(--w-bold); font-variant-numeric: tabular-nums; }
.rep__n { color: var(--muted); font-size: var(--t-sm); }

/* То, что мы знаем сами: проверен, сколько сделок довёл до конца, с какого месяца.
   Это честнее любых звёзд, потому что не зависит от чужого настроения. */
.facts { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.fact {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-sm); color: var(--ink-2);
  background: var(--surface-2); border-radius: var(--r-pill); padding: 5px 12px;
}
.fact--ok { background: var(--ru-soft); color: var(--ru-ink); font-weight: var(--w-mid); }

.rev__reply {
  border-left: 2px solid var(--line); padding-left: 10px; margin-top: 8px;
}
.rev__reply b { font-size: var(--t-xs); color: var(--muted); font-weight: var(--w-mid); }
.rev__reply p { margin: 2px 0 0; font-size: var(--t-sm); }

/* ——— «Чем закончилось» и оценка ——— */
/* Обратная связь — одной строкой, а не карточкой на весь экран.
   «Чем закончилось?» и три кнопки — в ряд; на узком экране кнопки
   переносятся под вопрос. */
.outcome {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  padding: 6px 8px 6px 14px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
}
.outcome__q { font-weight: var(--w-bold); font-size: var(--t-sm); margin-right: auto; }
.outcome__btns { display: flex; flex-wrap: wrap; gap: 6px; }
.outcome .btn--sm { min-height: 32px; padding: 0 12px; font-size: var(--t-sm); }

/* Отзыв: в покое — одна строка «Оцените продавца ★★★★★». Поле для слов,
   подписи шкалы и кнопка появляются, только когда звезда выбрана. */
.rate {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  padding: 4px 8px 4px 14px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
}
.rate__t { font-weight: var(--w-bold); font-size: var(--t-sm); }
.rate .rate__ends, .rate textarea, .rate .rate__btns { display: none; }
/* Звезда выбрана — рядом встают поле для пары слов и кнопка, в ту же
   строку на широком экране, под звёздами на узком. */
.rate:has(.rate__in:checked) { padding: 6px 8px 6px 14px; }
.rate:has(.rate__in:checked) textarea { display: block; flex: 1 1 240px; min-height: 36px; height: 36px; padding: 7px 10px; resize: none; }
.rate:has(.rate__in:checked) .rate__btns { display: block; flex: none; }
.rate .rate__btns .btn { width: auto; min-height: 36px; padding: 0 16px; font-size: var(--t-sm); }
/* Звёзды идут в разметке от пятой к первой: так соседний селектор гасит
   те, что правее выбранной, без единой строчки скрипта. */
.rate__stars { display: flex; flex-direction: row-reverse; justify-content: flex-end; gap: 4px; }
.rate__in { position: absolute; opacity: 0; width: 1px; height: 1px; }
.rate__star { cursor: pointer; padding: 4px; line-height: 0; }
.rate__star svg { width: 24px; height: 24px; fill: #cfd5d9; transition: fill 0.1s ease; }
.rate__in:checked ~ .rate__star svg,
.rate__star:hover svg,
.rate__star:hover ~ .rate__star svg { fill: var(--gold); }
.rate__in:focus-visible + .rate__star svg { outline: 2px solid var(--ru); outline-offset: 2px; }
.rate__ends { display: flex; justify-content: space-between; font-size: var(--t-xs); color: var(--muted); }

/* ═══════════ Витрина плитками ═══════════
   Выбранное оформление: партии идут плитками, а не длинным списком.
   Плитка узнаваема покупателю с Alibaba, и на экран влезает вдвое больше.
   Всё выше цены имеет заданную высоту — иначе цены разъезжаются по строке,
   потому что «Ханкайский р-н · Камень-Рыболов» вдвое длиннее «Ленинского». */
/* Плитка никогда не уже 230 пикселей: в узкой колонке «через Суйфэньхэ ·
   101 км» ломается на три строки, и ряд перестаёт читаться. Сколько плиток
   поместится — столько и будет. */
.cards--tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 12px;
}
@media (max-width: 520px) {
  /* На телефоне две в ряд: 230px там не помещаются, но и текста меньше. */
  .cards--tiles { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
}

/* Карточки в ряду выравниваются построчно: цена под ценой, отметки под
   отметками, белок под белком. Раньше это держалось на подпорках — каждой
   строке задавали min-height «на две строки текста», — и стоило одной
   карточке остаться без плашки «Пробу предоставляет», а другой уместить
   район в одну строку, как ряд разъезжался.

   Теперь ряд задаёт сетка: карточка занимает четыре строки общей сетки и
   берёт их высоты у неё (subgrid). Высоту каждой строки определяет самая
   высокая карточка ряда, а остальные к ней подстраиваются сами — сколько бы
   строк ни занял район и есть ли у партии отметки. */
.cards--tiles .card {
  padding: 13px;
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 4;
  row-gap: 6px;
  align-content: start;
  /* Без этого длинное слово внутри распирает колонку: у элемента сетки
     min-width по умолчанию не ноль, и на телефоне вторая плитка вылезала
     за край экрана. */
  min-width: 0;
}
.cards--tiles .card__top { display: block; }
.cards--tiles .card__title {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Длинное название района обрезаем на второй строке: без этого одна партия
   с длинным адресом растягивала весь ряд. */
.cards--tiles .card__place {
  line-height: var(--lh-tight);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.cards--tiles .price { display: block; }
/* В плитке места мало, и «Пробу предоставляет» вылезало за край карточки.
   Переносим по словам: subgrid поднимет всю строку ряда одинаково, так что
   от переноса ряд не разъедется. */
.cards--tiles .mark { white-space: normal; }
.cards--tiles .price__unit { display: block; line-height: var(--lh-tight); }
/* Цена с НДС — подробность для страницы партии. В плитке она есть не у всех
   и одна сдвигает вниз всё, что ниже, ломая ряд. */
.cards--tiles .price__alt { display: none; }
.cards--tiles .spec { align-self: flex-start; }
.cards--tiles .specs { flex-direction: column; gap: 0; align-content: start; }
.cards--tiles .specs .spec + .spec::before { content: ""; margin: 0; }

/* Цена — красная: так её читает китайский закупщик у себя дома. */
.price__main { color: var(--cn); }

/* Значки доверия: подтверждено — золотом, объём — нейтрально. */
.marks { display: flex; flex-wrap: wrap; gap: 5px; }
.mark {
  font-size: var(--t-xs); font-weight: var(--w-mid);
  padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--muted);
  white-space: nowrap;
}
.mark--ok { background: var(--gold-soft); color: #8a5d00; }

/* ═══════════ Рабочий стол площадки ═══════════
   На узком экране всё идёт в столбик, как и раньше: поиск, фильтры, партии.
   На широком страница раздаётся вширь, фильтры уезжают в левую колонку и
   остаются на виду при прокрутке, а партии получают всё освободившееся
   место — вместо двух карточек в ряд помещается четыре. Раньше на большом
   мониторе по бокам оставались пустые поля, а список жался в узкую полосу. */
.work { display: flex; flex-direction: column; gap: 14px; }
.work__side { display: flex; flex-direction: column; gap: 14px; }
/* Колонка партий — столбик с одинаковыми промежутками: у заголовков и
   абзацев отступы сняты глобально, и без gap подпись гостевой витрины
   слиплась бы с карточками. */
.work__main { min-width: 0; display: flex; flex-direction: column; gap: 14px; }

@media (min-width: 1080px) {
  .main--work { max-width: 82rem; }
  .work {
    display: grid; grid-template-columns: 290px minmax(0, 1fr);
    gap: 22px; align-items: start;
  }
  .work__side { position: sticky; top: 16px; }
  /* В своей колонке фильтры — панель, а не сворачиваемая полоска:
     заголовок с подсказкой «Фильтры» там лишний. */
  .work__side .fbox__sum { display: none; }
  .work__side .filters { padding-top: 14px; }
  /* Строка поиска в узкой колонке встаёт столбиком: иначе список регионов
     сжимается до «Весь Дальн…» и его не прочитать. */
  .work__side .qrow { flex-direction: column; align-items: stretch; margin: 0; }
  .work__side .qrow .input,
  .work__side .qrow .select,
  .work__side .qrow .btn { width: 100%; flex: none; }
}

/* ═══════════ Объём ═══════════
   Плоские рамки заменены на подъём: карточка лежит на фоне, кнопка выступает,
   нажатая — проваливается. Это и есть «объём» без картинок и без библиотек:
   тень, лёгкий градиент и сдвиг при нажатии. */
:root {
  --lift-1: 0 1px 2px rgb(16 20 24 / 6%), 0 2px 8px -2px rgb(16 20 24 / 8%);
  --lift-2: 0 2px 4px rgb(16 20 24 / 7%), 0 12px 24px -8px rgb(16 20 24 / 14%);
  --lift-btn: 0 1px 0 rgb(255 255 255 / 22%) inset, 0 2px 6px rgb(20 110 45 / 28%);
}
.card {
  border-color: transparent;
  box-shadow: var(--lift-1);
  transition: box-shadow 0.15s ease, transform 0.12s ease;
}
.card--link:active { transform: translateY(1px); box-shadow: var(--lift-1); }
@media (hover: hover) {
  .card--link:hover { box-shadow: var(--lift-2); border-color: transparent; transform: translateY(-1px); }
}

/* Кнопка действия: светлый кант сверху, тень снизу — палец видит, что она
   выступает. При нажатии уходит вниз, как настоящая. */
.btn {
  background-image: linear-gradient(180deg, rgb(255 255 255 / 14%), rgb(0 0 0 / 6%));
  box-shadow: var(--lift-btn);
  transition: transform 0.08s ease, box-shadow 0.12s ease, filter 0.12s ease;
}
.btn:active { transform: translateY(1px); box-shadow: 0 1px 3px rgb(20 110 45 / 30%); }
.btn--ghost, .btn--quiet {
  background-image: none;
  box-shadow: var(--lift-1);
}
.btn--ghost:active, .btn--quiet:active { transform: translateY(1px); box-shadow: none; }

/* Поля ввода — вдавленные, в противоположность кнопкам. */
.input, textarea.input, select.input {
  box-shadow: 0 1px 2px rgb(16 20 24 / 5%) inset;
  border-color: var(--line);
}

/* Пузыри переписки поднимаются над лентой. */
.msg--them { box-shadow: var(--lift-1); border-color: transparent; }
.msg--me { box-shadow: 0 2px 6px rgb(20 110 45 / 24%); }

/* Плитка партии: воздуха больше, строки не липнут друг к другу. */
.cards--tiles { gap: 12px; }
.cards--tiles .card { padding: 15px; }
.cards--tiles .card__title { font-size: var(--t-md); }
.cards--tiles .card__place { font-size: var(--t-sm); }
.cards--tiles .specs { gap: 3px 0; }
.cards--tiles .spec { line-height: 1.45; }
.cards--tiles .price { margin-top: 8px; }
.cards--tiles .marks { margin-top: 8px; }
.cards--tiles .specs { margin-top: 8px; }

/* ——— Компактная шапка разговора на широком экране ———
   Заказчик: «заполнить пространство, чтобы переписка была длиннее видна, и
   плашки аккуратнее». Было три строки над лентой: имя, вкладки на всю
   ширину, «Перевозка» на всю ширину. Теперь вкладки и сделка стоят в одну
   строку, раскрытая сделка ложится поверх ленты (как на телефоне), шапка
   плотнее — ленте достаётся ~110 px. */
@media (min-width: 861px) {
  body.app .mail__view { gap: 8px; }
  body.app .chathead { gap: 2px; }
  body.app .chathead__name { font-size: var(--t-lg); }
  body.app .dealbox {
    display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px;
    position: relative; z-index: 14; margin: 0; padding: 0; background: none;
  }
  body.app .dealbox .chtabs { flex: none; margin: 0; }
  body.app .dealbox .chtab { flex: none; padding: 7px 14px; }
  body.app .dealbox .deal { flex: 1 1 260px; min-width: 0; margin: 0; overflow: visible; position: relative; }
  body.app .dealbox .deal__sum { min-height: 36px; height: 100%; padding: 4px 12px; }
  body.app .dealbox .deal__in {
    position: absolute; left: -1px; right: -1px; top: calc(100% + 4px);
    max-height: 60vh; overflow-y: auto; padding: 10px 14px 14px;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
    box-shadow: var(--lift-2);
  }
  body.app .dealbox .opsnote { flex-basis: 100%; margin: 0; font-size: var(--t-xs); }
  body.app .thread { border-radius: var(--r); }
}
/* Узкий экран: «Оцените покупателя» и пять звёзд — тоже в одну строку. */
@media (max-width: 520px) {
  .rate__t { font-size: var(--t-xs); }
  .rate__star { padding: 2px; }
  .rate__star svg { width: 22px; height: 22px; }
  .outcome__q { font-size: var(--t-xs); }
}

/* ═══════════ Обновление интерфейса 12.10.2026 ═══════════ */

/* Значки перед характеристиками и местом партии. */
.spec__ic { width: 18px; height: 18px; display: inline-block; vertical-align: -4px; margin-right: 4px; object-fit: contain; }
.card__place .spec__ic { width: 16px; height: 16px; vertical-align: -3px; margin-right: 3px; }

/* Мои партии: отклики и просмотры — чипами, отклики подсвечены. */
.lotstat { display: flex; gap: 6px; margin-top: -4px; }
.lotstat__i {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px 4px 6px; border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--ink-2); font-size: var(--t-xs);
}
.lotstat__i img { width: 18px; height: 18px; }
.lotstat__i b { color: var(--ink); }
.lotstat__i--on { background: var(--ru-soft); color: var(--ru-ink); }

/* Страница партии на широком экране: слева партия, справа расчёт и кнопка. */
.lotgrid { display: flex; flex-direction: column; gap: 18px; }
.lotgrid__main, .lotgrid__side { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
@media (min-width: 900px) {
  .lotgrid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(300px, 1fr); align-items: start; gap: 24px; }
  .lotgrid__side { position: sticky; top: 16px; }
}

/* Витрина: карточки появляются волной, на компьютере приподнимаются
   под мышью. Без библиотек; «уменьшить движение» всё это выключает. */
@keyframes card-in { from { opacity: 0; translate: 0 10px; } }
.cards--tiles > .card { animation: card-in 0.32s ease-out both; }
.cards--tiles > .card:nth-child(2) { animation-delay: 30ms; }
.cards--tiles > .card:nth-child(3) { animation-delay: 60ms; }
.cards--tiles > .card:nth-child(4) { animation-delay: 90ms; }
.cards--tiles > .card:nth-child(5) { animation-delay: 120ms; }
.cards--tiles > .card:nth-child(6) { animation-delay: 150ms; }
.cards--tiles > .card:nth-child(7) { animation-delay: 180ms; }
.cards--tiles > .card:nth-child(n+8) { animation-delay: 210ms; }
@media (hover: hover) {
  .card--link { transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease; }
  .card--link:hover { transform: translateY(-2px); box-shadow: var(--lift-2); }
}

/* Список переписок: выбранный разговор плавно подсвечивается. */
.dlg { transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.12s ease; }
@media (hover: hover) { .dlg:hover { transform: translateX(2px); } }

/* Картинка в карточке партии: своё фото или одна из пяти соевых картинок.
   Плашка «Новая» — партии младше суток, с мягкой пульсирующей точкой. */
.card__pic {
  position: relative; height: 104px; margin: -13px -13px 2px; overflow: hidden;
  border-radius: var(--r) var(--r) 0 0;
  background: linear-gradient(160deg, #fbf6e6, #eef4e6);
  display: flex; align-items: center; justify-content: center;
}
.cards--tiles .card .card__pic { margin: -15px -15px 2px; }
.card__pic img { max-width: 86%; max-height: 92px; object-fit: contain; transition: transform 0.25s ease; }
.card__pic img.card__photo { max-width: none; max-height: none; width: 100%; height: 100%; object-fit: cover; }
@media (hover: hover) { .card--link:hover .card__pic img { transform: scale(1.05); } }
.cards:not(.cards--tiles) .card__pic { display: none; }
.card__new {
  position: absolute; top: 8px; left: 8px;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px 3px 7px; border-radius: var(--r-pill);
  background: var(--surface); color: var(--ru-ink);
  font-size: var(--t-xs); font-weight: var(--w-bold); box-shadow: var(--lift-1);
}
.card__new::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--ru);
  animation: new-dot 1.6s ease-in-out infinite;
}
@keyframes new-dot { 50% { box-shadow: 0 0 0 4px rgb(31 157 61 / 18%); } }

/* Пустые экраны с иллюстрацией: картинка крупнее и мягко «дышит». */
.empty--pic .empty__pic { width: 140px; height: 140px; object-fit: contain; animation: float 3.2s ease-in-out infinite; }
@keyframes float { 50% { translate: 0 -6px; } }

/* Порядок витрины — таблетками. */
.sortbar { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.sortbar__a {
  padding: 6px 14px; border-radius: var(--r-pill); font-size: var(--t-sm); font-weight: var(--w-mid);
  background: var(--surface); border: 1px solid var(--line); color: var(--ink-2); text-decoration: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.sortbar__a:hover { border-color: var(--ru); color: var(--ink); }
.sortbar__a--on { background: var(--ru-soft); border-color: var(--ru); color: var(--ru-ink); }

/* ═══ Широкий экран: одна шапка и шире рабочая область ═══
   Заказчик: «много места взято не очень правильно». Было две строки сверху
   (логотип с колокольчиком и отдельной полосой — разделы) и узкая колонка
   62rem посреди экрана в 2000 px. Теперь на экране от 1280 px разделы стоят
   в той же строке, что и логотип, а рабочая область шире — 80rem. */
@media (min-width: 1280px) {
  .top__in, .tabs__in, .bottom__in, .main--wide, .foot { max-width: 80rem; }
  body:has(.bottom) .top { position: relative; }
  body:has(.bottom) .top__in { min-height: 60px; }
  .bottom {
    position: absolute; top: env(safe-area-inset-top); left: 0; right: 0;
    z-index: 30; border: 0; background: none; pointer-events: none;
  }
  .bottom__in { justify-content: center; pointer-events: auto; width: max-content; }
  .bnav { padding: 18px 14px 16px; border-bottom-width: 3px; }
}

/* Телефон: плитки снова в две колонки — с картинкой одна колонка давала
   одну партию на экран. Картинка ниже, таблетки порядка — в строку с прокруткой. */
@media (max-width: 520px) {
  .card__pic { height: 78px; }
  .card__pic img { max-height: 68px; }
  .cards--tiles .card .card__pic { margin: -13px -13px 2px; }
  .sortbar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-right: calc(-1 * var(--pad)); padding-right: var(--pad); }
  .sortbar::-webkit-scrollbar { display: none; }
  .sortbar__a { flex: none; padding: 6px 12px; }
}

/* ——— Страница партии: таблица характеристик и продавец ——— */
.lotinfo { display: flex; flex-direction: column; gap: 14px; }
.lotinfo__price { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.lotinfo__price .price { margin: 0; }
.facts { margin: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 20px; }
.facts__row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--line-soft); min-width: 0;
}
.facts dt { color: var(--muted); font-size: var(--t-sm); display: flex; align-items: center; gap: 6px; }
.facts dt .spec__ic { margin: 0; vertical-align: 0; }
.facts dd { margin: 0; font-weight: var(--w-mid); text-align: right; font-variant-numeric: tabular-nums; }
.facts__hi { color: var(--ink); font-weight: var(--w-bold); }
.facts__dot { width: 18px; height: 18px; flex: none; display: inline-flex; align-items: center; justify-content: center; }
.facts__dot::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--line); }
@media (max-width: 520px) { .facts { grid-template-columns: minmax(0, 1fr); } }

.sellerbox {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border-radius: var(--r); background: var(--surface-2); color: var(--ink); text-decoration: none;
  transition: background-color 0.15s ease;
}
.sellerbox:hover { background: var(--ru-soft); }
.sellerbox__ic { width: 40px; height: 40px; flex: none; }
.sellerbox__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.sellerbox__name { font-weight: var(--w-bold); }
.sellerbox__ok { color: var(--ru-ink); font-size: var(--t-xs); font-weight: var(--w-mid); white-space: nowrap; }
.sellerbox__meta { display: flex; flex-wrap: wrap; gap: 2px 14px; font-size: var(--t-xs); color: var(--muted); }
.sellerbox__meta b { color: var(--ink); }
.sellerbox__go { color: var(--muted); }

/* ——— «Во сколько встанет»: объём, итог, условия доставки ——— */
.buy { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; box-shadow: var(--lift-1); }
.buy__head { display: flex; align-items: center; gap: 10px; padding: 14px 16px 6px; font-weight: var(--w-bold); font-size: var(--t-md); }
.buy__head img { width: 28px; height: 28px; }
.buy__vol { padding: 8px 16px 14px; display: flex; flex-direction: column; gap: 10px; }
.buy__label { font-size: var(--t-xs); color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.buy__step { display: flex; align-items: stretch; gap: 8px; }
.buy__pm {
  flex: none; width: 44px; border: 1px solid var(--line); border-radius: var(--r); background: var(--surface-2);
  font-size: var(--t-lg); font-weight: var(--w-bold); color: var(--ink-2); cursor: pointer;
  transition: background-color 0.15s ease, transform 0.1s ease;
}
.buy__pm:hover { background: var(--ru-soft); color: var(--ru-ink); }
.buy__pm:active { transform: scale(0.94); }
.buy__num {
  flex: 1; display: flex; align-items: center; gap: 6px; padding: 0 14px;
  border: 1.5px solid var(--line); border-radius: var(--r); background: var(--surface);
  transition: border-color 0.15s ease;
}
.buy__num:focus-within { border-color: var(--ru); }
.buy__num .input { border: 0; padding: 10px 0; text-align: center; font-size: var(--t-lg); font-weight: var(--w-bold); background: none; width: 100%; min-width: 0; font-variant-numeric: tabular-nums; }
.buy__num .input:focus-visible { outline: none; }
.buy__num span { color: var(--muted); font-weight: var(--w-mid); }
.buy__range {
  -webkit-appearance: none; appearance: none; width: 100%; height: 6px; border-radius: var(--r-pill); margin: 4px 0;
  background: linear-gradient(90deg, var(--ru) var(--fill, 100%), var(--line) var(--fill, 100%)); cursor: pointer;
}
.buy__range::-webkit-slider-thumb { -webkit-appearance: none; width: 22px; height: 22px; border-radius: 50%; background: #fff; border: 3px solid var(--ru); box-shadow: var(--lift-1); }
.buy__range::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: #fff; border: 3px solid var(--ru); }
.buy__quick { display: flex; gap: 6px; flex-wrap: wrap; }
.buy__chip {
  border: 1px solid var(--line); background: var(--surface); border-radius: var(--r-pill); padding: 5px 12px;
  font: inherit; font-size: var(--t-xs); font-weight: var(--w-mid); color: var(--ink-2); cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.buy__chip:hover, .buy__chip--on { background: var(--ru-soft); border-color: var(--ru); color: var(--ru-ink); }
.buy__total { padding: 14px 16px; background: linear-gradient(135deg, var(--ru-soft), #f3f9ec); border-top: 1px solid var(--line-soft); }
.buy__sumlabel { font-size: var(--t-xs); color: var(--ru-ink); font-weight: var(--w-mid); text-transform: uppercase; letter-spacing: 0.04em; }
.buy__sum { font-size: var(--t-xl); font-weight: var(--w-bold); color: var(--ru-ink); font-variant-numeric: tabular-nums; line-height: 1.2; margin: 2px 0; }
.buy__sum--tick { animation: tick 0.35s ease-out; }
@keyframes tick { 40% { transform: scale(1.04); } }
.buy__formula { font-size: var(--t-xs); color: var(--ink-2); font-variant-numeric: tabular-nums; }
.buy__warn { padding: 10px 16px; font-size: var(--t-sm); color: var(--warn); background: var(--warn-soft); }
.buy__warn[hidden] { display: none; }
.buy__info { display: flex; gap: 10px; align-items: flex-start; padding: 12px 16px 14px; font-size: var(--t-sm); color: var(--ink-2); line-height: var(--lh-tight); border-top: 1px solid var(--line-soft); }
.buy__info img { flex: none; width: 26px; height: 26px; margin-top: 1px; }

/* ═══ Плотнее (13.10): отметки на картинке, фильтры полосой сверху ═══ */
.card__marks { position: absolute; right: 8px; bottom: 8px; display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.card__marks .mark { background: rgb(255 255 255 / 92%); box-shadow: var(--lift-1); font-size: var(--t-xs); padding: 2px 8px; }
.card__marks .mark--ok { color: var(--ru-ink); }
.cards--tiles .specs { flex-direction: row; flex-wrap: nowrap; white-space: nowrap; overflow: hidden; gap: 0 12px; align-items: center; }
.cards--tiles .specs .spec + .spec::before { content: none; }


/* Перевозка — шаги полоской. Пройденные зелёные с галочкой, текущий пульсирует. */
.track { list-style: none; margin: 4px 0 2px; padding: 0; display: flex; }
.track__s { flex: 1; position: relative; display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.track__s::before {
  content: ''; position: absolute; top: 10px; left: -50%; right: 50%; height: 3px; background: var(--line);
}
.track__s:first-child::before { display: none; }
.track__s--done::before, .track__s--now::before { background: var(--ru); }
.track__dot {
  position: relative; z-index: 1; width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--line);
  display: flex; align-items: center; justify-content: center; font-size: var(--t-xs); color: #fff; font-weight: var(--w-bold);
}
.track__s--done .track__dot { background: var(--ru); border-color: var(--ru); }
.track__s--now .track__dot { border-color: var(--ru); box-shadow: 0 0 0 4px rgb(31 157 61 / 18%); animation: new-dot 1.6s ease-in-out infinite; }
.track__s--now .track__dot::after { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--ru); }
.track__t { font-size: var(--t-xs); color: var(--muted); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.track__s--done .track__t, .track__s--now .track__t { color: var(--ink); font-weight: var(--w-mid); }

/* Подсказка китайскому покупателю один раз: как узнать об ответе фермера. */
.hello {
  display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px;
  border-radius: var(--r); background: linear-gradient(135deg, var(--ru-soft), #f6faee);
  border: 1px solid rgb(31 157 61 / 25%);
}
.hello[hidden] { display: none; }
.hello__ic { width: 40px; height: 40px; flex: none; }
.hello__t { flex: 1; display: flex; flex-direction: column; gap: 3px; font-size: var(--t-sm); color: var(--ink-2); line-height: var(--lh-tight); }
.hello__t b { color: var(--ink); font-size: var(--t-md); }
.hello__x { border: 0; background: none; font-size: var(--g-sm); color: var(--muted); cursor: pointer; line-height: 1; padding: 0 2px; }

/* Полоса «сумма + написать продавцу» на телефоне. */
.lotbar { display: none; }
@media (max-width: 899px) {
  .lotbar {
    display: flex; align-items: center; gap: 10px;
    position: fixed; left: 8px; right: 8px; z-index: 20;
    bottom: calc(var(--bottom-h, 0px) + env(safe-area-inset-bottom) + 8px);
    padding: 8px 8px 8px 14px; border-radius: var(--r);
    background: var(--surface); box-shadow: var(--lift-2); border: 1px solid var(--line);
    transition: transform 0.2s ease, opacity 0.2s ease;
  }
  .lotbar--off { transform: translateY(140%); opacity: 0; pointer-events: none; }
  .lotbar__sum { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
  .lotbar__sum b { font-size: var(--t-md); color: var(--ru-ink); font-variant-numeric: tabular-nums; }
  .lotbar__sum small { font-size: var(--t-xs); color: var(--muted); }
  .lotbar .btn { flex: none; min-height: 42px; padding: 0 16px; font-size: var(--t-sm); }
  /* Чтобы полоса не закрывала конец страницы. */
  .lotgrid { padding-bottom: 72px; }
  /* Характеристики в плитках на телефоне — переносом, иначе год обрезается. */
  .cards--tiles .specs { flex-wrap: wrap; gap: 2px 10px; }
}

/* ——— Под фильтрами: сводка по площадке и «как проходит сделка» ——— */
.mkt { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: 14px; display: flex; flex-direction: column; gap: 10px; }
.mkt__h { font-size: var(--t-md); margin: 0; }
.how { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.how li { display: flex; gap: 10px; align-items: flex-start; }
.how img { width: 32px; height: 32px; flex: none; }
.how span { display: flex; flex-direction: column; font-size: var(--t-xs); color: var(--muted); line-height: var(--lh-tight); }
.how b { font-size: var(--t-sm); color: var(--ink); }

@media (min-width: 1080px) { .work__side { position: static; } }


/* ═══ Боковая колонка витрины на компьютере: одна панель поиска ═══ */
@media (min-width: 1080px) {
  .work__side { gap: 0; }
  /* Строка цены/региона и подробные фильтры — одна карточка. */
  .work__side .qrow {
    background: var(--surface); border: 1px solid var(--line); border-bottom: 0;
    border-radius: var(--r) var(--r) 0 0; padding: 14px 14px 4px; gap: 8px;
  }
  .work__side .qrow::before {
    content: attr(data-title); font-size: var(--t-xs); font-weight: var(--w-bold);
    color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em;
  }
  .work__side .qrow .btn { display: none; }   /* одна кнопка «Показать» — внизу панели */
  .work__side .fbox { border-top: 0; border-radius: 0 0 var(--r) var(--r); box-shadow: none; margin-bottom: 14px; }
  .work__side .filters { padding: 6px 14px 14px; gap: 12px; }
  .work__side .filters .field__label { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
  /* Галочки — переключателями-таблетками. */
  .work__side .filters .checks { display: flex; flex-direction: column; gap: 6px; }
  .work__side .filters .check {
    min-height: 40px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-pill);
    font-size: var(--t-sm); transition: background-color 0.15s ease, border-color 0.15s ease;
  }
  .work__side .filters .check:has(input:checked) { background: var(--ru-soft); border-color: var(--ru); color: var(--ru-ink); font-weight: var(--w-mid); }
  .work__side .filters .check input { width: 18px; height: 18px; }
  .work__side .filters .btns { display: flex; align-items: center; gap: 10px; }
  .work__side .filters .btns .btn:first-child { flex: 1; }
  .work__side .filters .btns .btn--ghost { border: 0; background: none; box-shadow: none; color: var(--muted); padding: 0 6px; text-decoration: underline; }
}

/* «Как проходит сделка» — шаги на линии, с номерами. */
.how { position: relative; gap: 14px; }
.how::before { content: ''; position: absolute; left: 19px; top: 20px; bottom: 20px; width: 2px; background: linear-gradient(var(--ru-soft), var(--ru), var(--ru-soft)); }
.how li { position: relative; align-items: center; }
.how__ic {
  position: relative; flex: none; width: 40px; height: 40px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--lift-1);
  display: flex; align-items: center; justify-content: center;
}
.how__ic img { width: 26px; height: 26px; }
.how__ic i {
  position: absolute; top: -4px; right: -6px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--ru); color: #fff; font-style: normal; font-size: var(--t-xs); font-weight: var(--w-bold);
  display: flex; align-items: center; justify-content: center; line-height: 1;
}
.how__t { display: flex; flex-direction: column; gap: 1px; font-size: var(--t-xs); color: var(--muted); line-height: var(--lh-tight); }
.how__t b { font-size: var(--t-sm); color: var(--ink); }
.mkt--how { background: linear-gradient(180deg, var(--surface), #f6faf2); }
.mkt--how .mkt__h { font-size: var(--t-sm); text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }

/* ═══ Телефон и планшет: та же панель фильтров, что на компьютере ═══
   Поиск и подробные фильтры — одна карточка; «Как проходит сделка» —
   под партиями, чтобы новичок увидел её, но партии были первыми. */
@media (max-width: 1079px) {
  .work__side { display: contents; }
  .work { display: flex; flex-direction: column; }
  .work__side > .qrow { order: 1; }
  .work__side > .fbox { order: 2; }
  .work__main { order: 3; }
  .work__side > .mkt { order: 4; margin-top: 4px; }

  .work__side .qrow {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: 8px; margin: 0;
    background: var(--surface); border: 1px solid var(--line); border-bottom: 0;
    border-radius: var(--r) var(--r) 0 0; padding: 12px 12px 6px;
  }
  .work__side .qrow .btn { display: none; }   /* регион применяется сам, цена — кнопкой «Найти» на клавиатуре */
  .work__side .fbox { border-top: 1px dashed var(--line); border-radius: 0 0 var(--r) var(--r); margin: 0; box-shadow: var(--lift-1); }
  .work__side .fbox .fbox__sum { padding-top: 10px; padding-bottom: 10px; }
  .work__side .filters { gap: 10px; }
  .work__side .filters .row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .work__side .filters .field__label { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
  .work__side .filters .checks { display: flex; flex-wrap: wrap; gap: 6px; }
  .work__side .filters .check {
    min-height: 38px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-pill); font-size: var(--t-sm);
  }
  .work__side .filters .check:has(input:checked) { background: var(--ru-soft); border-color: var(--ru); color: var(--ru-ink); font-weight: var(--w-mid); }
  .work__side .filters .check input { width: 18px; height: 18px; }
  .work__side .filters .btns { display: flex; align-items: center; gap: 12px; }
  .work__side .filters .btns .btn:first-child { flex: 1; }
  .work__side .filters .btns .btn--ghost { border: 0; background: none; box-shadow: none; color: var(--muted); text-decoration: underline; padding: 0 4px; }
}

/* ═══════════ Инструкция /help ═══════════ */
.mkt__more { font-size: var(--t-sm); font-weight: var(--w-mid); color: var(--ru-ink); text-decoration: none; }
.mkt__more:hover { text-decoration: underline; }

.hhero { text-align: center; display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 8px 0 6px; }
.hhero__pic { width: min(320px, 70%); height: auto; }
.hhero h1 { font-size: var(--t-xl); text-wrap: balance; }
.hhero p { color: var(--ink-2); max-width: 34rem; text-wrap: balance; }
.hswitch { display: inline-flex; gap: 6px; padding: 5px; margin-top: 6px; border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--line); box-shadow: var(--lift-1); }
.hswitch__b {
  display: inline-flex; align-items: center; gap: 8px; border: 0; cursor: pointer; font: inherit; font-weight: var(--w-mid);
  padding: 8px 16px 8px 10px; border-radius: var(--r-pill); background: none; color: var(--ink-2);
  transition: background-color 0.2s ease, color 0.2s ease;
}
.hswitch__b img { width: 28px; height: 28px; }
.hswitch__b--on { background: var(--ru-soft); color: var(--ru-ink); }

.hsteps { list-style: none; margin: 18px 0 0; padding: 0; display: flex; flex-direction: column; gap: 36px; position: relative; }
.hsteps[hidden] { display: none; }
.hstep { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; align-items: center; }
.hstep__phone { display: flex; justify-content: center; }
.hstep__text { display: flex; flex-direction: column; gap: 6px; }
.hstep__n { font-size: var(--t-xs); font-weight: var(--w-bold); text-transform: uppercase; letter-spacing: 0.06em; color: var(--ru-ink); }
.hstep__text h3 { font-size: var(--t-xl); line-height: var(--lh-tight); text-wrap: balance; }
.hstep__text p { color: var(--ink-2); max-width: 30rem; }
@media (min-width: 860px) {
  .hstep { grid-template-columns: 300px minmax(0, 1fr); gap: 48px; padding: 0 40px; }
  .hstep--flip { grid-template-columns: minmax(0, 1fr) 300px; }
  .hstep--flip .hstep__phone { order: 2; }
  .hstep--flip .hstep__text { text-align: right; align-items: flex-end; }
}

/* Рамка телефона вокруг снимка. */
.phone {
  --r-phone: 38px; --r-screen: 30px; --r-notch: 12px;
  position: relative; width: 260px; aspect-ratio: 585 / 1266; padding: 9px; border-radius: var(--r-phone);
  background: linear-gradient(145deg, #2a2f33, #101418); box-shadow: 0 24px 50px -18px rgb(16 20 24 / 45%), inset 0 0 0 2px #3a4045;
}
.phone__screen { position: relative; width: 100%; height: 100%; border-radius: var(--r-screen); overflow: hidden; }
.phone img { display: block; width: 100%; height: 100%; object-fit: cover; }
.phone::before { content: ''; position: absolute; top: 15px; left: 50%; translate: -50% 0; width: 76px; height: 20px; border-radius: var(--r-notch); background: #101418; z-index: 2; }
/* «Нажмите здесь»: точка + расходящееся кольцо. Анимируются только transform
   и opacity — это не перерисовывает снимок, и только у шага на экране. */
.phone__tap {
  position: absolute; width: 30px; height: 30px; margin: -15px 0 0 -15px; border-radius: 50%;
  background: rgb(31 157 61 / 35%); border: 2px solid #fff; box-shadow: 0 2px 6px rgb(16 20 24 / 30%); z-index: 3; pointer-events: none;
}
.phone__tap::after {
  content: ''; position: absolute; inset: -2px; border-radius: 50%; border: 2px solid rgb(31 157 61 / 80%); opacity: 0;
}
.hstep.is-live .phone__tap::after { animation: tap 1.8s ease-out infinite; }
@keyframes tap {
  0% { transform: scale(1); opacity: 0.9; }
  100% { transform: scale(2.2); opacity: 0; }
}

/* Шаги проявляются при прокрутке: телефон подъезжает сбоку, текст снизу. */
[data-reveal] { opacity: 0; translate: 0 24px; transition: opacity 0.6s ease, translate 0.6s ease; }
[data-reveal].is-in { opacity: 1; translate: 0 0; }
.hstep .phone { transition: transform 0.7s cubic-bezier(.2,.8,.2,1); transform: translateX(-30px); }
.hstep--flip .phone { transform: translateX(30px); }
.hstep.is-in .phone { transform: none; }

.hcta { display: flex; justify-content: center; padding: 26px 0 8px; }
.hcta .btn { min-width: 220px; }
@media (prefers-reduced-motion: reduce) { [data-reveal] { opacity: 1; translate: none; } .hstep .phone, .hstep--flip .phone { transform: none; } .hstep.is-live .phone__tap::after { animation: none; } }
.hsteps { max-width: 880px; margin-left: auto; margin-right: auto; width: 100%; }
@media (min-width: 860px) { .hstep { padding: 0; } }
