/* Дополнения темы к вёрстке.

   Файлы вёрстки переносятся в тему без правок, поэтому всё, что появилось
   уже при посадке на WordPress, живёт здесь отдельным слоем. Каждый блок
   ниже закрывает конкретный пробел вёрстки и назван в отчёте по этапу.
   Файл подключается последним, но ни одного !important в нём нет. */

/* Зона действий шапки. Состояние посетителя приходит после загрузки
   страницы, поэтому место под него резервируется заранее: иначе шапка
   дёргается, когда гостевые кнопки сменяются профилем. */
.header__auth-zone {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  min-height: var(--avatar-sm);
  min-width: var(--avatar-sm);
}

/* Авторизованная версия: отделяем шапку от admin bar тем же 16 px ритмом,
   который используется в интерфейсе. WordPress уже сдвигает документ вниз
   на высоту своей панели, поэтому здесь нужен только визуальный зазор. */
body.admin-bar .header {
  top: var(--space-4);
}

/* Компенсируем системный сдвиг WordPress за вычетом нового зазора. Так hero
   не растягивается на полную высоту admin bar, а его содержимое начинается
   после сдвинутой шапки и не пересекается с ней даже на мобильном. */
body.admin-bar .hero {
  padding-top: calc(var(--hero-padding-top) - 16px);
}

@media (min-width: 768px) {
  .header__auth-zone { min-width: 220px; }
}

/* Баннер cookies. В вёрстке он показывался только на своей демо-странице
   правилом .cookie-banner-page. В теме баннер приходит скрытым и
   показывается скриптом, если согласие ещё не сохранено. */
.cookie.is-visible { display: block; }

/* Модальные окна. В вёрстке они показаны раскрытыми и без кнопки закрытия -
   это состояния, а не страницы. В теме окно приходит скрытым через
   visibility (overlay.css) и появляется по клику, а закрыть его нужно
   не только по Esc: кнопка обязательна для доступности. */
.modal { position: relative; }

.modal__close {
  position: absolute;
  top: var(--space-4);
  inset-inline-end: var(--space-4);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--icon-xl);
  height: var(--icon-xl);
  border: none;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
}

.modal__close:hover { color: var(--text-strong); }

/* Страница под открытым окном не прокручивается. */
.is-modal-open { overflow: hidden; }

.video-preview__frame,
.video-preview__player {
  width: 100%;
  height: 100%;
  border: none;
  border-radius: var(--radius-lg);
}

/* Фильтры каталога. В вёрстке фильтр - только кнопка-триггер: списка
   значений там нет. Панель собрана на details, поэтому выбор работает и с
   выключенным JavaScript. */
.filter-drop { position: relative; }

.filter-drop > summary { list-style: none; cursor: pointer; }

.filter-drop > summary::-webkit-details-marker { display: none; }

.filter-drop__panel {
  position: absolute;
  z-index: 20;
  top: calc(100% + var(--space-2));
  inset-inline-start: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: max-content;
  min-width: max(100%, 220px);
  max-width: min(360px, calc(100vw - var(--space-8)));
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  box-shadow: var(--elevation-lg);
}

.filter-bar__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: none;
  white-space: nowrap;
}

.filter-bar__clear {
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-link);
  white-space: nowrap;
}

.filter-bar__clear:hover { color: var(--text-link-hover); }

.catalog__controls {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* Левая панель каталога до 1024 сворачивается в аккордеон - требование
   раздела 13 ТЗ по каталогу, в вёрстке колонка просто вставала над контентом. */
.cat-list__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  cursor: pointer;
  list-style: none;
}

.cat-list__summary::-webkit-details-marker { display: none; }

.cat-list__chevron { transition: transform var(--duration-fast, 150ms) ease; }

/* Атрибут open стоит на details, а не на обёртке nav.cat-list, и summary
   лежит внутри details. Прежний селектор `.cat-list[open] > .cat-list__summary`
   не совпадал ни с чем, поэтому стрелка смотрела вниз и в свёрнутом виде. */
.cat-list__details[open] > .cat-list__summary .cat-list__chevron { transform: rotate(180deg); }

@media (min-width: 1024px) {
  .cat-list__summary { pointer-events: none; }

  .cat-list__chevron { display: none; }
}

/* Ширины полей фильтра. В вёрстке они заданы правилом .filter-set > .filter,
   но в теме каждый фильтр обёрнут в details ради работы без JavaScript,
   поэтому размеры переезжают на обёртку. */
.filter-drop > .filter { width: 100%; }

@media (min-width: 1200px) {
  .filter-set > .filter-drop {
    flex: 1 1 auto;
    min-width: 0;
  }
}

/* Мобильные фильтры. Раздел 13 ТЗ по каталогу требует панель под кнопкой
   «Filters»: в вёрстке до 768 поля просто раскладывались сеткой в две
   колонки. Панель собрана из существующих блоков, новых не заводим.

   Поведение включается классом is-enhanced, который ставит скрипт: без
   JavaScript кнопки-переключателя нет, и поля остаются на виду, как в
   вёрстке. На десктопе обёртка панели растворяется - раскладка не меняется. */
.filter-bar__panel { display: contents; }

.filter-bar__toggle,
.filter-bar__panel-head { display: none; }

@media (max-width: 767px) {
  .filter-set { grid-template-columns: minmax(0, 1fr); }

  .filter-bar.is-enhanced .filter-bar__toggle {
    display: inline-flex;
    flex: 1 1 100%;
    justify-content: center;
    gap: var(--space-2);
  }

  .filter-bar__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: var(--radius-full);
    background: var(--primary-500);
    color: var(--neutral-white);
    font-size: var(--fs-caption);
  }

  .filter-bar.is-enhanced .filter-bar__panel {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-5);
    overflow-y: auto;
    background: var(--bg-surface);
  }

  .filter-bar.is-enhanced .filter-bar__panel[hidden] { display: none; }

  .filter-bar.is-enhanced .filter-bar__panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .filter-bar__panel-head .modal__close { position: static; }

  /* Внутри панели значения раскрыты списком, а не выпадают поверх. */
  .filter-bar.is-enhanced .filter-drop__panel {
    position: static;
    width: 100%;
    min-width: 0;
    max-width: none;
    box-shadow: none;
    padding: var(--space-3) 0 0;
  }

  .filter-bar__actions {
    margin-top: auto;
    flex-wrap: wrap;
  }

  .filter-bar__actions .btn,
  .filter-bar__actions .filter-bar__clear {
    flex: 1 1 100%;
    justify-content: center;
  }

  /* Внутри колоночной панели сетка полей тянется по высоте и разгоняет
     ряды: прижимаем их к началу. */
  .filter-bar.is-enhanced .filter-set { align-content: start; }
}

/* Строка значения фильтра. В вёрстке класс checkbox стоит на самом поле,
   поэтому подписи нужна своя обёртка. */
.filter-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
  color: var(--text-body);
  cursor: pointer;
  white-space: nowrap;
}

/* «Скопировать ссылку» в вёрстке было ссылкой, но никуда не ведёт: в теме
   это кнопка. Внешний вид остаётся прежним. */
.article-share__copy {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  cursor: pointer;
}

/* Результаты поиска по сайту. Отдельной страницы в вёрстке нет: список
   собран из тех же карточек, группам нужен только заголовок и отступ. */
.search-group + .search-group { margin-top: var(--space-10); }

.search-group__title { margin-bottom: var(--space-5); }

/* Страница в выдаче: карточка без обложки. */
.article-card--plain .article-card__body { padding-top: var(--space-6); }

/* Аватар соцдоказательства с собственной фотографией.
   Лица вёрстки вырезаны из общего листа классами avatar--face-N, у них свой
   масштаб и позиция кадра. Снимок, загруженный редактором, самостоятельный:
   его нужно вернуть к обычному «вписать по кругу». */
.avatar--custom {
  background-size: cover;
  background-position: center;
}

/* Ответ аккордеона приходит из wysiwyg-поля и может состоять из абзацев,
   списка и ссылок. Внешние отступы крайних элементов сняты: в вёрстке
   ответ был простым текстом, и высота блока не должна измениться. */
.accordion__answer-body > :first-child { margin-top: 0; }

.accordion__answer-body > :last-child { margin-bottom: 0; }

/* Лид и контактный блок юридической страницы. В вёрстке их нет: поля
   заведены по ТЗ, и пока они пусты, разметка страницы не меняется. */
.legal-header__lead {
  max-width: 62ch;
  margin-top: var(--space-4);
  color: var(--text-muted);
  font-size: var(--fs-lg);
}

.legal-contact {
  margin-top: var(--space-10);
  padding-top: var(--space-8);
  border-top: 1px solid var(--border-hairline);
}

.legal-contact__title { margin-bottom: var(--space-4); }


/* Подпись под кнопкой запуска сценария: поле есть, в вёрстке строки не было. */
.overview__note {
  margin-top: var(--space-3);
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

/* Выделенная цитата статьи. В вёрстке цитата живёт внутри текста статьи,
   а эта приходит отдельным полем и стоит после него: повторяем тот же вид. */
.article-quote {
  margin-top: var(--space-8);
  padding-block: var(--space-1); padding-inline: var(--space-6) 0;
  border-inline-start: 3px solid var(--sky-300);
  font-size: var(--fs-lg);
  line-height: var(--lh-relaxed);
  color: var(--text-strong);
}

.article-quote p { margin: 0; }

.article-quote cite {
  display: block;
  margin-top: var(--space-3);
  font-size: var(--fs-sm);
  font-style: normal;
  color: var(--text-muted);
}

/* ============================================================
   ЛИПКАЯ ШАПКА
   ============================================================
   Панель с клоном шапки, её строит assets/js/scroll.js (решение UI-10).
   Оригинальная .header лежит поверх градиентной зоны и своего фона не имеет:
   цвет под ней даёт .hero или .page-header. Ниже этой зоны фона взять
   неоткуда, поэтому у панели он свой - тот же цвет, который виден под шапкой
   на первом экране: первая точка градиента rgba(242, 247, 251, 0.5) поверх
   --bg-page. Заливка лежит на обёртке, а не на клоне: у .header стоит
   max-width контейнера, и края широкого экрана остались бы непрокрашенными.
   Нижние углы скруглены на 50, как у .hero и .page-header: панель читается
   продолжением градиентной зоны, а не отдельной планкой. */

.sticky-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 40;
  border-radius: 0 0 50px 50px;
  background: #f8f9fa;
  box-shadow: var(--elevation-sm);
  transform: translateY(-100%);
  transition: transform var(--duration-slow) cubic-bezier(0.16, 1, 0.3, 1);
}

.sticky-header.is-visible { transform: translateY(0); }

/* Внутри панели клон возвращается в поток: абсолютное позиционирование
   нужно было только оригиналу, чтобы лечь поверх первого экрана. */
.sticky-header .header { position: static; }

/* Под admin bar панель не подлезает. WordPress держит его на 32 px, а до 782
   он не фиксирован и уезжает вместе со страницей - там сдвиг не нужен. */
body.admin-bar .sticky-header { top: 32px; }

@media (max-width: 782px) {
  body.admin-bar .sticky-header { top: 0; }
}

/* ============================================================
   КНОПКА «НАВЕРХ»
   ============================================================
   Решение UI-12. Скрытая кнопка гасится прозрачностью, а не display: иначе
   не отрабатывает переход появления. pointer-events снимаем, чтобы невидимая
   кнопка не перехватывала клики по контенту под ней. --to-top-shift ставит
   скрипт: пока виден баннер cookies, кнопка стоит над ним. */

.to-top {
  position: fixed;
  inset-inline-end: var(--grid-margin);
  bottom: calc(var(--space-6) + var(--to-top-shift, 0px));
  z-index: 45;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--avatar-md);
  height: var(--avatar-md);
  padding: 0;
  border: none;
  border-radius: var(--radius-full);
  background: var(--action-primary-bg);
  color: var(--action-primary-text);
  box-shadow: var(--elevation-md);
  opacity: 0;
  pointer-events: none;
  transform: translateY(12px);
  cursor: pointer;
  transition:
    opacity var(--duration-base) ease,
    transform var(--duration-base) ease,
    background var(--duration-fast) ease,
    bottom var(--duration-base) ease;
}

.to-top .icon {
  width: var(--icon-lg);
  height: var(--icon-lg);
}

.to-top.is-visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.to-top:hover {
  background: var(--action-primary-bg-hover);
  box-shadow: var(--elevation-lg);
}

.to-top:active {
  background: var(--action-primary-bg-active);
  box-shadow: var(--elevation-sm);
}

.to-top:focus-visible { box-shadow: var(--focus-ring-on-raised); }

/* Под открытым меню и модальным окном кнопке делать нечего: страница за ними
   не прокручивается. */
.is-menu-open .to-top,
.is-modal-open .to-top {
  opacity: 0;
  pointer-events: none;
}

/* ---------------------------------------------------------------
   Формы на плагине SD Forms.
   Разметку даёт sd-forms/form.php, поле рисует sparrway_form_field()
   классами вёрстки (field, field-label, checkbox, consent) без изменений.
   front.css плагина уже стилизует honeypot, sdf-form__error и sdf-form__status -
   здесь только то, чего в бутафорской карточке не было и чего плагин не даёт:
   состояние ошибки поля, звёздочка обязательного поля, файловое поле, и две
   починки конфликта с front.css (комментарий в его шапке - "цвета, шрифты,
   радиусы и отступы инпутов и кнопки - только от темы"):
   1. Кнопка sdf-form__submit получает фон/цвет/радиус через переменные
      --sdf-btn-bg/--sdf-btn-fg/--sdf-radius-btn с фолбэком inherit. Пока
      админ не задал стиль формы, переменных нет, и inherit утаскивает кнопку
      в прозрачный фон родителя - отдаём те же токены, что красят .btn--primary.
   2. .sdf-form--inline из front.css ставит display:flex тем же весом
      селектора, что и .waitlist__form { display:grid }, и грузится позже -
      поднимаем специфичность до .sdf-form--inline.waitlist__form. */

.sdf-form {
  --sdf-btn-bg: var(--action-primary-bg);
  --sdf-btn-fg: var(--action-primary-text);
  --sdf-radius-btn: var(--radius-full);
}

/* margin-top кнопки в front.css задан не токеном; свой отступ уже даёт
   flex-gap карточки, здесь его гасим с более высокой специфичностью. */
.btn.sdf-form__submit { margin-top: 0; }

/* Пустой контейнер ошибки не должен занимать место в разметке. */
.field-error:empty { display: none; }

.field[aria-invalid='true'] { border-color: var(--feedback-danger-solid); }

.form-field__required { color: var(--feedback-danger-text); }

.form-card__status {
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}

.form-card__status:empty { display: none; }

.sdf-form--success .form-card__status { color: var(--feedback-success-text); }

.sdf-form--error .form-card__status { color: var(--feedback-danger-text); }

/* Кнопка на время запроса неактивна, но не мигает и не прыгает. */
.sdf-form--loading .sdf-form__submit {
  opacity: 0.6;
  pointer-events: none;
}

/* Своя кнопка выбора файла: решение заказчика от 2 сентября 2026 - нативный
   контрол браузер подписывает сам и на языке своего интерфейса, заменить
   подписи нельзя. Настоящий input остаётся в разметке (.visually-hidden из
   base.css - скрыт визуально, но в потоке фокуса), поэтому фокус приходит
   на него, а обводку рисуем на кнопке через :focus-within. Ширина - от
   содержимого, высота - от контента кнопки, без фиксированных значений. */
.file-field {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.file-field__button {
  cursor: pointer;
}

.file-field:focus-within .file-field__button {
  outline: 2px solid var(--border-strong);
  outline-offset: 2px;
}

.file-field__name {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  overflow-wrap: anywhere;
}

.file-field.is-filled .file-field__name {
  color: var(--text-strong);
}

/* Реквизиты компании под копирайтом подвала. Строка длинная, поэтому
   колонка сжимается и переносит текст, а переключатель языка стоит
   справа на уровне первой строки: при центровке по высоте блока он
   уезжал вниз под кнопку «наверх». */
.footer__bottom {
  align-items: flex-start;
}

.footer__meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.footer__legal {
  font-size: var(--fs-xs);
  line-height: var(--lh-normal);
  color: var(--text-muted);
}

/* Переносы по слогам в русских заголовках (этап ru/pt/fr, решение Juliana 23.10.2026).
   Длинные русские слова не помещались в крупный заголовок на телефоне:
   «конфиденциальности» в h1 страницы политики шире экрана 375 на 50 px. Браузер
   переносит по словарю языка страницы (html lang="ru-RU"); другие языки не задеты.
   overflow-wrap - запасной вариант для браузера без русского словаря переносов:
   слово рвётся без дефиса, но за край не выходит. */
:lang(ru) :is(h1, h2, h3, h4, h5, h6, .t-display, .t-h1, .t-h2, .t-h3, .t-h4) {
  -webkit-hyphens: auto;
  hyphens: auto;
  overflow-wrap: break-word;
}

/* ============================================================
   СПРАВА НАЛЕВО (этап ar). Раскладку зеркалят логические свойства во всех
   файлах; здесь только то, что ими не выразить. Иллюстрации и фото не
   зеркалятся (решение Р5).
   ============================================================ */

/* Иконки с направлением (стрелки, шевроны влево-вправо): класс icon--dir ставит
   sparrway_icon(). Логотип, arrow-up и chevron-down его не получают. */
[dir="rtl"] .icon--dir { transform: scaleX(-1); }

/* Пагинация блога: стрелки набраны символом «→», bidi его не отражает. */
[dir="rtl"] .pagination__arrow { transform: rotate(180deg); }
[dir="rtl"] .pagination__arrow--prev { transform: none; }

/* Декор с направлением движения (маршрут, путь шагов, линии алгоритма) зеркалится
   вместе с раскладкой (Р5). Это пустые слои без текста. */
[dir="rtl"] .about__route,
[dir="rtl"] .how__path,
[dir="rtl"] .dark-panel__lines,
[dir="rtl"] .final-cta__lines,
[dir="rtl"] .audience-hero__route { transform: scaleX(-1); }

/* У поддержки маршрут - фон контейнера с чипами: фон уходит в отражённый
   псевдоэлемент, чипы остаются как есть. */
[dir="rtl"] .support-hero__decor { background: none; }
[dir="rtl"] .support-hero__decor::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url("../img/decor-scenario-route.svg") center / contain no-repeat;
  transform: scaleX(-1);
}
[dir="rtl"] .support-hero__chip { z-index: 1; }

/* Числа со знаком («12,452+», «30 +») в RTL читаются в естественном порядке, плюс
   слева: так принято на арабских сайтах. Изоляция направления им не нужна. */

/* Почта, телефон и адрес набираются слева направо и в арабской форме. */
[dir="rtl"] input[type="email"],
[dir="rtl"] input[type="tel"],
[dir="rtl"] input[type="url"] { direction: ltr; text-align: right; }

/* Управление видео всегда слева направо: полоса времени не разворачивается
   (Material 3, Bidirectionality: media controls are always LTR). */
[dir="rtl"] video { direction: ltr; }

/* Латинское название (юрлицо в подвале) не рвётся посередине. */
.nowrap { white-space: nowrap; }

/* Коды действий сценария (greet_host) - латиница слева направо, у края колонки. */
[dir="rtl"] .code-line { direction: ltr; text-align: right; }

/* Голубой градиент акцентной части заголовка идёт по направлению чтения:
   светлое начало справа. Цифры «404» читаются слева направо, их не трогаем. */
[dir="rtl"] .hero__accent,
[dir="rtl"] .section-head__accent,
[dir="rtl"] .page-header__accent,
[dir="rtl"] .not-found__accent {
  background-image: linear-gradient(270deg, var(--action-sky-bg-hover), var(--sky-500));
}

/* Английские реплики в «» внутри арабского текста изолирует <bdi>
   (sparrway_i18n_isolate_latin_quotes в inc/i18n.php), отдельных правил не нужно. */

/* ============================================================
   АРАБСКИЙ: шрифт и типографика (этап ar, спека 4.6)
   ============================================================ */

/* У Involve и Golos Text нет арабских букв. Арабские семейства (fonts.css) стоят
   сразу за ними: латиница внутри арабского текста остаётся Involve и Golos.
   Межстрочный выше: у арабского письма высокие выносные и огласовки. */
:root:lang(ar) {
  --font-heading: "Involve", "Sparrway Arabic Head", "Golos Text", system-ui, sans-serif;
  --font-body:    "Golos Text", "Sparrway Arabic", system-ui, -apple-system, sans-serif;
  --lh-tight:   1.35;
  --lh-display: 1.4;
  --lh-snug:    1.45;
  --lh-normal:  1.75;
  --lh-relaxed: 1.9;
  /* Мелкие подписи (чипы, бейджи, заголовки колонок подвала, шаги) в латинице
     набраны прописными с разрядкой, а строчная вязь того же кегля выглядит
     заметно мельче. Арабскому прибавлены пункты, как советует Apple HIG
     (Right to left: increase the RTL font size by about 2 points). */
  --fs-xs:  14px;
  --fs-2xs: 14px;
}

/* Подпись над названием магазина на значке App Store и Google Play. */
:lang(ar) .store__kicker { font-size: 12px; }

/* Разрядка рвёт связное письмо, прописные к арабскому неприменимы, переносов
   у арабского нет. Разрядка задана и токенами, и числами в отдельных блоках,
   поэтому обнуляется у всех элементов сразу. */
:lang(ar),
:lang(ar) * {
  letter-spacing: 0 !important;
  text-transform: none !important;
  -webkit-hyphens: manual;
  hyphens: manual;
  /* Подчёркивание ниже точек и хвостов букв, а не поперёк них. */
  text-underline-offset: 0.35em;
}

/* Длинное арабское слово на 375 не выходит за карточку и кнопку. */
:lang(ar) { overflow-wrap: break-word; }
