/* Сквозные утилиты сайта.
   Здесь ТОЛЬКО то, что физически невозможно задать инлайном:
   media-query переключатели раскладки/видимости, кириллическая подмена
   шрифтов и глобальные переменные раскладки. Все цвета, отступы, радиусы,
   тени берутся из _ds/.../styles.css через var(--*).

   ПОДМЕНА ШРИФТОВ: Barlow / Barlow Condensed из дизайн-системы не содержат
   кириллицы — русский текст падал бы в системный Arial. Поэтому в стек
   первым ставится ближайший гротеск с кириллицей (Fira Sans / Fira Sans
   Condensed), Barlow остаётся вторым. Роли и связка «узкие заголовки над
   гротескным текстом» сохранены. */
@import url('https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500;600;700&family=Fira+Sans+Condensed:wght@400;500;600;700&display=swap');

:root {
  --font-heading: "Fira Sans Condensed", "Barlow Condensed", system-ui, sans-serif;
  --font-body: "Fira Sans", "Barlow", system-ui, sans-serif;
  --edge: clamp(16px, 4vw, 56px);
  --wrap: 1240px;
}

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { font-size: 16px; text-wrap: pretty; overflow-x: hidden; }

/* видимость по ширине вьюпорта. Переключение «мобильный ↔ десктоп» — 900px */
@media (max-width: 899px) { .hide-mob { display: none !important; } }
@media (min-width: 900px) { .only-mob { display: none !important; } }
@media (max-width: 1180px) { .hide-md { display: none !important; } }
@media (max-width: 767px)  { .hide-sm  { display: none !important; } }

/* мега-меню на узком десктопе: колонки сжимаются, паддинги уменьшаются */
@media (max-width: 1140px) {
  .mega-grid { grid-template-columns: 190px repeat(3, 1fr) !important; }
  .mega-grid > div { padding-left: 12px !important; padding-right: 12px !important; }
}

/* раскладки, которые складываются в одну колонку на узком экране */
@media (max-width: 899px) {
  .stack { grid-template-columns: minmax(0, 1fr) !important; }
  .stack-rev { display: flex !important; flex-direction: column-reverse !important; }
}
@media (max-width: 1023px) { .stack-md { grid-template-columns: minmax(0, 1fr) !important; } }

/* Многоколоночные сетки карточек: промежуточный шаг в 2 колонки, потом в одну.
   Без него 4 и 5 колонок остаются на 640–900px и выдавливают строку за вьюпорт. */
@media (max-width: 1023px) { .stack-sm { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; } }
@media (max-width: 640px)  { .stack-sm { grid-template-columns: minmax(0, 1fr) !important; } }

/* запас под фиксированную мобильную панель действий */
@media (max-width: 899px) { body { padding-bottom: 68px; } }

/* сквозные плавающие элементы уступают место мобильной панели действий */
@media (max-width: 899px) {
  .cookie-pos { bottom: 68px !important; }
  .chat-pos { bottom: 80px !important; right: 12px !important; }
}

/* пока висит плашка cookie-согласия, чат поднимается над ней (класс ставит SiteChrome) */
.chat-raised { bottom: 92px !important; }
@media (max-width: 899px) { .chat-raised { bottom: 148px !important; } }

/* карусели: scroll-snap вместо карусельных библиотек */
.snap { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: thin; }
.snap > * { scroll-snap-align: start; flex: none; }

/* Reveal-анимация появления секций удалена: см. комментарий в Home.dc.html.
   Класс .reveal остаётся в разметке как семантический маркер и ничего не скрывает —
   при отключённом JS и при любой реконсиляции React контент виден всегда. */

/* Подъём карточки под курсором. Инлайном не задать: нужен transition
   и :hover одновременно, а style-hover перекрывает transform без плавности. */
.lift { transition: transform 180ms ease, box-shadow 180ms ease, background-color 180ms ease; }
.lift:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
@media (prefers-reduced-motion: reduce) { .lift:hover { transform: none; } }

/* Масонри-сетка отзывов: CSS-колонки вместо карусели — пользователь видит
   6–9 отзывов сразу, а не первый и край второго. */
.masonry { column-count: 3; column-gap: clamp(14px, 1.6vw, 20px); }
.masonry > * { break-inside: avoid; margin-bottom: clamp(14px, 1.6vw, 20px); }
@media (max-width: 1023px) { .masonry { column-count: 2; } }
@media (max-width: 640px)  { .masonry { column-count: 1; } }

/* Набор числовых плиток hero. Четыре колонки живут только на широком экране:
   в половине hero на 1100px на колонку приходится ~114px, а плейсхолдерные токены
   вроде {{TOTAL_JOBS}} и «с {{YEAR_FOUNDED}}» шире и вылезают за рамку. Складываем в 2×2
   до 1100px и разрешаем перенос внутри ячеек, чтобы длинные значения не рвали сетку. */
.stat-row > div { min-width: 0; }
.stat-row > div > span { overflow-wrap: anywhere; }
@media (max-width: 1100px) {
  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .stat-row > div:nth-child(3),
  .stat-row > div:nth-child(4) { border-top: 1px solid var(--color-divider); }
  .stat-row > div:nth-child(odd) { border-left: 0 !important; }
}
/* Плитка из трёх цифр (hero страниц услуг, категорий и лендингов) в две
   колонки ещё тесна: на 375px это ~165px на ячейку. Ниже 430px — одна колонка. */
@media (max-width: 430px) {
  .stat-row { grid-template-columns: minmax(0, 1fr) !important; }
  .stat-row > div { border-left: 0 !important; }
  .stat-row > div + div { border-top: 1px solid var(--color-divider); }
}

/* Лента табов с горизонтальным скроллом на мобильных, без переноса в две строки */
@media (max-width: 640px) {
  .tabs-row { flex-wrap: nowrap !important; overflow-x: auto; scrollbar-width: none; }
  .tabs-row::-webkit-scrollbar { display: none; }
  .tabs-row > * { flex: none; }
}

/* СРАВНЕНИЕ С АЛЬТЕРНАТИВАМИ.
   Была таблица в четыре колонки с горизонтальным скроллом — на телефоне
   она ездила и сравнивать в ней было невозможно. Сейчас грид на три колонки
   (критерий · мы · оппонент), на узком экране — стопка карточек без скролла. */
.cmp-row { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr) minmax(0, 1fr); }
.cmp-row > * { min-width: 0; }
@media (max-width: 900px) {
  .cmp-row { grid-template-columns: minmax(0, 1fr); gap: 0; }
  /* внутренние разделители между ячейками одной карточки, а не между колонками */
  .cmp-row > .cmp-cell { border-left: 0 !important; }
  .cmp-row > .cmp-cell + .cmp-cell { border-top: 1px solid var(--color-divider); }
}

/* Подсветка строки под курсором: сравнивать восемь пунктов глазом легче,
   когда активная строка выделена. Только на устройствах с наведением. */
@media (hover: hover) {
  .cmp-row-hl { transition: background-color 140ms ease; }
  .cmp-row-hl:hover { background: color-mix(in srgb, var(--color-accent-100) 55%, transparent); }
}

/* нативный аккордеон FAQ.
   ВАЖНО: инлайновый display на прямом потомке <details> перебивает UA-правило,
   скрывающее не-summary детей закрытого элемента. У нас обёртка ответа несёт
   display:grid (нужен gap между абзацем и ссылкой), поэтому закрытый вопрос
   продолжал раскладывать содержимое и накладывал его на следующий заголовок.
   Правило ниже возвращает скрытие и страхует все FAQ проекта — на главной,
   страницах услуг, категорий и лендингах, где применён тот же паттерн. */
details:not([open]) > *:not(summary) { display: none !important; }
details > summary { list-style: none; cursor: pointer; }
details > summary::-webkit-details-marker { display: none; }
details[open] .faq-plus { transform: rotate(45deg); }

/* ПРАЙС-ТАБЛИЦЫ НА ТЕЛЕФОНЕ.
   У таблиц стоит min-width 560–640px: внутри своего overflow-x они едут, страница
   при этом не ломается, но сравнивать цены горизонтальным скроллом неудобно.
   Ниже 640px снимаем минимальную ширину и прячем описательную колонку
   («Что делаем» / «Что входит») — остаются работа, срок и цена, то есть то,
   за чем пришли. Сам текст описания есть в контенте страницы. */
@media (max-width: 640px) {
  .table { min-width: 0 !important; }
  .col-desc { display: none !important; }
  .table th, .table td { padding-left: 10px; padding-right: 10px; }
}

/* STICKY-БАР CTA НА ДЕСКТОПЕ.
   Появляется после ухода hero из вида: между первым экраном и прайсом пять
   экранов без возможности действия. На мобильных не показываем — там уже есть
   фиксированная панель действий, два фиксированных элемента съели бы экран.
   Видимость держит состояние компонента (класс .sticky-on), а не императивная
   мутация DOM: React владеет этими узлами. */
.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 78;
  transform: translateY(100%); transition: transform 260ms ease;
  pointer-events: none;
}
.sticky-cta.sticky-on { transform: none; pointer-events: auto; }
@media (max-width: 899px) { .sticky-cta { display: none; } }
@media (prefers-reduced-motion: reduce) { .sticky-cta { transition: none; } }
