/* Раздел «Найти цену»: подбор, удобства экрана, траты. */

/* --- раздел «Найти цену» ---------------------------------------------
   Список материалов сверху, лист найденного снизу — один экран на весь путь.
   Стили дописаны в конец файла и ничего выше не переопределяют: лист берёт
   готовые `.sheet`/`table.rows`, своё здесь только ввод и ход поиска. */

.ceny-vvod {
  display: grid;
  grid-template-columns: 1fr 260px;
  /* Колонки выравниваются по ВЕРХУ, а не тянутся друг за другом: справа стоит
     длинное объяснение про поставщиков, и без этой строки поле списка
     растягивалось под него, оставляя под собой пустую половину экрана
     (замечено на снимке прода 27.08.2026). */
  align-items: start;
  gap: 16px;
  background: var(--paper);
  border: 1px solid var(--bd);
  border-radius: var(--r-lg);
  padding: 16px;
  box-shadow: var(--sh-1);
}
/* Поле и колонка номеров едут одной сеткой: номер обязан стоять напротив
   своей строки, иначе он хуже, чем его отсутствие. */
.ceny-pole { display: grid; grid-template-columns: 34px 1fr; }
.ceny-nomera {
  font: 400 13px/1.55 var(--mono);
  color: var(--fg-3);
  text-align: right;
  padding: 10px 8px 10px 0;
  user-select: none;
  white-space: pre;
  overflow: hidden;
}
/* У `textarea` в проекте нет общего правила — задаём своё целиком. */
.ceny-pole textarea {
  font: 400 13px/1.55 var(--mono);
  color: var(--ink);
  background: var(--sunken);
  border: 1px solid var(--bd-2);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  /* Растянуть поле рукой можно всегда: скрипт растит его по содержимому, но
     последнее слово за человеком (`app.js`, модуль растущего поля). */
  resize: vertical;
  /* Пять строк вместо десяти: при высоком поле кнопка «Найти цены» уезжала
     под сгиб экрана ещё до того, как в список попадала хоть одна позиция.
     Дальше поле растёт само — до 45% высоты окна, потом прокручивается
     внутри себя. */
  min-height: 96px;
  width: 100%;
}
.ceny-pole textarea:focus { outline: none; border-color: var(--accent); }
.ceny-nastroyki { display: grid; gap: 12px; align-content: start; }
.ceny-nastroyki .field { display: grid; gap: 4px; }
.ceny-nastroyki select { width: 100%; }

/* Панель пуска прилипает к низу окна, пока форма на экране. До этой правки
   кнопка стояла просто под полем: список на сотню позиций уводил её далеко
   вниз, и человек, набравший список, не видел, чем его запустить. Липкая
   панель показывает и кнопку, и цену прогона всё время, пока идёт набор. */
.ceny-pusk {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 12px 0 4px;
  padding: 10px 12px;
  background: var(--paper);
  border: 1px solid var(--bd);
  border-radius: var(--r-md);
  box-shadow: var(--sh-1);
}
.ceny-stoimost { color: var(--fg-2); font-size: 13px; margin: 0; }
.ceny-pusk .btn { margin-left: auto; }

/* Ожидание сборки книг: панель видна, пока фоновая очередь делает работу. */
.sborka-zhdyom {
  display: grid;
  gap: 6px;
  margin-top: 12px;
  padding: 12px 14px;
  background: var(--panel);
  border: 1px solid var(--bd);
  border-radius: var(--r-md);
}
.sborka-slova { font-size: 15px; }
/* Дельта дозаполнения: что человек заработал последним нажатием. */
.dozap-delta { margin-top: 6px; font-weight: 500; }

/* Фоновая работа в шапке: видно с любого экрана сервиса. */
.fonovaya { display: inline-flex; align-items: center; gap: 6px; }
.fonovaya-tochka {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  animation: fonovaya-puls 2s ease-in-out infinite;
}
@keyframes fonovaya-puls {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .45; transform: scale(.8); }
}
@media (prefers-reduced-motion: reduce) {
  .fonovaya-tochka { animation: none; }
}

/* Ход поиска: та же полоса, что и в макете, — видно, что сервис работает. */
.ceny-hod {
  display: grid;
  gap: 6px;
  background: var(--panel);
  border: 1px solid var(--bd);
  border-radius: var(--r-md);
  padding: 12px 16px;
  margin: 0 0 16px;
}
.ceny-hod-slova { font-size: 15px; }
/* Иерархия внутри блока хода: крупно — сколько сделано, тише — чем занят
   сервис и служебные обещания. Класс `.tech` сам по себе стиля не несёт (он
   описан только внутри карточек), и без этого правила блок читался стеной
   одинаковых строк — особенно на узком экране. */
.ceny-hod .tech { color: var(--fg-2); font-size: 13px; }
/* Пустая строка хода (ещё нет оценки времени, ещё нет слов движка) не должна
   занимать место: сетка блока даёт зазор каждому потомку, и пустые узлы,
   которые заполнит скрипт, иначе разъезжались бы дырками. */
.ceny-hod > span:empty { display: none; }
/* Полоса намеренно толстая. Она главный ответ на вопрос «работает ли ещё»
   в те минуты, когда одна позиция ищется, и тонкая линия в 6 px читалась
   как декоративная черта под текстом, а не как ход работы. */
.ceny-hod-polosa {
  position: relative;
  display: block;
  height: 14px;
  border-radius: 7px;
  background: var(--sunken);
  overflow: hidden;
}
.ceny-hod-zalivka {
  display: block;
  height: 100%;
  border-radius: 7px;
  background: var(--accent);
  /* Полоса теперь двигается ЧАСТО и малыми шагами (ход внутри позиции), и
     переход длиннее нажатия: короткий `--t-pop` превращал плавный рост в
     дёрганье на каждом опросе. */
  transition: width 600ms var(--e-out);
}
/* Работа идёт: по полосе бежит мягкий блик. Он не изображает прогресс — его
   дело сказать «сервис жив» в те минуты, когда одна позиция ещё ищется.
   Причина в реестре находок 25.08.2026: неподвижная полоса читается как
   зависание, и человек уходит перезагружать страницу. */
.ceny-hod-idet::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 7px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in oklch, var(--accent) 30%, transparent) 50%,
    transparent 100%
  );
  transform: translateX(-100%);
  animation: ceny-hod-blik 2.2s var(--e-out) infinite;
}
@keyframes ceny-hod-blik {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}
.ceny-hod-vygruzka { color: var(--fg-2); font-size: 13px; }
/* Живой шаг движка: что именно делается с текущей позицией прямо сейчас.
   Полоса за это же время двигается своим ходом (страницы и поставщики), но
   словам человек верит быстрее, чем пикселям. */
.ceny-hod-shag {
  color: var(--fg-2);
  font-size: 13px;
  overflow-wrap: anywhere;
}
/* Второй слой хода: числа, по которым двигается сегмент текущей позиции. */
.ceny-hod-podrobno { font-variant-numeric: tabular-nums; }
/* Обещание тишины и выключатель звука — одной строкой, без вида настройки. */
.ceny-zvuk { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.ceny-zvuk-perekl {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.ceny-zvuk-perekl:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 2px; }
.ceny-hod-shag b { color: var(--fg-1); font-weight: 500; }
.recent-polosa { margin-top: 6px; }
.recent-shag { color: var(--fg-3); overflow-wrap: anywhere; }

.ceny-itog-kartochka {
  background: var(--panel);
  border: 1px solid var(--bd);
  border-radius: var(--r-md);
  padding: 14px 16px;
  margin: 0 0 16px;
}
.ceny-itog-kartochka h2 { font-size: 17px; margin: 0 0 6px; }
.ceny-itog-kartochka p { color: var(--fg-2); margin: 0; }
.ceny-itog-predislovie { color: var(--fg-2) !important; margin-bottom: 8px !important; }
.ceny-itog-deystviya { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.ceny-itog-check { display: inline-block; color: var(--fg-2); }
/* Итог подбора одной полосой. Растёт один раз, при первом показе готового
   подбора: повторные заходы на тот же экран — уже не событие. */
.ceny-itog-polosa {
  display: flex;
  height: 6px;
  border-radius: 3px;
  overflow: hidden;
  background: var(--sunken);
  margin: 12px 0 2px;
  transform-origin: left;
}
.ceny-itog-polosa span { display: block; height: 100%; }
.ceny-itog-dolya-prinyato { background: var(--ok); }
/* Цвет задан прямо. Прежняя запись `color-mix(in oklch, var(--accent) 55%, var(--sunken))`
   смешивала оттенки 68° и 265°: браузер ведёт hue по короткой дуге, путь шёл через
   красный, и «ждёт вашего решения» выходило розовым (#ecaec5) на 80 % полосы. */
.ceny-itog-dolya-sporno { background: oklch(0.82 0.10 78); }
.ceny-zavershen .ceny-itog-polosa { animation: ceny-itog-rost 700ms var(--e-out); }
@keyframes ceny-itog-rost { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.ceny-novaya td { animation: ceny-new-row 420ms var(--e-out); }
.ceny-v-fokuse td { animation: ceny-focus-row 420ms var(--e-out); }
.ceny-zavershen .ceny-itog-check { animation: ceny-check 380ms var(--e-out); }
@keyframes ceny-new-row { from { background: var(--accent-wash); } to { background: transparent; } }
@keyframes ceny-focus-row { from { background: color-mix(in oklch, var(--stop) 14%, transparent); } to { background: transparent; } }
@keyframes ceny-check { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .ceny-hod-zalivka, .ceny-novaya td, .ceny-v-fokuse td, .ceny-zavershen .ceny-itog-check { animation: none; transition: none; }
  /* Бегущий блик, дыхание строки и рост полосы итога — то же правило: человек,
     попросивший систему не двигать картинку, получает статику. */
  .ceny-hod-idet::after,
  .ceny-list tr[data-ceny-state="ishchem"] .ceny-shag-stroki,
  .ceny-itog-polosa { animation: none; }
}

.ceny-list .ceny-est td { background: transparent; }
/* Позиция, сорвавшаяся на обработке. Она отличается от «искали и не нашли»:
   поиск по ней не состоялся вовсе, и человеку нужна кнопка, а не разбор. */
.ceny-list .ceny-sboy td { background: color-mix(in oklch, var(--stop) 4%, transparent); }
.ceny-povtor { margin-top: 6px; }
.ceny-povtor .btn { padding: 6px 12px; font-size: 13px; }
.ceny-itog-sboy { color: var(--stop); }
/* Строка в работе. До этой правки она ничем не отличалась от ждущей своей
   очереди, хотя именно на неё уходят минуты ожидания. */
.ceny-list .ceny-idet td { color: var(--fg-3); }
.ceny-list tr[data-ceny-state="ishchem"] td {
  background: color-mix(in oklch, var(--accent) 5%, transparent);
}
.ceny-list tr[data-ceny-state="ishchem"] td:first-child {
  box-shadow: inset 2px 0 0 var(--accent);
}
/* Дыхание строки в работе: на неё уходят минуты ожидания, и среди соседних
   строк она обязана отличаться не только цветом. Медленно и слабо — это
   признак жизни, а не мигалка. */
.ceny-list tr[data-ceny-state="ishchem"] .ceny-shag-stroki {
  animation: ceny-dyhanie 2.6s ease-in-out infinite;
}
@keyframes ceny-dyhanie {
  0%, 100% { opacity: 1; }
  50% { opacity: .55; }
}
.ceny-shag-stroki { display: block; color: var(--fg-3); overflow-wrap: anywhere; }
/* Подпись под значением — своей строкой. `table.rows .sub` задаёт только цвет и
   отступ, а `margin-top` строчному элементу ничего не двигает: в листе цен ячейка
   принятой цены собиралась в одну длинную строку и растягивала таблицу. Правило
   стоит на листе цен, а не на всех таблицах: у остальных экранов своя разметка,
   и менять её этой волной не за чем. */
/* Наименование материала — то, ради чего сметчик и смотрит строку, а весило
   оно столько же, сколько единица измерения и служебные подписи. Начертание
   среднее: жирным на экране уже набрана принятая цена, и два одинаково тяжёлых
   места в строке спорили бы между собой. Правило берёт РОВНО строку позиции —
   у листа предложений внутри неё своя колонка с тем же классом. */
.ceny-list > tbody > tr > td.name { font-weight: 500; }
.ceny-list td .sub { display: block; }
/* Строка, до которой подбор не дошёл: работа по ней не начиналась вовсе. */
.ceny-list .ceny-ne-doshli td { color: var(--fg-3); }
.ceny-stop { color: oklch(0.48 0.17 27); font-weight: 600; }
/* Блок предложений живёт на белом: серая заливка занимала шестую часть экрана,
   а розовая метка спорной строки поверх неё давала грязный серо-розовый. Границу
   блока держит линия слева. */
.ceny-podstroki > td { padding: 0 0 0 24px; background: var(--paper); box-shadow: inset 2px 0 0 var(--bd); }
.ceny-podstroki summary {
  cursor: pointer;
  padding: 10px 0;
  font-size: 13px;
  color: var(--fg-2);
}
.ceny-predlozheniya { margin: 0 0 10px; }
.ceny-predlozheniya td { border-top: 1px solid var(--bd); }
/* «Спорно» стоит на 64 % предложений (замер по восьми подборам 27.08.2026) —
   заливка на такой доле строк перестаёт быть пометкой и становится фоном. Осталась
   узкая метка слева: глазу есть за что держаться, экран при этом белый. */
.ceny-sporno td { background: transparent; }
.ceny-sporno td:first-child { box-shadow: inset 3px 0 0 oklch(0.72 0.04 70); }
/* Оговорку читают целиком — она бывает в три строки. Красным набирается только
   то, мимо чего проходить нельзя (см. `.ceny-rashozhdenie-vazhno` ниже); рядовая
   идёт обычным тёмным текстом, а сигналит значок. */
.ceny-rashozhdenie { display: block; color: var(--fg-1); font-size: 13px; margin-top: 2px; }
.ceny-rashozhdenie::first-letter { color: var(--vnimanie); }
/* Вторая ступень: цена, выпавшая из ряда, уедет в смету ошибкой в разы. Это
   единственное место листа, где красное означает «остановись». */
.ceny-rashozhdenie-vazhno,
.ceny-rashozhdenie-vazhno::first-letter { color: oklch(0.48 0.17 27); }
.ceny-rashozhdenie-vazhno { font-weight: 500; }
/* Базис НДС без подтверждения. Цену он не отменяет — по нему видно, какую
   графу сметчик обязан уточнить у поставщика перед сдачей формы. */
.ceny-bez-bazisa { color: var(--fg-2); }
.ceny-citata { color: var(--fg-2); font-size: 13px; max-width: 34ch; }

.ceny-itog { display: flex; align-items: center; gap: 16px; margin: 16px 0; }
.ceny-itog .btn { margin-left: auto; }

/* Граница про экспертизу стоит на обоих экранах раздела и выглядит одинаково:
   это одно и то же правило, а не два разных предупреждения. */
.ceny-granica {
  background: var(--accent-wash);
  border: 1px solid var(--accent-ring);
  border-radius: var(--r-md);
  padding: 14px 16px;
  font-size: 14px;
  margin: 16px 0 24px;
}

@media (max-width: 760px) {
  .ceny-vvod { grid-template-columns: 1fr; }
  .ceny-pusk { flex-wrap: wrap; }
  .ceny-pusk .btn { margin-left: 0; width: 100%; }
  .ceny-itog-deystviya .btn { width: 100%; }
  .ceny .privacy { padding-right: 72px; }
  .ceny-citata { max-width: none; }
}

/* --- семь удобств экрана цен ------------------------------------------ */

/* Поле списка и его кнопки — одной колонкой: кнопки принадлежат полю, а не
   настройкам поиска, и на узком экране обязаны остаться при нём. */
.ceny-stolbec { display: grid; gap: 8px; align-content: start; }
.ceny-chernovik {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
  margin: 0;
}
/* Кнопки черновика намеренно тише кнопки пуска: они обслуживают набор, а не
   запускают работу за деньги. Тот же почерк, что у выключателя звука. */
.ceny-chernovik-knopka {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 13px;
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.ceny-chernovik-knopka:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 2px; }
.ceny-chernovik .tech { color: var(--fg-3); font-size: 13px; }

/* Пришли из готового подбора: список подставлен, и человек обязан узнать об
   этом раньше, чем нажмёт кнопку — вместе с тем, что поиск будет новым. */
.ceny-povtor-podbora {
  background: var(--accent-wash);
  border: 1px solid var(--accent-ring);
  border-radius: var(--r-md);
  padding: 12px 14px;
  font-size: 14px;
  margin: 0 0 16px;
}

/* Условия подбора: когда искали, где, сколько поставщиков просили. */
.ceny-usloviya {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
  margin: -4px 0 16px;
  font-size: 13px;
}
.ceny-usloviya .tech { color: var(--fg-2); }
.recent-usloviya { color: var(--fg-3); }

/* Фильтр листа. Кнопки-таблетки: выбранная залита, остальные обведены. */
.ceny-filtr {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
}
.ceny-filtr .tech { color: var(--fg-2); font-size: 13px; }
.ceny-filtr-knopka {
  font: inherit;
  font-size: 13px;
  color: var(--fg-1);
  background: var(--paper);
  border: 1px solid var(--bd-2);
  border-radius: 999px;
  padding: 4px 12px;
  cursor: pointer;
}
.ceny-filtr-knopka:hover { background: var(--hover); }
.ceny-filtr-knopka:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 2px; }
.ceny-filtr-knopka[aria-pressed="true"] {
  background: var(--accent-wash);
  border-color: var(--accent-ring);
  color: var(--accent-ink);
}
/* Переключатель предложений стоит в той же панели, но делает другое: он не
   фильтрует лист, а раскрывает его. Отодвигаем его от фильтров. */
.ceny-razvernut { margin-left: auto; }
/* Строка, спрятанная фильтром. Отдельный класс, а не `hidden`: строка из листа
   не исчезла, её просто сейчас не показывают. */
.ceny-list tr.ceny-skryta { display: none; }

/* Копирование цены. Кнопки маленькие: их на экране столько же, сколько
   предложений, и спорить с ценой по весу они не должны. */
.ceny-kopii { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.ceny-kopiya {
  font: inherit;
  font-size: 12px;
  color: var(--accent-ink);
  background: none;
  border: 1px solid var(--bd-2);
  border-radius: var(--r-sm);
  padding: 2px 8px;
  cursor: pointer;
  white-space: nowrap;
}
.ceny-kopiya:hover { background: var(--hover); }
.ceny-kopiya:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 2px; }

.ceny-povtor-vse { margin: 0; }

@media (max-width: 760px) {
  /* Панель фильтра на телефоне переносится, и «развернуть всё» перестаёт
     цепляться за правый край: там она оказалась бы одна на своей строке. */
  .ceny-razvernut { margin-left: 0; }
  .ceny-povtor-vse .btn { width: 100%; }
}

/* --- экран трат ------------------------------------------------------- */

.traty-itogi {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin: 0 0 24px;
}
.traty-plitka {
  display: grid;
  gap: 2px;
  background: var(--paper);
  border: 1px solid var(--bd);
  border-radius: var(--r-md);
  padding: 14px 16px;
  box-shadow: var(--sh-1);
}
.traty-podpis { font-size: 13px; color: var(--fg-2); }
.traty-cifra { font-size: 24px; font-weight: 600; }
@media (max-width: 760px) { .traty-itogi { grid-template-columns: 1fr; } }

