/**
 * ATS Blocks
 * Стили для всех именованных секций сайта (см. контракт, раздел
 * "Имена CSS/HTML классов блоков"). Общая физика кнопок/полей/карточек —
 * в components.css. Внутренняя разметка блоков (__body, __title и т.п.)
 * не зафиксирована контрактом — имена подобраны по BEM с префиксом ats-.
 * Зависит от tokens.css, base.css, components.css.
 */

/* =====================================================
   Header
   ===================================================== */

.ats-header {
	position: relative;
	background: var(--surface-base);
	border-bottom: 1px solid var(--border-default);
	z-index: 100;
}

.ats-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-4);
	padding-block: var(--space-4);
}

.ats-header__nav {
	display: none;
}

/*
 * Полное меню появляется с 1280, а не с 1024.
 *
 * Замеры в браузере (scrollWidth против clientWidth документа):
 *   1024 — документ шире окна на 79px: строка «логотип + шесть пунктов меню +
 *          телефон + оранжевая кнопка» не помещается, появляется
 *          горизонтальная прокрутка;
 *   1152 — переполнение 13px.
 *
 * Раньше на 1152 переполнения не было, но лишь потому, что «О компании»
 * переносился на две строки, а номер телефона ломался посимвольно: строка
 * «помещалась» за счёт собственной поломки. С запретом переноса (см. правила
 * ниже) меню честно требует ~1165px и больше, поэтому граница — 1280, ближайший
 * шаг сетки с реальным запасом. Ниже 1280 работает бургер: то же меню, тем же
 * способом, что и на телефоне. Ревизия дизайна 2026-08-18.
 */
@media (min-width: 1280px) {
	.ats-header__nav {
		display: flex;
		align-items: center;
		gap: var(--space-6);
	}
}

.ats-header__nav-link {
	position: relative;
	font-size: .9375rem;
	font-weight: 500;
	color: var(--text-primary);
	text-decoration: none;
	/* «О компании» — единственный пункт из двух слов — переносился на две
	   строки и ломал высоту всей шапки. Ревизия дизайна 2026-08-18. */
	white-space: nowrap;
}

.ats-header__nav-link:hover {
	color: var(--text-link);
}

/* Подчёркивание-индикатор при наведении: scaleX от левого края (только
   transform — layout не трогается, глушится prefers-reduced-motion). */
.ats-header__nav-link::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: -6px;
	height: 2px;
	border-radius: var(--r-full);
	background: var(--brand-600);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform var(--t-fast) var(--ease-standard);
}

.ats-header__nav-link:hover::after,
.ats-header__nav-link:focus-visible::after {
	transform: scaleX(1);
}

/*
 * Текущий раздел. Разметка проставляла aria-current="page" (шаблон header.php
 * считает текущим и сам раздел, и любую страницу внутри него), но в стилях
 * этого состояния не было: подчёркивание появлялось только на наведении, и
 * зрячий человек не видел, где находится. Полоса + насыщенное начертание —
 * два признака, а не один цвет. Ревизия дизайна 2026-08-18.
 */
.ats-header__nav-link[aria-current="page"] {
	color: var(--text-primary);
	font-weight: 700;
}

.ats-header__nav-link[aria-current="page"]::after {
	transform: scaleX(1);
}

.ats-mobile-menu__link[aria-current="page"] {
	color: var(--brand-700);
	font-weight: 700;
}

.ats-header__nav-item {
	position: relative;
}

/*
 * Классы ниже (.ats-header__logo*, __actions, __phone, __burger*) — раньше
 * отсутствовали в CSS полностью, хотя разметка (site-header.php) их уже
 * выводила: бургер-кнопка не имела display:none на десктопе и была видна
 * рядом с полным меню, телефон рендерился обычной синей ссылкой (наследовал
 * глобальный `a`), а на мобильном логотип/телефон/CTA/бургер боролись за
 * ширину — телефон скрыт до десктопа, где место уже есть (сотовый — в
 * sticky-баре и мобильном меню). Найдено ревизией через агентов Fable,
 * 2026-08-06, см. docs/11-audit-fable-2026-08-06.md, П1.16.
 */
.ats-header__logo-link {
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}

.ats-header__logo-text {
	font-family: var(--font-display);
	/* 800 + сжатый трекинг — тот же вес, что у заголовков (base.css), текст
	   читается как вордмарк, а не как обычная ссылка. */
	font-weight: 800;
	font-size: 1.125rem;
	letter-spacing: -.02em;
	color: var(--text-primary);
}

.ats-header__actions {
	display: flex;
	align-items: center;
	gap: var(--space-3);
}

/*
 * До 768px оранжевая кнопка из шапки убрана совсем.
 *
 * Компактных паддингов (прежнее решение полиш-прохода 2026-08-11) не хватало:
 * логотип ~150px + кнопка ~175px + бургер «Меню» ~85px + отступы не влезают
 * ни в 360, ни в 390, ни в 430px. Кнопка выдавливала бургер ЗА пределы
 * экрана — то есть с телефона в меню было не попасть вообще. Проверено
 * рендером шапки на 360/390/430px.
 *
 * Убрана именно кнопка, а не бургер: путей оставить заявку с телефона и без
 * неё три — CTA в первом экране, нижняя липкая панель и та же кнопка внутри
 * самого меню, — а путь к навигации был ровно один. Ревизия дизайна 2026-08-18.
 */
@media (max-width: 767.98px) {
	.ats-header__actions .ats-btn--primary {
		display: none;
	}
}

.ats-header__phone {
	display: none;
	align-items: center;
	gap: var(--space-2);
	font-weight: 600;
	font-size: .9375rem;
	color: var(--text-primary);
	text-decoration: none;
	/* Номер не переносится никогда: во flex-строке шапки он ломался
	   посимвольно и выглядел как «+7 / 991 / 222- / 91- / 92» —
	   нечитаемо и невозможно продиктовать. Ревизия дизайна 2026-08-18. */
	white-space: nowrap;
}

/*
 * Номер в шапке — с 768px. Раньше он включался вместе с полным меню на 1024,
 * а теперь меню переехало на 1280, и на промежутке 768-1280 (планшет, окно в
 * половину экрана) в строке остаются только логотип, номер, кнопка и бургер —
 * место есть. Для грузоперевозок звонок это главный способ связи, прятать его
 * до 1280 было бы хуже. Ревизия дизайна 2026-08-18.
 */
@media (min-width: 768px) {
	.ats-header__phone { display: inline-flex; }
}

.ats-header__burger {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	min-height: 44px;
	padding: var(--space-2);
	background: none;
	border: none;
	color: var(--text-primary);
	cursor: pointer;
}

.ats-header__burger-label {
	font-size: .875rem;
	font-weight: 600;
}

@media (min-width: 1280px) {
	.ats-header__burger { display: none; }
}

/* Sticky-режим: тень появляется через opacity, компактность — мгновенным
   изменением padding (без transition, чтобы не анимировать не-transform/opacity свойство) */
.ats-header--sticky {
	position: sticky;
	top: 0;
}

.ats-header--sticky::after {
	content: "";
	position: absolute;
	top: auto;
	right: 0;
	bottom: -1px;
	left: 0;
	height: 1px;
	box-shadow: var(--shadow-sm);
	opacity: 0;
	transition: opacity var(--t-base) var(--ease-standard);
}

.ats-header--sticky.is-scrolled::after {
	opacity: 1;
}

.ats-header--sticky.is-scrolled .ats-header__inner {
	padding-block: var(--space-2);
}

/* Mega-menu */
.ats-mega-menu {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--space-6);
	background: var(--surface-base);
	border-top: 1px solid var(--border-default);
	box-shadow: var(--shadow-lg);
	padding: var(--space-6);
	opacity: 0;
	transform: translateY(-8px);
	pointer-events: none;
	transition: opacity var(--t-base) var(--ease-standard), transform var(--t-base) var(--ease-standard);
	z-index: 90;
}

.ats-mega-menu.is-open {
	opacity: 1;
	transform: translateY(0);
	pointer-events: auto;
}

@media (min-width: 1024px) {
	.ats-mega-menu { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 1280px) {
	.ats-mega-menu { grid-template-columns: repeat(4, 1fr); }
}

.ats-mega-menu__title {
	font-family: var(--font-display);
	font-size: .8125rem;
	font-weight: 700;
	color: var(--text-muted);
	text-transform: uppercase;
	letter-spacing: .02em;
	margin-bottom: var(--space-3);
}

/* Mobile menu */
/*
 * Стороны выписаны по отдельности, а не одним inset — и так во всём файле.
 * inset понимает Safari с 14.1, а на iOS 12–14.0 свойство игнорируется
 * целиком: панель садилась по месту в потоке, при этом header.js ставил
 * <html> overflow:hidden. Меню не открывалось, а страница под ним оставалась
 * заблокированной — выйти можно было только перезагрузкой.
 */
.ats-mobile-menu {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 200;
	background: var(--surface-base);
	overflow-y: auto;
	padding: var(--space-6) var(--space-4);
	transform: translateX(100%);
	/*
	 * visibility:hidden (с задержкой transition, равной длительности сдвига)
	 * — закрытое меню раньше оставалось табабельным при translateX(100%):
	 * оно физически за кадром, но клавиатурная навигация (Tab) всё равно
	 * заходила внутрь скрытой панели. Найдено ревизией через агентов Fable,
	 * 2026-08-06, см. docs/11-audit-fable-2026-08-06.md, П1.17.
	 */
	visibility: hidden;
	transition: transform var(--t-slow) var(--ease-standard), visibility 0s linear var(--t-slow);
}

.ats-mobile-menu.is-open {
	transform: translateX(0);
	visibility: visible;
	transition: transform var(--t-slow) var(--ease-standard), visibility 0s linear 0s;
}

@media (min-width: 1280px) {
	.ats-mobile-menu { display: none; }
}

.ats-mobile-menu__inner {
	display: flex;
	flex-direction: column;
	gap: var(--space-6);
	max-width: 360px;
	margin-inline: auto;
}

.ats-mobile-menu__close {
	display: flex;
	align-items: center;
	justify-content: center;
	align-self: flex-end;
	/* Тач-цель 44px по норме (был голый 24px svg без паддинга-хитбокса). */
	min-width: 44px;
	min-height: 44px;
	background: none;
	border: none;
	color: var(--text-primary);
	cursor: pointer;
}

.ats-mobile-menu__link {
	display: block;
	padding: var(--space-4) 0;
	font-size: 1.0625rem;
	font-weight: 600;
	color: var(--text-primary);
	text-decoration: none;
	border-bottom: 1px solid var(--border-default);
}

.ats-mobile-menu__contacts {
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
	padding-top: var(--space-4);
}

.ats-mobile-menu__messengers {
	display: flex;
	gap: var(--space-2);
}

/* =====================================================
   Footer
   ===================================================== */

.ats-footer {
	background: var(--surface-inverse);
	color: var(--text-inverse);
	padding-block: var(--space-16) var(--space-8);
}

/*
 * Запас снизу под мобильную .ats-sticky-bar: она fixed и на самом низу
 * страницы ложится поверх последних строк подвала — а там реквизиты ООО и
 * ссылки на политику и согласие, то есть обязательная по закону информация,
 * которую нельзя перекрывать. Ревизия дизайна 2026-08-18.
 */
@media (max-width: 1023.98px) {
	.ats-footer {
		padding-bottom: calc(var(--space-8) + var(--ats-sticky-bar-h) + env(safe-area-inset-bottom));
	}
}

.ats-footer a {
	color: var(--text-inverse-muted);
	text-decoration: none;
}

.ats-footer a:hover {
	color: var(--text-inverse);
	text-decoration: underline;
}

.ats-footer__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-8);
}

@media (min-width: 768px) {
	.ats-footer__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
	.ats-footer__grid { grid-template-columns: repeat(4, 1fr); }
}

.ats-footer__heading {
	font-family: var(--font-display);
	/* Caption-стиль (та же система, что .ats-caption/eyebrow секций) —
	   раньше заголовки колонок сливались с обычными ссылками по кеглю. */
	font-size: .8125rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .05em;
	color: var(--text-inverse);
	margin-bottom: var(--space-4);
}

/*
 * Классы ниже — раньше отсутствовали в CSS, хотя site-footer.php их уже
 * выводит (__col/__menu/__contacts/__address/__hours/__messengers/__legal*).
 * Найдено ревизией через агентов Fable, 2026-08-06, см.
 * docs/11-audit-fable-2026-08-06.md, П1.18.
 */
.ats-footer__menu li,
.ats-footer__contacts li {
	margin-bottom: var(--space-2);
}

.ats-footer__contacts li {
	display: flex;
	align-items: center;
	gap: var(--space-2);
}

.ats-footer__address {
	align-items: flex-start !important;
}

.ats-footer__messengers {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2);
	margin-top: var(--space-4);
}

/*
 * Tertiary-кнопки мессенджеров на тёмном футере: --action-secondary (#2851FF)
 * на ink-950 даёт всего ~3.4:1 — токен --text-link-inverse введён в v2 ровно
 * для ссылок на тёмных поверхностях (5.11:1). Полиш-проход 2026-08-11.
 */
.ats-footer .ats-btn--tertiary {
	color: var(--text-link-inverse);
}

.ats-footer .ats-btn--tertiary:hover:not(:disabled) {
	background: rgba(255, 255, 255, .08);
	color: var(--text-inverse);
}

.ats-footer__bottom {
	margin-top: var(--space-12);
	padding-top: var(--space-6);
	border-top: 1px solid rgba(255, 255, 255, .12);
	font-size: .8125rem;
	color: var(--text-inverse-muted);
}

/*
 * Flex space-between был раньше на .ats-footer__bottom, но единственный её
 * прямой ребёнок — .ats-footer__bottom-inner (с .ats-container для отступов
 * по ширине), внутри которого лежат оба <p> — правило работать не могло.
 */
.ats-footer__bottom-inner {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-4);
	justify-content: space-between;
}

.ats-footer__legal-links a {
	text-decoration: underline;
}

/* =====================================================
   Sticky bottom bar (мобильный call/WA/заявка)
   position: fixed держит CLS = 0
   ===================================================== */

/*
 * Высота 64px, 2 действия (не 3 — WhatsApp переехал в .ats-chat-quick) —
 * см. Design Specification / decisions-log 2026-08-05.
 * header.js показывает панель только после скролла на revealThreshold
 * (240px, .is-visible), но CSS не имел ни скрытого дефолта, ни правила
 * .is-visible — панель висела с первого пикселя и на мобильном сразу
 * перекрывала контент. transform вместо display, чтобы grid/центрирование
 * не пересчитывались при каждом появлении. Найдено ревизией через агентов
 * Fable, 2026-08-06, см. docs/11-audit-fable-2026-08-06.md, П1.19.
 */
.ats-sticky-bar {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 150;
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	min-height: var(--ats-sticky-bar-h);
	gap: var(--space-2);
	background: var(--surface-base);
	border-top: 1px solid var(--border-default);
	box-shadow: var(--shadow-up);
	padding: var(--space-2) var(--space-2) calc(var(--space-2) + env(safe-area-inset-bottom));
	transform: translateY(100%);
	transition: transform var(--t-base) var(--ease-standard);
}

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

@media (min-width: 1024px) {
	.ats-sticky-bar { display: none; }
}

.ats-sticky-bar__item {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 2px;
	padding: var(--space-1);
	border-radius: var(--r-md);
	/* 12px — минимум для подписи кликабельного элемента; было 11px. */
	font-size: .75rem;
	font-weight: 600;
	text-decoration: none;
	color: var(--text-secondary);
}

/* "Позвонить" — ink (нейтральный тёмный), не брендовый синий, по спеке. */
.ats-sticky-bar__item--call { color: var(--text-primary); }
.ats-sticky-bar__item--lead { color: var(--action-primary); }

/* =====================================================
   Cookie banner
   position: fixed держит CLS = 0
   ===================================================== */

.ats-cookie-banner {
	position: fixed;
	left: var(--space-4);
	right: var(--space-4);
	bottom: calc(var(--space-4) + 68px);
	z-index: 180;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-4);
	background: var(--surface-inverse);
	color: var(--text-inverse);
	border-radius: var(--r-lg);
	box-shadow: var(--shadow-lg);
	padding: var(--space-4) var(--space-5);
	opacity: 0;
	transform: translateY(16px);
	pointer-events: none;
	transition: opacity var(--t-slow) var(--ease-standard), transform var(--t-slow) var(--ease-standard);
}

.ats-cookie-banner.is-visible {
	opacity: 1;
	transform: translateY(0);
	pointer-events: auto;
}

.ats-cookie-banner p {
	color: var(--text-inverse-muted);
	font-size: .875rem;
	flex: 1 1 240px;
}

/* Ссылка на политику внутри тёмного баннера: глобальный --text-link (#2851FF)
   на ink-950 даёт ~3.4:1 — тот же случай, что мессенджеры футера; применён
   токен для тёмных поверхностей. Полиш-проход 2026-08-11, круг 2. */
.ats-cookie-banner a {
	color: var(--text-link-inverse);
}

.ats-cookie-banner a:hover {
	color: var(--text-inverse);
}

@media (min-width: 768px) {
	.ats-cookie-banner { left: auto; max-width: 420px; }
}

@media (min-width: 1024px) {
	.ats-cookie-banner { bottom: var(--space-6); }
}

/* =====================================================
   Хлебные крошки — положение в потоке страницы
   (визуальный стиль самого компонента — в components.css)
   ===================================================== */

.ats-breadcrumbs {
	margin-block-start: var(--space-4);
}

@media (min-width: 1024px) {
	.ats-breadcrumbs { margin-block-start: var(--space-6); }
}

/* =====================================================
   Заголовок секции: надзаголовок-eyebrow (.ats-caption) + h2
   ===================================================== */

/*
 * Появился 2026-08-10 — раньше крупные секции страницы направления
 * (транспорт, гарантии, FAQ, соседние направления...) шли подряд без
 * собственных заголовков и читались "кучей карточек". Паттерн — из Design
 * Specification: caption-надзаголовок (утилита .ats-caption из base.css там
 * была описана, но нигде не использовалась) + H2. Решение заказчика, см.
 * docs/02-decisions-log.md.
 */
.ats-section-head {
	margin-bottom: var(--space-6);
}

@media (min-width: 1024px) {
	.ats-section-head { margin-bottom: var(--space-8); }
}

/* Ссылка «Все направления» под сеткой: тот же вертикальный шаг, что и над
   сеткой у .ats-section-head, чтобы блок читался симметрично. */
.ats-section-more {
	margin-top: var(--space-6);
	display: flex;
	justify-content: center;
}

@media (min-width: 1024px) {
	.ats-section-more { margin-top: var(--space-8); }
}

.ats-section-head .ats-caption {
	display: block;
	margin-bottom: var(--space-2);
	color: var(--brand-600);
}

.ats-section-head h2 {
	text-wrap: balance;
}

/* =====================================================
   Hero
   ===================================================== */

/*
 * Hero — по умолчанию тёмный (ink-950), концепция B из Design Specification:
 * "технологичность через тёмный фон + светящаяся сеть маршрутов", решение
 * заказчика от 2026-08-05 (см. docs/02-decisions-log.md). Текст внутри hero
 * переопределён на inverse-тона явно (а не унаследован от body), т.к. базовые
 * h1/p/li используют var(--text-primary) — тёмный, непригодный на тёмном фоне.
 */
.ats-hero {
	position: relative;
	overflow: hidden;
	padding-block: var(--space-10) var(--space-12);
	background: var(--surface-inverse);
	color: var(--text-inverse);
	/*
	 * isolation — чтобы z-index слоёв героя (видео 0, сеть 1, подложка 2,
	 * текст 3) считались внутри него, а не относительно всей страницы: иначе
	 * sticky-шапка со своим z-index:100 попадала бы в тот же контекст.
	 * Ревизия композиции 2026-08-22.
	 */
	isolation: isolate;
}

/*
 * Первый экран главной. Он единственный на сайте занимает почти весь вид, и
 * высота задана через clamp, а не 100dvh: полный экран на ноутбуке 13" уводил
 * полосу доверия и первую секцию полностью за сгиб, и страница выглядела так,
 * будто на ней ничего нет, кроме заголовка. Верхняя граница 720px оставляет
 * следующий блок подглядывающим снизу — это и есть приглашение прокрутить,
 * поэтому отдельной подписи "листайте вниз" не нужно.
 */
.ats-hero--home {
	display: grid;
	align-items: center;
	min-height: clamp(460px, 66vh, 660px);
	padding-block: var(--space-16) var(--space-12);
}

/*
 * Подложка под текстом. Не декоративный градиент из списка запретов, а
 * средство контраста: белый заголовок ложится поверх видео и светящихся линий
 * сети, и без неё проваливает 4.5:1 на светлых участках кадра. Плотность
 * убывает вправо — слева, под текстом, почти непрозрачная, справа пропускает
 * графику. Тот же тон ink-950, что и фон героя, поэтому там, где подложка
 * плотная, она неотличима от фона и не читается как отдельный слой.
 */
.ats-hero--home::before {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	/*
	 * Слой 1 — между видео (0) и сетью маршрутов (2). Подложка гасит видео, но
	 * не сеть: сеть — единственная графика первого экрана, когда файла видео
	 * ещё нет, и накрытая подложкой она пропадала полностью. Линии тонкие
	 * (1.5px) и текст поверх них норму держит: контраст считается по фону, а
	 * не по волоску, пересекающему букву.
	 */
	z-index: 1;
	pointer-events: none;
	background: linear-gradient(
		100deg,
		rgba(11, 13, 18, .96) 0%,
		rgba(11, 13, 18, .9) 40%,
		rgba(11, 13, 18, .58) 74%,
		rgba(11, 13, 18, .42) 100%
	);
}

/* Ниже 1024 ни видео, ни сети нет — подложке нечего затемнять, а лишний слой
   поверх сплошного фона только съедает кадр отрисовки. */
@media (max-width: 1023.98px) {
	.ats-hero--home::before { display: none; }
}

.ats-hero__col {
	max-width: 44rem;
}

/*
 * Отдельная шкала для главного заголовка сайта: он крупнее любого другого h1
 * и на широком экране доходит до 4.25rem против 3.5rem у остальных страниц.
 * Это единственное место, где размер работает как приём, а не как уровень
 * иерархии, поэтому исключение точечное, а не сдвиг всей шкалы в base.css.
 */
/*
 * Плашка ЭТрН над заголовком первого экрана (2026-09-14). Не кнопка и не
 * надзаголовок: ссылка-пилюля на разворот про накладную ниже. Тон — полу-
 * прозрачный белый на тёмном, как у границы полосы доверия, чтобы не спорить
 * ни с оранжевой кнопкой, ни с заголовком.
 */
.ats-hero__badge {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	max-width: 100%;
	margin-bottom: var(--space-5);
	padding: var(--space-2) var(--space-4) var(--space-2) var(--space-3);
	border: 1px solid rgba(255, 255, 255, .22);
	border-radius: var(--r-full);
	background: rgba(255, 255, 255, .06);
	font-size: .875rem;
	font-weight: 600;
	line-height: 1.3;
	color: var(--text-inverse);
	text-decoration: none;
	transition:
		background-color var(--t-fast) var(--ease-standard),
		border-color var(--t-fast) var(--ease-standard);
}

.ats-hero__badge:hover,
.ats-hero__badge:focus-visible {
	background: rgba(255, 255, 255, .12);
	border-color: rgba(255, 255, 255, .4);
	color: var(--text-inverse);
}

.ats-hero__badge .ats-icon {
	color: var(--brand-300);
}

.ats-hero__badge-arrow {
	transition: transform var(--t-fast) var(--ease-standard);
}

.ats-hero__badge:hover .ats-hero__badge-arrow {
	transform: translateX(2px);
}

/* Стрелка внутри плашки — тем же цветом, что текст: она про переход, а не
   про иконку документа. */
.ats-hero__badge .ats-hero__badge-arrow {
	color: var(--text-inverse-muted);
}

.ats-hero__title {
	font-size: clamp(2.25rem, 1.35rem + 3.6vw, 3.75rem);
	line-height: 1.02;
	letter-spacing: -.03em;
}

.ats-hero--home .ats-hero__lead {
	max-width: 46ch;
	margin-block: var(--space-5) var(--space-8);
	font-size: clamp(1.0625rem, 1rem + .3vw, 1.25rem);
}

/* ---- Слой видео ---- */

/*
 * Видео появляется только с 1024: на телефоне его не показывает и hero-media.js
 * (он же не даёт браузеру начать загрузку), но правило нужно и в CSS — иначе
 * между разбором стилей и запуском отложенного скрипта элемент успевал занять
 * место в потоке.
 */
.ats-hero__media {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 0;
	display: none;
	overflow: hidden;
	pointer-events: none;
}

@media (min-width: 1024px) {
	.ats-hero__media { display: block; }
}

.ats-hero__video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Видео — фон, а не иллюстрация: приглушено, чтобы не спорить с текстом и
	   с линиями сети, которые идут поверх него. */
	opacity: .55;
}

.ats-hero h1 {
	color: var(--text-inverse);
}

/* Модификатор для страниц услуг (single-ats_service.php) — светлый плоский
   фон, альтернатива тёмному hero-B (элементы концепции A из спеки). */
.ats-hero--light {
	background: var(--surface-base);
	color: var(--text-primary);
	border-bottom: 1px solid var(--border-default);
}

.ats-hero--light h1 {
	color: var(--text-primary);
}

.ats-hero__lead {
	max-width: 60ch;
	margin-block: var(--space-4) var(--space-6);
	font-size: 1.0625rem;
	color: var(--text-inverse-muted);
}

.ats-hero--light .ats-hero__lead {
	color: var(--text-secondary);
}

@media (min-width: 768px) {
	.ats-hero__lead { font-size: 1.1875rem; }
}

.ats-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-3);
}

.ats-hero__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2) var(--space-5);
	margin-block: var(--space-4);
	list-style: none;
	font-size: .9375rem;
	color: var(--text-inverse-muted);
}

.ats-hero--light .ats-hero__meta {
	color: var(--text-secondary);
}

.ats-hero__meta li {
	display: flex;
	align-items: center;
	gap: var(--space-2);
}

/* Брендовый тон иконок меты — без него иконки сливались с текстом в одну
   серую массу; на тёмном hero светлый брендовый тон, на светлом — основной. */
.ats-hero__meta .ats-icon {
	color: var(--brand-300);
}

.ats-hero--light .ats-hero__meta .ats-icon {
	color: var(--brand-600);
}

.ats-hero__price {
	font-family: var(--font-mono);
	font-weight: 600;
	font-size: 1.25rem;
	color: var(--text-inverse);
	margin-bottom: var(--space-5);
}

.ats-hero--light .ats-hero__price {
	color: var(--brand-700);
}

@media (min-width: 768px) {
	.ats-hero__price { font-size: 1.5rem; }
}

/*
 * --- Маршрутная нить: signature-элемент бренда ---
 * Структура: [точка][город] --линия-- [точка][город]. .ats-hero__route-point —
 * чистый 10px кружок-маркер (без иконки/текста внутри — раньше оба лежали
 * внутри point, а class __route-city не использовался вовсе, из-за чего CSS
 * ниже никогда не применялся к тексту города). Найдено ревизией через
 * агентов Fable, 2026-08-06, см. docs/11-audit-fable-2026-08-06.md, П1.8.
 */
.ats-hero__route {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	margin-block: var(--space-6);
	max-width: 480px;
}

.ats-hero__route-city {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	gap: var(--space-1);
	font-family: var(--font-display);
	font-weight: 700;
	font-size: .9375rem;
	white-space: nowrap;
	color: var(--text-inverse);
}

.ats-hero--light .ats-hero__route-city {
	color: var(--text-primary);
}

.ats-hero__route-point {
	flex-shrink: 0;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--action-primary);
}

.ats-hero__route-line {
	position: relative;
	flex: 1;
	height: 2px;
	background: rgba(255, 255, 255, .16);
	overflow: hidden;
	border-radius: var(--r-full);
}

.ats-hero--light .ats-hero__route-line {
	background: var(--border-default);
}

.ats-hero__route-line::after {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: 40%;
	background: linear-gradient(90deg, transparent, var(--brand-500), transparent);
	transform: translateX(-100%);
	animation: ats-route-flow var(--t-signature) var(--ease-standard) infinite;
}

@keyframes ats-route-flow {
	to { transform: translateX(250%); }
}

/*
 * --- "Оборванный маршрут" (404) ---
 * Пунктирная неподвижная линия вместо анимированного "потока" + красная
 * точка назначения — визуальная метафора "маршрут не найден". Ранее
 * модификатор не имел стилей вовсе.
 */
.ats-hero__route--broken .ats-hero__route-line {
	background: repeating-linear-gradient(
		90deg,
		rgba(255, 255, 255, .35) 0,
		rgba(255, 255, 255, .35) 6px,
		transparent 6px,
		transparent 12px
	);
}

.ats-hero__route--broken .ats-hero__route-line::after {
	display: none;
}

.ats-hero__route--broken .ats-hero__route-point--to {
	background: var(--error);
}

/*
 * --- Вступление страницы направления ---
 *
 * Ни фона, ни рамки, ни скругления: раньше здесь была тёмная карточка, и она
 * выделяла вступление сильнее, чем текст направления под ним, а краями не
 * совпадала ни с крошками сверху, ни с оглавлением справа. Тёмный герой
 * остался на главной, где занимает первый экран целиком и работает обложкой.
 *
 * Единственная граница — тонкая линия под цифрами: она отделяет вступление
 * от остальной страницы, не превращая его в отдельный блок.
 */
.ats-route-hero {
	padding-block: var(--space-2) var(--space-4);
}

/*
 * --- Заголовок-маршрут страницы направления ---
 *
 * Раньше первый экран называл города дважды: в h1 и в маршрутной нити под
 * ним. Дублирование съедало половину высоты героя, а сам h1 при этом рвался
 * по дефису — «Санкт-» / «Петербург». Теперь нить проведена между городами
 * внутри заголовка: тот же signature-элемент, но он показывает маршрут, а не
 * повторяет уже написанное.
 */
.ats-route-head {
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
	/*
	 * Кегль ниже общего h1 (до 3.5rem) намеренно. В заголовке направления не
	 * одно слово, а два длинных топонима и нить между ними; на 3.5rem пара
	 * «Санкт-Петербург — Владивосток» не помещалась в колонку рядом с
	 * оглавлением и разваливалась на три строки. 2.75rem — предел, при
	 * котором самая длинная пара из базы ещё встаёт в строку на ноутбуке.
	 */
	font-size: clamp(1.75rem, 1.1rem + 2.2vw, 2.75rem);
}

/*
 * Надзаголовок в общей caption-системе сайта (.ats-caption у секций). Слово
 * «Грузоперевозки» вынесено из строки с городами не для красоты: в одной
 * строке оно было третьим длинным словом и заставляло заголовок ломаться
 * ещё до городов.
 */
.ats-route-head__eyebrow {
	display: block;
	font-size: .8125rem;
	font-weight: 700;
	line-height: 1;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--brand-600);
}

.ats-route-head__pair {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--space-3) var(--space-5);
}

/*
 * nowrap — то самое, ради чего заголовок разобран на части. Название города
 * не переносится никогда, даже если в нём есть дефис: разорванный посередине
 * топоним читается как опечатка, а не как перенос.
 */
.ats-route-head__city {
	white-space: nowrap;
}

/*
 * Нить между городами. flex-basis 0 с min-width — чтобы она сжималась первой
 * и уступала место названиям: города обязаны поместиться целиком, нить
 * декоративна и может стать короткой.
 */
.ats-route-head__thread {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	flex: 1 1 0;
	min-width: 3rem;
}

/*
 * Точки маршрута синие, а не оранжевые, как в тёмном герое: оранжевый на
 * сайте закреплён за главным действием и на светлом холсте даёт 2.67:1 —
 * ниже нормы 3:1 для нетекстовой графики. Синий даёт 4.87:1.
 */
.ats-route-head__dot {
	flex-shrink: 0;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--brand-600);
}

/* Та же бегущая подсветка, что у нити в тёмном герое (@keyframes
   ats-route-flow), — элемент бренда один и тот же, меняется только тон
   основания под светлый фон. */
.ats-route-head__line {
	position: relative;
	flex: 1;
	height: 2px;
	overflow: hidden;
	border-radius: var(--r-full);
	background: var(--border-strong);
}

.ats-route-head__line::after {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: 40%;
	background: linear-gradient(90deg, transparent, var(--brand-500), transparent);
	transform: translateX(-100%);
	animation: ats-route-flow var(--t-signature) var(--ease-standard) infinite;
}

/*
 * Когда пара не уместилась в строку и города встали друг под другом,
 * горизонтальная нить между ними теряет смысл — она соединяла бы то, что
 * больше не стоит рядом. Прячем: точки маршрута остаются в самой сетке
 * заголовка, а роль связки берёт на себя вертикальный ритм.
 */
@media (max-width: 639px) {
	.ats-route-head__pair {
		display: grid;
		gap: var(--space-2);
		justify-items: start;
	}

	.ats-route-head__thread {
		width: 100%;
	}
}

/*
 * --- Характеристики маршрута ---
 *
 * Открытая строка, а не сетка залитых ячеек. Ячейки читались как таблица,
 * положенная поверх фона, и при пяти пунктах последняя строка оставалась
 * наполовину пустой — дыра в прямоугольнике, которую видно первой.
 *
 * Теперь это flex: пункты занимают ровно свою ширину, перенос ничего не
 * ломает, пустых клеток не бывает по устройству. Границы только сверху и
 * снизу — они отделяют цифры от заголовка и от текста, не обводя их в рамку.
 */
.ats-route-specs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-5) var(--space-10);
	margin-block: var(--space-6) var(--space-8);
	padding-block: var(--space-5);
	border-block: 1px solid var(--border-default);
}

.ats-route-specs__item {
	display: flex;
	flex-direction: column;
	gap: var(--space-1);
	/* Длинная «Отправки» не должна растягивать строку до края: на узком
	   экране она переносится внутри себя, а не выдавливает соседей. */
	max-width: 22ch;
}

.ats-route-specs__label {
	font-size: .75rem;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--text-muted);
}

.ats-route-specs__value {
	margin: 0;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.0625rem;
	line-height: 1.35;
	color: var(--text-primary);
}

/* Цифры моноширинным — как тарифы и реквизиты по всему сайту: одинаковая
   ширина знака не даёт значениям плясать при разной длине чисел. */
.ats-route-specs__num {
	font-family: var(--font-mono);
	font-size: 1.25rem;
	letter-spacing: -.02em;
}

/*
 * --- "Веер рейсов": декоративный фон hero, замена фотографии автопарка ---
 * Осознанное расхождение с UX/UI-спецификацией (п. "Запрещено": "анимации на
 * первом экране") — решение заказчика от 2026-08-01, см. docs/02-decisions-log.md.
 * Требования, которые всё равно соблюдены: не параллакс (чистый SVG+CSS, вес
 * < 3 КБ разметки), развитие уже существующего фирменного мотива "маршрутной
 * нити" (.ats-hero__route выше), а не случайный сторонний эффект; только
 * desktop (как и фото автопарка, которое заменяет, по B-01: "только desktop");
 * подчиняется глобальному prefers-reduced-motion (base.css) без дополнительного
 * кода — все анимации ниже используют animation, которую общее правило уже
 * глушит до .01ms.
 *
 * Ревизия композиции 2026-08-22: линии сведены в один узел отправления, добавлены
 * разметочная сетка и точки назначения. Слой поднят НАД видео (z-index 1 против
 * 0 у .ats-hero__media): линии, идущие поверх движущегося кадра, — это и есть
 * задуманный эффект, а не наложение по недосмотру.
 */
.ats-hero__network {
	position: absolute;
	/*
	 * Сеть занимает правую часть первого экрана, а не всю его ширину. Когда она
	 * шла во всю ширину, линии проходили прямо сквозь заголовок и подзаголовок:
	 * читалось это не как карта позади текста, а как брак вёрстки. Текст живёт
	 * слева (.ats-hero__col, максимум 44rem), карта — справа, и они не спорят.
	 * Узел отправления оказывается у левого края карты, то есть ровно там, где
	 * заканчивается текст: рейсы уходят от него вправо.
	 */
	top: 0;
	right: 0;
	bottom: 20%;
	left: 52%;
	z-index: 2;
	display: none;
	overflow: hidden;
	pointer-events: none;
	/* Края гасятся с обеих сторон, чтобы линии не упирались в границы блока
	   обрубленными концами. */
	mask-image: linear-gradient(to right, transparent 0%, black 14%, black 84%, transparent 100%);
	-webkit-mask-image: linear-gradient(to right, transparent 0%, black 14%, black 84%, transparent 100%);
}

/*
 * Карта появляется с 1200, а не с 1024. Замер: при 3.75rem самая длинная строка
 * заголовка («Санкт-Петербурга») занимает около 530px, и левая половина должна
 * быть шире неё с запасом. На 1024 половина — 512px, то есть заголовок уходил
 * бы под узел отправления. На 1200 половина 624px, запас есть.
 */
@media (min-width: 1200px) {
	.ats-hero__network { display: block; }
}

/* От 1440 запас слева больше, карте можно отдать чуть больше места. */
@media (min-width: 1440px) {
	.ats-hero__network { left: 48%; }
}

.ats-hero__network svg {
	width: 100%;
	height: 100%;
}

/* Разметочная сетка — самый глубокий слой. Непрозрачность на пороге
   различимости: она должна ощущаться как фактура штурманской карты, а не
   читаться как таблица. */
.ats-hero__grid path {
	fill: none;
	stroke: rgba(255, 255, 255, .07);
	stroke-width: 1;
}

/* Сама разметка (.ats-hero__content) должна оставаться поверх сети — см. правило ниже. */
.ats-hero__content {
	position: relative;
	z-index: 3;
}

/* pathLength="100" — SVG-атрибут на самом <path> (не CSS-свойство), задаёт
   единицы stroke-dasharray/-dashoffset независимо от реальной длины кривой. */
.ats-hero__lane {
	fill: none;
	stroke-width: 1.5;
	stroke-linecap: round;
	stroke-dasharray: 100;
	stroke-dashoffset: 100;
	/* --ease-expo вместо --ease-out: линия почти всю анимацию замедляется, и
	   рейс "дотягивается" до города, а не приезжает рывком. */
	animation: ats-lane-draw 1.8s var(--ease-expo) forwards;
}

/* Непрозрачность поднята относительно v1: на тёмном ink-950 (hero-B) светлые
   линии читаются как "свечение" сети маршрутов, а не как фоновый шум. */
.ats-hero__lane--1 { stroke: var(--brand-300); opacity: .85; animation-delay: 120ms; }
.ats-hero__lane--2 { stroke: var(--brand-400); opacity: .8; animation-delay: 240ms; }
.ats-hero__lane--3 { stroke: var(--brand-500); opacity: .75; animation-delay: 360ms; }
.ats-hero__lane--4 { stroke: var(--brand-400); opacity: .7; animation-delay: 480ms; }
.ats-hero__lane--5 { stroke: var(--accent-500); opacity: .9; animation-delay: 600ms; }

/* .ats-hero--light — та же сеть поверх светлого фона, непрозрачность ниже
   (иначе линии будут слишком контрастными на белом/светлом). */
.ats-hero--light .ats-hero__lane--1 { opacity: .3; }
.ats-hero--light .ats-hero__lane--2 { opacity: .28; }
.ats-hero--light .ats-hero__lane--3 { opacity: .22; }
.ats-hero--light .ats-hero__lane--4 { opacity: .2; }
.ats-hero--light .ats-hero__lane--5 { opacity: .4; }

@keyframes ats-lane-draw {
	to { stroke-dashoffset: 0; }
}

/* Точки назначения зажигаются после того, как до них дорисовалась линия:
   задержка каждой = задержка её линии + длительность отрисовки. */
.ats-hero__node {
	opacity: 0;
	fill: var(--brand-300);
	animation: ats-node-in var(--t-slow) var(--ease-out) forwards;
}

.ats-hero__node--1 { animation-delay: 1.9s; }
.ats-hero__node--2 { animation-delay: 2.02s; }
.ats-hero__node--3 { animation-delay: 2.14s; }
.ats-hero__node--4 { animation-delay: 2.26s; }
.ats-hero__node--5 { fill: var(--accent-500); animation-delay: 2.38s; }

@keyframes ats-node-in {
	from { opacity: 0; }
	to { opacity: .9; }
}

/* Узел отправления — Санкт-Петербург. Единственная оранжевая точка покоя на
   первом экране: акцент отмечает то, откуда всё идёт. */
.ats-hero__hub {
	fill: var(--accent-500);
}

.ats-hero__hub-ring {
	fill: none;
	stroke: var(--accent-500);
	stroke-width: 1.5;
	transform-origin: 70px 350px;
	animation: ats-hub-pulse 3.6s var(--ease-out) infinite;
}

@keyframes ats-hub-pulse {
	0% { transform: scale(1); opacity: .7; }
	70% { transform: scale(2.6); opacity: 0; }
	100% { transform: scale(2.6); opacity: 0; }
}

/* "Грузы" — точки, непрерывно бегущие вдоль своих маршрутов (offset-path
   продублирован из "d" соответствующего .ats-hero__lane). */
.ats-hero__cargo {
	r: 3.5;
	animation-name: ats-cargo-move;
	animation-timing-function: linear;
	animation-iteration-count: infinite;
}

.ats-hero__cargo--1 { fill: var(--brand-300); offset-path: path('M 70 350 C 300 200, 560 120, 880 90'); animation-duration: 6.4s; animation-delay: 2.1s; }
.ats-hero__cargo--2 { fill: var(--brand-400); offset-path: path('M 70 350 C 320 300, 600 250, 890 215'); animation-duration: 7.8s; animation-delay: 2.6s; }
.ats-hero__cargo--3 { fill: var(--brand-400); offset-path: path('M 70 350 C 330 370, 620 380, 890 360'); animation-duration: 5.6s; animation-delay: 3.1s; }
.ats-hero__cargo--4 { fill: var(--brand-500); offset-path: path('M 70 350 C 310 430, 580 500, 870 520'); animation-duration: 6.9s; animation-delay: 3.6s; }
.ats-hero__cargo--5 { fill: var(--accent-500); offset-path: path('M 70 350 C 280 260, 480 90, 700 40'); animation-duration: 5.2s; animation-delay: 4.1s; }

@keyframes ats-cargo-move {
	0% { offset-distance: 0%; opacity: 0; }
	6% { opacity: 1; }
	94% { opacity: 1; }
	100% { offset-distance: 100%; opacity: 0; }
}

/* =====================================================
   Trust bar
   ===================================================== */

.ats-trust-bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--space-6);
	padding-block: var(--space-6);
	border-block: 1px solid var(--border-default);
}

.ats-trust-bar__item {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	font-size: .875rem;
	font-weight: 500;
	color: var(--text-secondary);
}

.ats-trust-bar__item .ats-icon {
	color: var(--brand-600);
}

/* =====================================================
   Формы
   ===================================================== */

.ats-form-quick {
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
	background: var(--surface-base);
	border-radius: var(--r-lg);
	box-shadow: var(--shadow-md);
	padding: var(--space-5);
}

.ats-form-quick .ats-field { margin-bottom: 0; }

/* Чекбокс согласия внутри обеих форм: свой margin-bottom (модификатор
   --consent) складывался с gap контейнера в двойной отступ. Полиш-проход
   2026-08-11, круг 2. */
.ats-form-quick .ats-checkbox--consent,
.ats-form-full .ats-checkbox--consent {
	margin-bottom: 0;
}

@media (min-width: 768px) {
	.ats-form-quick {
		flex-direction: row;
		align-items: flex-start;
		flex-wrap: wrap;
	}

	.ats-form-quick .ats-field { flex: 1 1 200px; }
	.ats-form-quick .ats-btn { flex-shrink: 0; }

	/* Согласие — на свою строку: зажатое между полями и кнопкой в один ряд,
	   оно рвало выравнивание строки. */
	.ats-form-quick .ats-checkbox--consent { flex: 1 1 100%; }
}

.ats-form-full {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-4);
	background: var(--surface-base);
	border: 1px solid var(--border-default);
	border-radius: var(--r-lg);
	padding: var(--space-6);
}

@media (min-width: 768px) {
	.ats-form-full { grid-template-columns: repeat(2, 1fr); padding: var(--space-8); }
}

/* Вертикальный ритм строк формы: собственный margin-bottom поля складывался
   с gap сетки в 32px по вертикали против 16px по горизонтали. */
.ats-form-full .ats-field { margin-bottom: 0; }

.ats-form-full .ats-field--full {
	grid-column: 1 / -1;
}

/*
 * Fallback-разметка полной формы (class-shortcodes.php) не проставляет
 * .ats-field--full — комментарий-textarea, чекбокс согласия и submit-кнопка
 * занимали пол-колонки 2-колоночной сетки и ломали ритм формы. Селекторы
 * ниже ловят реальную разметку. Полиш-проход 2026-08-11.
 */
.ats-form-full .ats-checkbox--consent,
.ats-form-full > .ats-btn {
	grid-column: 1 / -1;
}

/*
 * :has() вынесен в отдельное правило намеренно.
 *
 * В группе селекторов браузер, который не знает :has(), считает невалидной всю
 * группу и выбрасывает правило целиком — вместе с чекбоксом согласия и
 * кнопкой. На Firefox ≤ 120 (в том числе ESR 115 из корпоративных парков) и
 * Safari/iOS ≤ 15.3 согласие и «Отправить заявку» сжимались в полуколонку и
 * вставали в один ряд: форма выглядела сломанной ровно в тот момент, когда
 * человек решает её отправить. Отдельным правилом теряется только растяжка
 * комментария, и это незаметно.
 */
.ats-form-full .ats-field:has(textarea) {
	grid-column: 1 / -1;
}

.ats-form-full > .ats-btn {
	justify-self: start;
}

/* =====================================================
   Калькулятор
   ===================================================== */

.ats-calculator {
	background: var(--surface-subtle);
	border-radius: var(--r-xl);
	padding: var(--space-6);
}

@media (min-width: 768px) {
	.ats-calculator { padding: var(--space-8); }
}

.ats-calculator__progress {
	display: flex;
	gap: var(--space-2);
	margin-bottom: var(--space-6);
}

.ats-calculator__progress-item {
	flex: 1;
	height: 4px;
	border-radius: var(--r-full);
	background: var(--border-default);
}

.ats-calculator__progress-item.is-active,
.ats-calculator__progress-item.is-done {
	background: var(--action-secondary);
}

/*
 * calculator.js переключает шаги нативным атрибутом [hidden] (goToStep()),
 * а не классом is-active — тот вешается только на [data-step-indicator]
 * (точки прогресса). Раньше здесь было безусловное display:none +
 * .is-active, которого JS никогда не проставлял на сам шаг — калькулятор
 * был не виден целиком. Найдено ревизией через агентов Fable, 2026-08-06,
 * см. docs/11-audit-fable-2026-08-06.md, П0.2. .is-active оставлен как
 * задел под будущий визард с анимацией между шагами.
 */
.ats-calculator__step {
	opacity: 1;
	transform: translateX(0);
	transition: opacity var(--t-base) var(--ease-standard), transform var(--t-base) var(--ease-standard);
}

.ats-calculator__step[hidden] {
	display: none;
}

.ats-calculator__options {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-3);
}

@media (min-width: 480px) {
	.ats-calculator__options { grid-template-columns: repeat(2, 1fr); }
}

.ats-calculator__option {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	padding: var(--space-4);
	border: 1.5px solid var(--border-default);
	border-radius: var(--r-md);
	background: var(--surface-base);
	cursor: pointer;
	transition: border-color var(--t-fast) var(--ease-standard);
}

.ats-calculator__option:hover {
	border-color: var(--border-strong);
}

.ats-calculator__option:has(input:checked) {
	border-color: var(--action-secondary);
	background: var(--surface-brand-soft);
}

.ats-calculator__nav {
	display: flex;
	justify-content: space-between;
	gap: var(--space-3);
	margin-top: var(--space-6);
}

.ats-calculator__result {
	background: var(--surface-brand-soft);
	border-radius: var(--r-lg);
	padding: var(--space-6);
	text-align: center;
}

/*
 * Классы ниже — реальные, которые создаёт assets/js/calculator.js::renderResult()
 * (.ats-calculator__price/__days/__vehicle). Раньше здесь были другие имена
 * (__result-price/__result-meta), которых JS никогда не проставлял — крупная
 * mono-цена, центральный момент калькулятора, не отрисовывалась вообще.
 * Найдено ревизией через агентов Fable, 2026-08-06, см.
 * docs/11-audit-fable-2026-08-06.md, П1.12.
 */
.ats-calculator__price {
	font-family: var(--font-mono);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	font-size: 1.75rem;
	color: var(--brand-800);
}

@media (min-width: 768px) {
	.ats-calculator__price { font-size: 2.25rem; }
}

.ats-calculator__days,
.ats-calculator__vehicle {
	margin-top: var(--space-2);
	color: var(--text-secondary);
	font-size: .9375rem;
}

.ats-calculator__result-actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--space-3);
	margin-top: var(--space-5);
}

/* =====================================================
   Сетки карточек (направления / услуги / транспорт)
   ===================================================== */

.ats-grid-directions,
.ats-grid-services,
.ats-grid-vehicles {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-5);
}

@media (min-width: 480px) {
	.ats-grid-directions,
	.ats-grid-services,
	.ats-grid-vehicles {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 1024px) {
	.ats-grid-directions,
	.ats-grid-services,
	.ats-grid-vehicles {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (min-width: 1280px) {
	.ats-grid-directions,
	.ats-grid-services,
	.ats-grid-vehicles {
		gap: var(--space-6);
	}
}

/* Внутренняя структура карточек: физика — components.css, здесь — контент */
.ats-card-direction__body,
.ats-card-service__body,
.ats-card-vehicle__body,
.ats-card-review__body,
.ats-card-case__body,
.ats-card-post__body {
	display: flex;
	flex-direction: column;
	flex: 1;
	gap: var(--space-2);
	padding: var(--space-5);
}

.ats-card-direction__title,
.ats-card-service__title,
.ats-card-vehicle__title,
.ats-card-case__title,
.ats-card-post__title {
	margin: 0;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.0625rem;
	line-height: 1.3;
	color: var(--text-primary);
}

.ats-card-direction__title a,
.ats-card-service__title a,
.ats-card-vehicle__title a,
.ats-card-case__title a,
.ats-card-post__title a {
	color: inherit;
	text-decoration: none;
}

.ats-card-direction__title a::after,
.ats-card-service__title a::after,
.ats-card-vehicle__title a::after,
.ats-card-case__title a::after,
.ats-card-post__title a::after {
	content: "";
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
}

.ats-card-direction__desc,
.ats-card-service__desc,
.ats-card-vehicle__desc {
	font-size: .875rem;
	color: var(--text-secondary);
}

/*
 * .ats-card-cta — заменяет прежний показ фиксированной цены "от X ₽" на
 * карточках направлений/услуг/транспорта. Решение заказчика 2026-08-08:
 * цены на рейсы договорные (нет прайс-листа), фиксированное число на сайте
 * создавало риск "у вас на сайте написано столько" от клиента. Тот же класс
 * общий для всех трёх типов карточек — визуально это всегда одна и та же
 * ссылка-приглашение, а не число, поэтому разделять по типу карточки не
 * нужно (в отличие от __title/__desc, которые несут разный контент).
 */
.ats-card-cta {
	margin-top: auto;
	padding-top: var(--space-2);
	font-size: .875rem;
	font-weight: 600;
	color: var(--text-link);
}

.ats-card-direction:hover .ats-card-cta,
.ats-card-service:hover .ats-card-cta,
.ats-card-vehicle:hover .ats-card-cta {
	color: var(--text-link-hover);
}

/*
 * Характеристики на карточке транспорта ("1,5 т · 9 м³") — раньше <ul> в
 * шаблонах шёл без класса: reset убирал маркеры, но значения вставали
 * вертикальной колонкой вместо компактной строки. Полиш-проход 2026-08-11.
 */
/* Мета-строка карточки направления (км · срок) — та же типографика, что у
   характеристик транспорта: это один и тот же приём «факты через точку»,
   и разъезжаться они не должны. */
.ats-card-direction__meta,
.ats-card-vehicle__specs {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-1) var(--space-2);
	font-size: .875rem;
	color: var(--text-muted);
	font-variant-numeric: tabular-nums;
}

.ats-card-direction__meta li,
.ats-card-vehicle__specs li {
	display: flex;
	align-items: center;
	gap: var(--space-2);
}

.ats-card-direction__meta li:not(:last-child)::after,
.ats-card-vehicle__specs li:not(:last-child)::after {
	content: "·";
	color: var(--border-strong);
}

/* Стрелка — микро-интеракция при ховере карточки (только transform, layout
   не трогается; глушится глобальным prefers-reduced-motion из base.css). */
.ats-card-cta::after {
	content: " →";
	display: inline-block;
	transition: transform var(--t-fast) var(--ease-standard);
}

.ats-card-direction:hover .ats-card-cta::after,
.ats-card-service:hover .ats-card-cta::after,
.ats-card-vehicle:hover .ats-card-cta::after {
	transform: translateX(4px);
}

.ats-card-direction__footer,
.ats-card-service__footer,
.ats-card-vehicle__footer,
.ats-card-case__footer {
	margin-top: auto;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-3);
	padding: var(--space-4) var(--space-5);
	border-top: 1px solid var(--border-default);
}

/* Отзывы — карточка без фото, текст-цитата */
.ats-card-review__body {
	padding: var(--space-5);
}

.ats-card-review__quote {
	font-size: .9375rem;
	line-height: 1.6;
	color: var(--text-secondary);
}

.ats-card-review__author {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	margin-top: auto;
	padding-top: var(--space-3);
	border-top: 1px solid var(--border-default);
}

.ats-card-review__author-name {
	font-weight: 600;
	font-size: .875rem;
	color: var(--text-primary);
}

.ats-card-review__author-role {
	font-size: .8125rem;
	color: var(--text-muted);
}

/* Имя и должность идут одно под другим внутри блока автора, а сам блок
   выровнен по левому краю — ссылка на скан прижимается к правому. */
.ats-card-review__author > div {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

/* Ссылка на скан отзыва на фирменном бланке: проверяемое доказательство,
   поэтому она видна, но не спорит за внимание с текстом отзыва. */
.ats-card-review__scan {
	display: inline-flex;
	align-items: center;
	gap: var(--space-1);
	margin-left: auto;
	flex-shrink: 0;
	font-size: .8125rem;
	font-weight: 500;
	color: var(--text-muted);
	text-decoration: none;
	transition: color var(--t-fast) var(--ease-standard);
}

.ats-card-review__scan:hover,
.ats-card-review__scan:focus-visible {
	color: var(--brand-700);
}

/* Кейсы — метки над заголовком */
.ats-card-case__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2);
}

/* Мета-список и описание кейса: шаблон direction выводит их голыми <ul>/<p>
   — рендерились основным кеглем без иерархии. Полиш-проход 2026-08-11, круг 2. */
.ats-card-case__body ul {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-1) var(--space-3);
	font-size: .875rem;
	color: var(--text-muted);
}

.ats-card-case__body p {
	font-size: .9375rem;
	color: var(--text-secondary);
}

/* Единственный кейс на странице направления занимал 1/3 ширины 3-колоночной
   сетки — сиротливая узкая карточка. Одиночной карточке — полный ряд с
   разумным пределом ширины. */
.ats-cases .ats-card-case:only-child {
	grid-column: 1 / -1;
	max-width: 760px;
}

/* =====================================================
   Преимущества
   ===================================================== */

/* gap поднят с --space-5 (20px) до --space-6 (24px) для той же цели, что и
   у .ats-guarantees/.ats-documents — плашки крупнее (иконка+заголовок+текст),
   им нужно больше воздуха. Решение заказчика 2026-08-10. */
.ats-advantages {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-6);
}

@media (min-width: 480px) {
	.ats-advantages { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
	.ats-advantages { grid-template-columns: repeat(4, 1fr); }
}

.ats-advantages__item {
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
	padding: var(--space-5);
	background: var(--surface-base);
	border: 1px solid var(--border-default);
	border-radius: var(--r-lg);
}

.ats-advantages__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	border-radius: var(--r-md);
	background: var(--surface-brand-soft);
	color: var(--brand-600);
}

.ats-advantages__title {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1rem;
}

.ats-advantages__desc {
	font-size: .875rem;
	color: var(--text-secondary);
}

/* =====================================================
   Как это работает
   ===================================================== */

.ats-how-it-works {
	display: flex;
	flex-direction: column;
	gap: var(--space-8);
}

@media (min-width: 768px) {
	.ats-how-it-works { flex-direction: row; flex-wrap: wrap; gap: var(--space-6); }
}

.ats-how-it-works__step {
	position: relative;
}

/*
 * flex-basis задаём только в строке. В колонке (мобильная раскладка выше)
 * основная ось вертикальная, и «1 1 200px» превращается в высоту: каждый шаг
 * растягивался до 200px при содержимом вдвое меньше, и на телефоне четыре
 * шага давали около четырёхсот пикселей пустоты. Свойство было объявлено вне
 * медиазапроса, а работало по-разному в двух раскладках — ровно тот случай,
 * когда правило выглядит безобидно и ломает только один экран.
 */
@media (min-width: 768px) {
	.ats-how-it-works__step {
		flex: 1 1 200px;
	}
}

/*
 * Число шага — реальный <span class="ats-how-it-works__num"> из разметки
 * (шаблоны сами выводят порядковый номер), а не CSS-counter в ::before:
 * разметка никогда не проставляла класс __step на <li> (counter-increment не
 * применялся), из-за чего число отрисовывалось как голый текст без кружка.
 * Найдено ревизией через агентов Fable, 2026-08-06, см.
 * docs/11-audit-fable-2026-08-06.md, П1.11.
 */
.ats-how-it-works__num {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	margin-bottom: var(--space-3);
	border-radius: 50%;
	background: var(--brand-600);
	color: var(--white);
	font-family: var(--font-display);
	font-weight: 700;
}

/*
 * Селекторы-соседи (h3/p внутри __step): шаблоны direction/service выводят
 * заголовок и текст шага голыми <h3>/<p> без классов __title/__desc —
 * заголовки рендерились глобальным h3-кеглем (1.25-1.5rem) и ломали
 * иерархию секции (шаг крупнее её заголовка). Та же семья "класс в CSS ≠
 * разметка". Полиш-проход 2026-08-11, круг 2.
 */
.ats-how-it-works__title,
.ats-how-it-works__step h3 {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.0625rem;
	margin-bottom: var(--space-2);
}

.ats-how-it-works__desc,
.ats-how-it-works__step p {
	font-size: .875rem;
	color: var(--text-secondary);
}

/* =====================================================
   Таблица тарифов
   .ats-route-table (таблица параметров маршрута, блок 5 контракта) убрана
   отсюда 2026-08-09 вместе с самим блоком в single-ats_direction.php — она
   была единственным местом, где класс использовался (см.
   docs/02-decisions-log.md). Имя класса не зарезервировано контрактом под
   что-то ещё, поэтому стили не оставлены "про запас", как .ats-hero__price —
   если понадобится, восстановить из истории git.
   ===================================================== */

.ats-tariff-table {
	width: 100%;
	display: block;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	white-space: nowrap;
	border-collapse: collapse;
	font-size: .9375rem;
	border: 1px solid var(--border-default);
	border-radius: var(--r-lg);
}

@media (min-width: 768px) {
	.ats-tariff-table {
		display: table;
		white-space: normal;
	}
}

/* Тёмная шапка + тёплая зебра строк — по Design Specification (было:
   светлый заголовок, ховер вместо зебры). */
.ats-tariff-table th {
	background: var(--ink-900);
	color: var(--text-inverse);
	font-weight: 600;
	font-size: .8125rem;
	text-transform: uppercase;
	letter-spacing: .04em;
	text-align: left;
	padding: var(--space-3) var(--space-4);
}

.ats-tariff-table td {
	padding: var(--space-3) var(--space-4);
	border-bottom: 1px solid var(--border-default);
	color: var(--text-primary);
}

.ats-tariff-table tr:last-child td {
	border-bottom: none;
}

.ats-tariff-table tbody tr:nth-child(even) td {
	background: var(--surface-warm);
}

/* Вместимость — числовая колонка: Mono, выравнивание по правому краю,
   по спеке ("числа — данные, не текст"). */
.ats-tariff-table td:nth-child(2) {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	text-align: right;
}

.ats-tariff-table th:nth-child(2) {
	text-align: right;
}

/*
 * Колонка "Стоимость" раньше показывала фиксированную цену тарифа —
 * тот же риск, что и на карточках (см. .ats-card-cta выше): цены
 * договорные, число в таблице читалось как обещание. Заменено на CTA-ссылку
 * к расчёту, тем же приёмом, что и везде на сайте. Решение заказчика,
 * 2026-08-09.
 */
.ats-tariff-table td:nth-child(3) {
	text-align: right;
}

.ats-tariff-table th:nth-child(3) {
	text-align: right;
}

.ats-tariff-table__cta {
	font-weight: 600;
	color: var(--text-link);
	text-decoration: none;
}

.ats-tariff-table__cta:hover {
	color: var(--text-link-hover);
	text-decoration: underline;
}

/* =====================================================
   Отзывы, кейсы, документы (сетки)
   ===================================================== */

.ats-reviews {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-5);
}

@media (min-width: 768px) {
	.ats-reviews { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
	.ats-reviews { grid-template-columns: repeat(3, 1fr); }
}

.ats-cases {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-5);
}

@media (min-width: 768px) {
	.ats-cases { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
	.ats-cases { grid-template-columns: repeat(3, 1fr); }
}

/* gap поднят с --space-3 (12px) до --space-4 (16px) — та же причина, что у
   .ats-guarantees выше: бордер-плашки нуждаются в более заметном воздухе
   между собой. Решение заказчика 2026-08-10. */
.ats-documents {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-4);
}

@media (min-width: 768px) {
	.ats-documents { grid-template-columns: repeat(2, 1fr); }
}

.ats-documents__item {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	padding: var(--space-4);
	background: var(--surface-base);
	border: 1px solid var(--border-default);
	border-radius: var(--r-md);
	color: var(--text-primary);
	text-decoration: none;
	transition: border-color var(--t-fast) var(--ease-standard), background-color var(--t-fast) var(--ease-standard);
}

.ats-documents__item:hover {
	border-color: var(--border-strong);
	background: var(--surface-base);
}

/*
 * Внутренняя структура карточки документа — появилась вместе с шаблоном
 * архива 2026-08-12 (раньше выводить документы было нечем).
 * align-items: flex-start — иконка выравнивается по первой строке названия,
 * а не по центру блока из трёх строк.
 */
.ats-documents__item {
	align-items: flex-start;
}

.ats-documents__item .ats-icon {
	color: var(--brand-600);
	margin-top: 2px;
}

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

.ats-documents__title {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1rem;
	color: var(--text-primary);
}

.ats-documents__desc {
	font-size: .875rem;
	color: var(--text-secondary);
}

.ats-documents__meta {
	font-size: .8125rem;
	font-weight: 600;
	color: var(--text-link);
}

.ats-documents__item:hover .ats-documents__meta {
	color: var(--text-link-hover);
}

/* Документ без прикреплённого файла (див, а не ссылка) — не притворяется
   кликабельным. */
div.ats-documents__item {
	cursor: default;
	opacity: .7;
}

/* =====================================================
   FAQ (использует паттерн аккордеона из components.css)
   ===================================================== */

.ats-faq {
	max-width: 860px;
	border-top: 1px solid var(--border-default);
}

.ats-faq__item {
	border-bottom: 1px solid var(--border-default);
}

.ats-faq__item-trigger {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-4);
	padding: var(--space-4) 0;
	background: none;
	border: none;
	text-align: left;
	cursor: pointer;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1rem;
	color: var(--text-primary);
}

.ats-faq__item-trigger:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
	border-radius: var(--r-sm);
}

.ats-faq__item-icon {
	flex-shrink: 0;
	transition: transform var(--t-base) var(--ease-standard);
}

.ats-faq__item-trigger[aria-expanded="true"] .ats-faq__item-icon {
	/* Плюс -> крест: поворот 45°, не 180° (было для chevron) — по спеке. */
	transform: rotate(45deg);
}

.ats-faq__item-answer {
	padding-bottom: var(--space-4);
	color: var(--text-secondary);
	font-size: .9375rem;
	line-height: 1.6;
	opacity: 0;
	transform: translateY(-4px);
	transition: opacity var(--t-base) var(--ease-standard), transform var(--t-base) var(--ease-standard);
}

/*
 * Селектор по классу родителя ".ats-faq__item", а не sibling-combinator от
 * триггера: кнопка-триггер вложена ВНУТРЬ <h3 class="ats-faq__item-question">
 * (см. templates/single-ats_direction.php, single-ats_service.php,
 * includes/shortcodes/class-shortcodes.php), поэтому она не является прямым
 * соседом .ats-faq__item-answer — "~"-комбинатор от неё никогда бы не сработал.
 * Класс "is-open" на .ats-faq__item выставляет accordion.js.
 */
.ats-faq__item.is-open .ats-faq__item-answer {
	opacity: 1;
	transform: translateY(0);
}

.ats-faq__item-answer[hidden] {
	display: none;
}

/*
 * Закрытие быстрее открытия (~2/3 длительности) — интерфейс от этого кажется
 * отзывчивее: появление можно рассмотреть, а исчезновение только задерживает.
 * Значение согласовано с CLOSE_DELAY_MS в assets/js/accordion.js — скрипт
 * ждёт конца затухания, прежде чем поставить [hidden].
 */
.ats-faq__item:not(.is-open) .ats-faq__item-answer {
	transition-duration: var(--t-fast);
}

/* =====================================================
   CTA-баннер
   ===================================================== */

.ats-cta-banner {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-5);
	background: var(--surface-inverse);
	color: var(--text-inverse);
	border-radius: var(--r-xl);
	padding: var(--space-8) var(--space-6);
}

@media (min-width: 768px) {
	.ats-cta-banner {
		flex-direction: row;
		/* wrap — внутри баннера живёт полная форма ([ats_lead_form type="full"],
		   см. шаблоны): без переноса она сжималась с заголовком в одну строку. */
		flex-wrap: wrap;
		align-items: center;
		justify-content: space-between;
		padding: var(--space-10) var(--space-8);
	}

	.ats-cta-banner__title,
	.ats-cta-banner > h2 {
		flex: 1 1 320px;
	}

	.ats-cta-banner .ats-form-full {
		flex: 1 1 460px;
	}
}

/*
 * Селектор ".ats-cta-banner > h2" рядом с "__title": шаблоны
 * (single-ats_direction.php и др.) выводят заголовок CTA голым <h2> без
 * класса, а базовая типографика (base.css) красит все h1-h6 в
 * --text-primary — на тёмном баннере заголовок был бы почти невидим.
 * Та же семья багов "класс в CSS ≠ разметка", что и в аудите Fable.
 * Полиш-проход 2026-08-11.
 */
.ats-cta-banner__title,
.ats-cta-banner > h2 {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.5rem;
	color: var(--text-inverse);
	text-wrap: balance;
}

@media (min-width: 768px) {
	.ats-cta-banner__title,
	.ats-cta-banner > h2 { font-size: 1.875rem; }
}

.ats-cta-banner__desc {
	color: var(--text-inverse-muted);
	margin-top: var(--space-2);
}

.ats-cta-banner__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-3);
	flex-shrink: 0;
}

/* =====================================================
   Карта и контакты
   ===================================================== */

.ats-map-contacts {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-6);
}

@media (min-width: 1024px) {
	.ats-map-contacts { grid-template-columns: 1fr 1fr; align-items: stretch; }
}

.ats-map-contacts__map {
	border-radius: var(--r-lg);
	overflow: hidden;
	background: var(--surface-sunken);
	aspect-ratio: 4 / 3;
	/* Safari ≤ 14 не знает aspect-ratio и схлопывает блок в ноль. */
	min-height: 240px;
}

@media (min-width: 1024px) {
	.ats-map-contacts__map { aspect-ratio: auto; height: 100%; min-height: 360px; }
}

.ats-map-contacts__info {
	display: flex;
	flex-direction: column;
	gap: var(--space-4);
	padding: var(--space-6);
	background: var(--surface-base);
	border: 1px solid var(--border-default);
	border-radius: var(--r-lg);
}

/* =====================================================
   Подборка блога
   ===================================================== */

.ats-blog-picks {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-5);
}

@media (min-width: 768px) {
	.ats-blog-picks { grid-template-columns: repeat(3, 1fr); }
}

.ats-card-post__meta {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	font-size: .8125rem;
	color: var(--text-muted);
}

/* =====================================================
   Статистика
   ===================================================== */

.ats-stats {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--space-6);
	text-align: center;
}

@media (min-width: 768px) {
	.ats-stats { grid-template-columns: repeat(4, 1fr); }
}

.ats-stats__value {
	font-family: var(--font-mono);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	font-size: 2rem;
	color: var(--brand-700);
}

.ats-stats__label {
	margin-top: var(--space-1);
	font-size: .8125rem;
	color: var(--text-muted);
}

/* =====================================================
   Условия работы (НДС, оплата, погрузка, простой, страхование)
   Появился 2026-08-12, см. docs/13-audit-rabota-sayta-2026-08-12.md.
   Формат «лейбл — значение», чтобы блок читался как условия договора,
   а не как ещё один список преимуществ.
   ===================================================== */

.ats-terms {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-4);
}

@media (min-width: 768px) {
	.ats-terms { grid-template-columns: repeat(2, 1fr); }
}

.ats-terms__item {
	display: flex;
	flex-direction: column;
	gap: var(--space-1);
	padding: var(--space-5);
	/*
	 * Белый фон с рамкой, а не surface-subtle.
	 *
	 * Карточка на surface-subtle давала контраст к подложке 1,06:1 — блока
	 * визуально не было вовсе. На странице направления зебра красит секцию
	 * тем же surface-subtle, и «Как работаем с юрлицами» — НДС, оплата,
	 * простой — сливалось в ровную плоскость. Вне зебры карточка лежала на
	 * surface-app #EDEEF0 против собственного #F6F5F1: тоже не видно.
	 * Это ровно те условия, которые снабженец ищет глазами перед звонком.
	 */
	background: var(--surface-base);
	border: 1px solid var(--border-default);
	border-radius: var(--r-lg);
}

.ats-terms__label {
	font-size: .8125rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--brand-600);
}

.ats-terms__value {
	color: var(--text-secondary);
}

/* =====================================================
   Гарантии
   ===================================================== */

/*
 * gap поднят с --space-4 (16px) до --space-5 (20px) — на бордер-плашках
 * (сплошная рамка + фон) тесный gap визуально читался как "слипшиеся"
 * карточки, особенно в 2-колоночной раскладке. Решение заказчика 2026-08-10.
 */
.ats-guarantees {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-5);
}

@media (min-width: 480px) {
	.ats-guarantees { grid-template-columns: repeat(2, 1fr); }
}

.ats-guarantees__item {
	display: flex;
	align-items: flex-start;
	gap: var(--space-3);
	padding: var(--space-5);
	border: 1px solid var(--border-default);
	border-radius: var(--r-md);
	background: var(--surface-base);
}

.ats-guarantees__item .ats-icon {
	color: var(--brand-600);
}

/* =====================================================
   Галерея автопарка
   ===================================================== */

.ats-fleet-gallery {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--space-3);
}

@media (min-width: 768px) {
	.ats-fleet-gallery { grid-template-columns: repeat(4, 1fr); }
}

.ats-fleet-gallery img {
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	border-radius: var(--r-md);
}

/* Одиночная графическая заглушка (нет ни одного фото у транспорта) занимала
   1/4 ширины 4-колоночной галереи — крошечный квадрат. Одиночному визуалу —
   широкий баннер на весь ряд. Полиш-проход 2026-08-11, круг 2. */
.ats-fleet-gallery .ats-card-vehicle__visual:only-child {
	grid-column: 1 / -1;
	aspect-ratio: 21 / 9;
}

/*
 * =====================================================
 * Графическая заглушка транспорта (ats_child_vehicle_visual(), functions.php)
 * =====================================================
 * Занимает место фото, когда у записи нет ни veh_photo, ни featured image.
 * Не имитирует фотографию (никакого "почти как фото" полутона) — фирменная
 * графика: маршрутная линия + иконка грузовика, тот же визуальный язык, что
 * у .ats-hero__route/.ats-hero__network. Решение заказчика 2026-08-09:
 * отказ от стоковых фото чужих грузовиков в пользу графики бренда.
 */
.ats-card-vehicle__visual {
	position: relative;
	aspect-ratio: 4 / 3;
	/* Запасная высота для Safari ≤ 14: без неё силуэт машины исчезает. */
	min-height: 200px;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	background: linear-gradient(135deg, var(--surface-brand-soft), var(--brand-100));
}

.ats-fleet-gallery .ats-card-vehicle__visual {
	aspect-ratio: 1 / 1;
	border-radius: var(--r-md);
}

.ats-card-vehicle__visual-route {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	width: 100%;
	height: 100%;
}

.ats-card-vehicle__visual-route path {
	fill: none;
	stroke: var(--brand-300);
	stroke-width: 2;
	stroke-linecap: round;
	stroke-dasharray: 6 10;
}

/* Общее для обеих точек маршрута — чтобы обводка не наследовалась от
   родительского <svg>, который рисует саму линию штрихом. */
.ats-card-vehicle__visual-dot { stroke: none; }

.ats-card-vehicle__visual-dot--a { fill: var(--brand-400); }
.ats-card-vehicle__visual-dot--b { fill: var(--accent-500); }

.ats-card-vehicle__visual-icon {
	position: relative;
	width: 42%;
	height: 42%;
	color: var(--brand-600);
	filter: drop-shadow(0 6px 14px rgba(23, 51, 158, .16));
}

/* Чередование тона по нечётным карточкам сетки — та же "зебра"-логика,
   что и у секций страницы направления, только в акцентных тонах. */
.ats-grid-vehicles a:nth-child(even) .ats-card-vehicle__visual,
.ats-fleet-gallery .ats-card-vehicle__visual:nth-of-type(even) {
	background: linear-gradient(135deg, var(--surface-accent-soft), var(--accent-100));
}

.ats-grid-vehicles a:nth-child(even) .ats-card-vehicle__visual-icon {
	color: var(--accent-600);
	filter: drop-shadow(0 6px 14px rgba(208, 77, 17, .16));
}

.ats-grid-vehicles a:nth-child(even) .ats-card-vehicle__visual-route path {
	stroke: var(--accent-400);
}

/* =====================================================
   География покрытия
   ===================================================== */

.ats-geo-coverage {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-6);
}

@media (min-width: 1024px) {
	.ats-geo-coverage { grid-template-columns: 1fr 1fr; }
}

.ats-geo-coverage__map {
	aspect-ratio: 4 / 3;
	/* То же, что у карты контактов: без запасной высоты блок схлопывается. */
	min-height: 240px;
	border-radius: var(--r-lg);
	background: var(--surface-sunken);
	overflow: hidden;
}

.ats-geo-coverage__list {
	columns: 2;
	gap: var(--space-4);
	font-size: .875rem;
	color: var(--text-secondary);
}

@media (min-width: 768px) {
	.ats-geo-coverage__list { columns: 3; }
}

/* =====================================================
   Быстрый чат (WhatsApp/Telegram)
   position: fixed держит CLS = 0
   ===================================================== */

.ats-chat-quick {
	position: fixed;
	right: var(--space-4);
	bottom: calc(var(--space-4) + 72px);
	z-index: 160;
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
}

@media (min-width: 1024px) {
	.ats-chat-quick { bottom: var(--space-6); }
}

.ats-chat-quick__btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	border-radius: 50%;
	color: var(--white);
	box-shadow: var(--shadow-md);
	transition: transform var(--t-fast) var(--ease-standard);
}

.ats-chat-quick__btn:hover {
	transform: scale(1.06);
}

.ats-chat-quick__btn:active {
	transform: scale(.96);
}

.ats-chat-quick__btn--whatsapp { background: var(--whatsapp); }
.ats-chat-quick__btn--telegram { background: var(--telegram); }
.ats-chat-quick__btn--max { background: var(--max); }

/* =====================================================
   Блок для перевозчиков
   ===================================================== */

.ats-carrier-block {
	display: flex;
	flex-direction: column;
	gap: var(--space-4);
	background: var(--surface-brand-soft);
	border-radius: var(--r-xl);
	padding: var(--space-6);
}

@media (min-width: 768px) {
	.ats-carrier-block {
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
		padding: var(--space-8);
	}
}

/* =====================================================
   Оглавление (Table of Contents)
   ===================================================== */

.ats-toc {
	background: var(--surface-subtle);
	border-radius: var(--r-lg);
	padding: var(--space-5);
	font-size: .875rem;
	/* До desktop-сетки aside рендерится ПОСЛЕ всего контента — оглавление в
	   самом низу страницы бесполезно и выглядит недоработкой. Показываем
	   только там, где оно sticky сбоку. Полиш-проход 2026-08-11, круг 2. */
	display: none;
}

@media (min-width: 1024px) {
	.ats-toc { display: block; }
}

.ats-toc__title {
	font-family: var(--font-display);
	/* Caption-стиль — единая система лейблов с .ats-caption и футером. */
	font-size: .8125rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--text-muted);
	margin-bottom: var(--space-3);
}

.ats-toc a {
	display: block;
	/* space-2 вместо space-1 — тач-цели ссылок были ниже 30px. */
	padding: var(--space-2) 0;
	color: var(--text-secondary);
	text-decoration: none;
}

.ats-toc a:hover {
	color: var(--text-link);
}

@media (min-width: 1024px) {
	.ats-toc {
		position: sticky;
		top: calc(var(--ats-header-h, 64px) + var(--space-6));
	}
}

/* =====================================================
   Блоки, появившиеся при переходе на собственный движок
   (2026-08-17). Раньше эти куски разметки собирались
   плагином или редактором WordPress, поэтому стилей
   для них в дизайн-системе не существовало.
   ===================================================== */

/* Текст и кнопка cookie-баннера: сам баннер — flex-строка, тексту нужно
   право занимать оставшееся место, кнопке — не сжиматься. */
.ats-cookie-banner__text {
	flex: 1 1 260px;
	margin: 0;
	font-size: .875rem;
	line-height: 1.5;
	color: var(--text-inverse-muted);
}

.ats-cookie-banner__text a {
	color: var(--text-link-inverse);
	text-decoration: underline;
}

.ats-cookie-banner__accept {
	flex-shrink: 0;
}

/* Часы работы в подвале выравниваются по первой строке, как и адрес:
   строка «Пн-Пт 09:00-19:00, Сб 10:00-15:00» на узкой колонке переносится,
   и иконка не должна уезжать в вертикальный центр двух строк. */
.ats-footer__hours {
	align-items: flex-start !important;
}

/* Поле формы во всю ширину: сетка форм двухколоночная, а комментарию
   на одну колонку тесно — в него пишут адреса и требования к погрузке. */
.ats-field--wide {
	grid-column: 1 / -1;
}

/* Обещание срока ответа под кнопкой отправки. Тише кнопки, но читаемо:
   это последнее, что человек видит перед отправкой заявки. */
.ats-form__note {
	grid-column: 1 / -1;
	margin: 0;
	font-size: .8125rem;
	color: var(--text-muted);
}

/* Страница транспорта: графика и характеристики рядом на десктопе,
   друг под другом на телефоне. */
.ats-vehicle-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-6);
	align-items: start;
}

@media (min-width: 900px) {
	.ats-vehicle-layout {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		gap: var(--space-8);
	}
}

.ats-vehicle-layout__visual {
	position: relative;
	overflow: hidden;
	border-radius: var(--r-lg);
	background: var(--surface-subtle);
	border: 1px solid var(--border-default);
}

.ats-vehicle-layout__visual img {
	display: block;
	width: 100%;
	height: auto;
}

.ats-vehicle-layout__specs h2 {
	margin-bottom: var(--space-4);
}

/* Текстовая страница (О компании, юридические тексты): узкая колонка,
   потому что сплошной текст на всю ширину экрана не читается. */
.ats-text-page {
	max-width: 68ch;
	margin-inline: auto;
	padding-block: var(--space-10) var(--space-16);
}

.ats-text-page h1 {
	margin-bottom: var(--space-6);
}

/* =====================================================
   Ритм разворотов (ревизия композиции 2026-08-22)

   До ревизии вертикальные отступы задавала каждая секция сама, и расстояние
   между блоками главной гуляло от 48 до 96px без правила. Здесь два класса на
   всё: .ats-section — обычный светлый блок, .ats-spread — блок во всю ширину
   окна, который может нести свой фон. Всё остальное отличие между секциями
   должно быть в раскладке содержимого, а не в отступах.
   ===================================================== */

.ats-section {
	padding-block: var(--section-pad);
}

.ats-spread {
	padding-block: var(--section-pad);
}

@media (min-width: 1024px) {
	.ats-section,
	.ats-spread {
		padding-block: var(--section-pad-lg);
	}
}

/*
 * Заголовок секции без надзаголовка-эйбрау. Раньше над каждым h2 стоял
 * .ats-caption («Услуги», «Транспорт», «Процесс»), и почти везде он повторял
 * сам заголовок другими словами: «Услуги» над «Что мы возим». Восемь одинаковых
 * надписей подряд задают шаблонный ритм и не сообщают ничего — заголовок несёт
 * себя сам.
 */
.ats-section__head {
	max-width: 42rem;
	margin-bottom: var(--space-10);
}

.ats-section__head p {
	margin-top: var(--space-3);
	max-width: 60ch;
	color: var(--text-secondary);
}

/* ---- Тёмный разворот ---- */

/*
 * Тёмных плоскостей на главной ровно две: первый экран и «как мы работаем».
 * Вторая делит длинную светлую полосу пополам. Больше двух — и приём
 * превращается в чересполосицу, где непонятно, что здесь главное.
 *
 * Текст переопределяется явно: базовые h2/h3/p используют --text-primary,
 * непригодный на тёмном. Ссылки — --text-link-inverse (--brand-400): чистый
 * --brand-600 на ink-950 даёт 3.43:1 и проваливает AA для мелкого кегля,
 * см. комментарий в tokens.css.
 */
.ats-spread--dark {
	background: var(--surface-inverse);
	color: var(--text-inverse);
}

.ats-spread--dark h2,
.ats-spread--dark h3 {
	color: var(--text-inverse);
}

.ats-spread--dark p {
	color: var(--text-inverse-muted);
}

.ats-spread--dark a:not(.ats-btn) {
	color: var(--text-link-inverse);
}

/*
 * Строка маршрутного листа — не ссылка внутри текста, а строка таблицы целиком.
 * Правило выше (0,2,1) перебивало color у .ats-routes__link (0,1,0), и все
 * города красились ссылочным синим: восемь синих строк подряд читались как
 * список ссылок, а не как разнарядка. Исключение точечное.
 */
.ats-spread--dark .ats-routes__link,
.ats-spread--dark .ats-routes__link:hover {
	color: var(--text-inverse);
}

.ats-spread__head {
	max-width: 42rem;
	margin-bottom: var(--space-10);
}

.ats-spread__head p {
	margin-top: var(--space-3);
	max-width: 60ch;
	color: var(--text-inverse-muted);
}

.ats-spread__more {
	margin-top: var(--space-10);
}

/* =====================================================
   Маршрутный лист (.ats-routes)

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

.ats-routes {
	border-top: 1px solid rgba(255, 255, 255, .12);
}

.ats-routes__row {
	border-bottom: 1px solid rgba(255, 255, 255, .12);
}

/*
 * Две раскладки. На узком экране — флексбокс с переносом: город занимает всю
 * строку, под ним в одну строку километры, срок и стрелка. Сеткой из двух
 * колонок это раскладывалось как [город | км] и [срок | стрелка], то есть
 * расстояние и срок оказывались на разных строках и переставали читаться как
 * пара. От 768 — настоящая сетка с колонками, где цифры выравниваются по
 * вертикали между строками.
 */
.ats-routes__link {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-1) var(--space-4);
	padding: var(--space-4) var(--space-3);
	text-decoration: none;
	color: var(--text-inverse);
	transition: background-color var(--t-fast) var(--ease-standard);
}

.ats-routes__link:hover {
	background: rgba(255, 255, 255, .04);
	color: var(--text-inverse);
}

.ats-routes__link:focus-visible {
	outline: 2px solid var(--brand-400);
	outline-offset: -2px;
	box-shadow: none;
	border-radius: var(--r-sm);
}

.ats-routes__city {
	flex: 1 1 100%;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.125rem;
	letter-spacing: -.01em;
}

/*
 * Маршрутная нить — тот же фирменный мотив, что в .ats-hero__route, но здесь
 * она ещё и несёт данные: закрашенная часть пропорциональна сроку доставки
 * относительно самого долгого направления в выборке. Долю считает
 * app/Views/pages/home.php и передаёт inline-переменной --ats-route-days.
 * Строки отсортированы по километражу, поэтому отрезки складываются в
 * нарастающую лесенку, и соотношение сроков видно, не сверяя числа построчно.
 *
 * Число рядом остаётся: отрезок его дублирует, а не заменяет. Поэтому сама
 * нить помечена aria-hidden — для скринридера она пустая.
 *
 * На узком экране колонки нет, шкалу тянуть некуда, и нить прячется.
 */
.ats-routes__row {
	/* Значение по умолчанию. Оно же делает переменную объявленной для
	   scripts/verify.py: inline-стиль в разметке скрипт не видит. */
	--ats-route-days: 0;
}

.ats-routes__thread {
	display: none;
	position: relative;
	height: 2px;
	background: rgba(255, 255, 255, .1);
	border-radius: var(--r-full);
	overflow: hidden;
}

.ats-routes__thread::after {
	content: "";
	position: absolute;
	top: 0;
	right: auto;
	bottom: 0;
	left: 0;
	width: calc(var(--ats-route-days) * 100%);
	background: var(--brand-400);
	opacity: .6;
	border-radius: inherit;
	/*
	 * Отрезок вырастает до своей настоящей длины при появлении секции — это
	 * отрисовка диаграммы, а не украшение: движение показывает, что величина
	 * разная. Задержка общая со строкой (--ats-route-delay), поэтому шкала
	 * растёт вместе со своей строкой, а не отдельно от неё.
	 */
	transform-origin: left center;
	transition:
		transform var(--t-reveal) var(--ease-expo),
		opacity var(--t-fast) var(--ease-standard);
	transition-delay: var(--ats-route-delay, 0ms);
}

/* Наведение подсвечивает шкалу активной строки, но не меняет её длину:
   меняющаяся длина читалась бы как другое значение. */
.ats-routes__link:hover .ats-routes__thread::after,
.ats-routes__link:focus-visible .ats-routes__thread::after {
	opacity: 1;
}

.ats-routes__figure {
	font-size: .9375rem;
	color: var(--text-inverse-muted);
	white-space: nowrap;
}

/* Пустая ячейка не должна забирать ширину колонки: у части направлений
   расстояние или срок в базе не заполнены, и место под них пропадало. */
.ats-routes__figure:empty {
	display: none;
}

.ats-routes__arrow {
	margin-left: auto;
	color: var(--brand-400);
	transition: transform var(--t-base) var(--ease-expo);
}

.ats-routes__link:hover .ats-routes__arrow,
.ats-routes__link:focus-visible .ats-routes__arrow {
	transform: translateX(4px);
}

@media (min-width: 768px) {
	.ats-routes__link {
		display: grid;
		grid-template-columns: 15rem minmax(var(--space-8), 1fr) 6.5rem 8rem auto;
		gap: var(--space-5);
		padding-block: var(--space-5);
	}

	.ats-routes__city { flex: none; }

	.ats-routes__arrow { margin-left: 0; }

	.ats-routes__thread { display: block; }

	/* Цифры выравниваются по правому краю колонки: так одинаковые разряды
	   стоят друг под другом и «1 700 км» против «690 км» читается сравнением,
	   а не двумя отдельными надписями. tabular-nums даёт .ats-numeric. */
	.ats-routes__figure { text-align: right; }
}

/* =====================================================
   Плитка услуг (.ats-bento)

   Ширина ячеек чередуется по схеме 4-2 / 2-4 из шести колонок: при любом
   количестве услуг, кратном четырём или шести, ряды заполняются нацело, то
   есть пустых ячеек в сетке не появляется. Чередование даёт ритм, которого не
   было у сетки из одинаковых карточек.
   ===================================================== */

.ats-bento {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-4);
}

.ats-bento__cell {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-3);
	padding: var(--space-6);
	background: var(--surface-base);
	border: 1px solid var(--border-default);
	border-radius: var(--r-lg);
	text-decoration: none;
	color: var(--text-primary);
	transition:
		transform var(--t-base) var(--ease-standard),
		border-color var(--t-base) var(--ease-standard),
		box-shadow var(--t-base) var(--ease-standard);
}

.ats-bento__cell:hover {
	transform: translateY(-2px);
	border-color: var(--brand-200);
	box-shadow: var(--shadow-sm);
	color: var(--text-primary);
}

.ats-bento__icon {
	color: var(--brand-600);
}

.ats-bento__title {
	margin: 0;
	font-size: 1.25rem;
}

.ats-bento__desc {
	margin: 0;
	color: var(--text-secondary);
	max-width: 52ch;
}

/* .ats-card-cta прижимается к низу ячейки, чтобы у соседних ячеек разной
   высоты ссылки стояли на одной линии. */
.ats-bento__cell .ats-card-cta {
	margin-top: auto;
	padding-top: var(--space-2);
}

@media (min-width: 640px) {
	.ats-bento { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
	.ats-bento {
		grid-template-columns: repeat(6, 1fr);
		gap: var(--space-5);
	}

	.ats-bento__cell { grid-column: span 3; }
	.ats-bento__cell:nth-child(4n + 1) { grid-column: span 4; }
	.ats-bento__cell:nth-child(4n + 2) { grid-column: span 2; }
	.ats-bento__cell:nth-child(4n + 3) { grid-column: span 2; }
	.ats-bento__cell:nth-child(4n + 4) { grid-column: span 4; }

	/*
	 * Широкие ячейки получают другую подложку. Плитка целиком из белых
	 * прямоугольников на светлом холсте — это та же сетка карточек, только с
	 * разной шириной; тон отличает опорные ячейки от остальных. Оттенок берётся
	 * из брендовой шкалы, новых цветов не вводится.
	 */
	.ats-bento__cell:nth-child(4n + 1),
	.ats-bento__cell:nth-child(4n + 4) {
		background: var(--surface-brand-soft);
		border-color: var(--brand-100);
	}

	.ats-bento__cell:nth-child(4n + 1) .ats-bento__title,
	.ats-bento__cell:nth-child(4n + 4) .ats-bento__title {
		font-size: 1.5rem;
	}
}

/* =====================================================
   Лента транспорта (.ats-rail)

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

.ats-rail {
	--rail-gutter: var(--space-4);
	display: flex;
	gap: var(--space-4);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	/*
	 * Отступы повторяют .ats-container: первая карточка встаёт ровно под
	 * заголовком секции, а последняя не прилипает к правому краю окна.
	 * scroll-padding — чтобы привязка останавливала карточку на той же линии,
	 * а не вплотную к краю вьюпорта.
	 */
	padding-inline: max(var(--rail-gutter), calc((100% - var(--container-max)) / 2 + var(--rail-gutter)));
	scroll-padding-inline: max(var(--rail-gutter), calc((100% - var(--container-max)) / 2 + var(--rail-gutter)));
	padding-block: var(--space-2) var(--space-4);
}

@media (min-width: 480px) { .ats-rail { --rail-gutter: var(--space-5); } }
@media (min-width: 768px) { .ats-rail { --rail-gutter: var(--space-6); } }
@media (min-width: 1024px) { .ats-rail { --rail-gutter: var(--space-8); gap: var(--space-5); } }
@media (min-width: 1280px) { .ats-rail { --rail-gutter: var(--space-10); } }

.ats-rail__item {
	flex: 0 0 min(80vw, 21rem);
	scroll-snap-align: start;
}

.ats-rail__card {
	display: flex;
	flex-direction: column;
	height: 100%;
	overflow: hidden;
	background: var(--surface-base);
	border: 1px solid var(--border-default);
	border-radius: var(--r-lg);
	text-decoration: none;
	color: var(--text-primary);
	transition:
		transform var(--t-base) var(--ease-standard),
		border-color var(--t-base) var(--ease-standard),
		box-shadow var(--t-base) var(--ease-standard);
}

.ats-rail__card:hover {
	transform: translateY(-2px);
	border-color: var(--brand-200);
	box-shadow: var(--shadow-sm);
	color: var(--text-primary);
}

.ats-rail__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-2);
	padding: var(--space-5);
}

.ats-rail__title {
	margin: 0;
	font-size: 1.125rem;
}

.ats-rail__specs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-1) var(--space-3);
	font-size: .875rem;
	color: var(--text-muted);
}

.ats-rail__specs li:not(:last-child)::after {
	content: "·";
	margin-left: var(--space-3);
	color: var(--border-strong);
}

.ats-rail__card .ats-card-cta {
	margin-top: var(--space-2);
}

/* =====================================================
   Гарантии и условия в один разворот (.ats-conditions)
   ===================================================== */

.ats-conditions {
	display: grid;
	gap: var(--space-10);
}

@media (min-width: 900px) {
	.ats-conditions {
		grid-template-columns: 1fr 1fr;
		gap: var(--space-16);
	}
}

/*
 * Подзаголовки колонок набраны как подписи, а не как обычный h3: они разделяют
 * две половины одного блока, и полноразмерный заголовок спорил бы с h2 секции
 * над ними.
 */
.ats-conditions__subtitle {
	margin-bottom: var(--space-5);
	padding-bottom: var(--space-3);
	border-bottom: 1px solid var(--border-default);
	font-family: var(--font-body);
	font-size: .8125rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--text-muted);
}

/* =====================================================
   «Как мы работаем» на тёмном развороте
   ===================================================== */

/*
 * Селекторы приходится усиливать: .ats-how-it-works__step p (0,2,1) перебивает
 * общее правило .ats-spread--dark p (0,1,1), и текст шага остался бы тёмным на
 * тёмном. Тот же случай, что описан выше у самого блока — «класс в CSS ≠
 * разметка», только здесь наоборот, специфичность.
 */
.ats-spread--dark .ats-how-it-works__step p,
.ats-spread--dark .ats-how-it-works__desc {
	color: var(--text-inverse-muted);
}

/*
 * Нить между шагами. Нумерация в этом блоке несёт реальную последовательность
 * (заявка → договор → погрузка → документы), и линия показывает, что шаги
 * связаны, а не просто стоят рядом. На узком экране шаги идут колонкой, и
 * горизонтальная линия там ни к чему.
 */
@media (min-width: 768px) {
	.ats-spread--dark .ats-how-it-works__step::after {
		content: "";
		position: absolute;
		top: 18px;
		left: calc(36px + var(--space-3));
		right: calc(var(--space-6) * -1);
		height: 1px;
		background: rgba(255, 255, 255, .14);
	}

	.ats-spread--dark .ats-how-it-works__step:last-child::after {
		display: none;
	}
}

.ats-spread--dark .ats-how-it-works__num {
	/* Кружок стоит на нити, и без подложки цвета фона линия просвечивала бы
	   сквозь промежуток между ним и следующим шагом. */
	position: relative;
	z-index: 1;
	box-shadow: 0 0 0 4px var(--surface-inverse);
}

/* =====================================================
   Отзывы: цитата крупнее
   ===================================================== */

/*
 * Было .9375rem цветом --text-secondary — то есть высказывание клиента
 * набиралось мельче и бледнее окружающего текста, хотя это единственное на
 * странице, что говорит не компания о себе. Кегль поднят, цвет — основной.
 */
.ats-card-review__quote {
	font-size: 1.0625rem;
	line-height: 1.6;
	color: var(--text-primary);
	max-width: 60ch;
}

/* =====================================================
   Появление маршрутного листа

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

   Задержки заданы поштучно, а не через nth-child(n) с переменной: восемь
   направлений на главной — фиксированное число (Direction::published(8)),
   а calc с индексом в CSS без --i из разметки не считается.
   ===================================================== */

html.ats-js .ats-reveal .ats-routes__row {
	opacity: 0;
	transform: translateY(10px);
	transition:
		opacity var(--t-base) var(--ease-expo),
		transform var(--t-base) var(--ease-expo);
	transition-delay: var(--ats-route-delay, 0ms);
}

/* Шкала срока свёрнута, пока строка не появилась. */
html.ats-js .ats-reveal .ats-routes__thread::after {
	transform: scaleX(0);
}

html.ats-js .ats-reveal.is-visible .ats-routes__row {
	opacity: 1;
	transform: none;
}

html.ats-js .ats-reveal.is-visible .ats-routes__thread::after {
	transform: scaleX(1);
}

/* Одна задержка на строку: её наследует и шкала внутри, поэтому строка и её
   отрезок появляются вместе, а не двумя отдельными волнами. */
html.ats-js .ats-reveal.is-visible .ats-routes__row:nth-child(1) { --ats-route-delay: 60ms; }
html.ats-js .ats-reveal.is-visible .ats-routes__row:nth-child(2) { --ats-route-delay: 105ms; }
html.ats-js .ats-reveal.is-visible .ats-routes__row:nth-child(3) { --ats-route-delay: 150ms; }
html.ats-js .ats-reveal.is-visible .ats-routes__row:nth-child(4) { --ats-route-delay: 195ms; }
html.ats-js .ats-reveal.is-visible .ats-routes__row:nth-child(5) { --ats-route-delay: 240ms; }
html.ats-js .ats-reveal.is-visible .ats-routes__row:nth-child(6) { --ats-route-delay: 285ms; }
html.ats-js .ats-reveal.is-visible .ats-routes__row:nth-child(7) { --ats-route-delay: 330ms; }
html.ats-js .ats-reveal.is-visible .ats-routes__row:nth-child(8) { --ats-route-delay: 375ms; }

/*
 * Глобальное правило prefers-reduced-motion в base.css глушит длительность, но
 * не задержку: без этого блока строки при «уменьшить движение» появлялись бы
 * мгновенно, зато по очереди, растянуто на 375мс — то есть движение убрано, а
 * ожидание осталось.
 */
@media (prefers-reduced-motion: reduce) {
	html.ats-js .ats-reveal.is-visible .ats-routes__row {
		--ats-route-delay: 0ms;
		transition-delay: 0ms !important;
	}

	/* Шкала показывается сразу нужной длины, без отрисовки. */
	html.ats-js .ats-reveal .ats-routes__thread::after {
		transform: scaleX(1);
	}
}

/* =====================================================
   Хребет маршрута (.ats-spine)

   Сквозная линия рейса вдоль всей страницы: прочерчивается по мере прокрутки,
   по ней едет груз, узлы зажигаются при прохождении. Тот же мотив маршрутной
   нити, что в первом экране и в маршрутном листе, растянутый на весь документ.

   Построено на scroll-driven animations: прогресс берётся из
   animation-timeline: scroll(root block), то есть считает браузер в потоке
   композитора. Обработчика scroll в JS нет и быть не должно — он выполнялся бы
   на каждом кадре прокрутки и ронял бы отзывчивость на длинной странице.

   Блок целиком под @supports: в браузерах без поддержки он не показывается.
   Это осознанно — линия декоративная (aria-hidden), и вместо неё не нужен
   запасной вариант, нужна её пустота. Полифилл ради украшения — лишние
   килобайты на всех устройствах.
   ===================================================== */

.ats-spine {
	display: none;
}

@supports (animation-timeline: scroll()) {
	@media (min-width: 1440px) {
		.ats-spine {
			display: block;
			position: fixed;
			top: 50%;
			/*
			 * Линия встаёт по центру левого поля — промежутка между краем окна
			 * и контейнером. Ниже 1440px этого промежутка нет, поэтому и весь
			 * блок появляется только с этой ширины.
			 */
			left: calc((100vw - var(--container-max)) / 4);
			width: 60px;
			height: min(760px, 82vh);
			transform: translateY(-50%);
			/*
			 * Поверх содержимого, но ниже шапки (100), нижней панели и
			 * кнопок чата: линия проходит и по тёмным разворотам во всю
			 * ширину, иначе она пропадала бы на них и выглядела оборванной.
			 */
			z-index: 50;
			pointer-events: none;
		}

		.ats-spine svg {
			width: 100%;
			height: 100%;
		}

		/* Непройденная часть маршрута. neutral-400 при 38% читается и на
		   светлом холсте, и на тёмных разворотах — отдельный цвет под каждую
		   подложку не нужен, а новых значений в палитру не добавляется. */
		.ats-spine__track {
			fill: none;
			stroke: var(--neutral-400);
			stroke-opacity: .2;
			stroke-width: 1.5;
			stroke-linecap: round;
		}

		.ats-spine__line {
			fill: none;
			stroke: var(--brand-500);
			stroke-width: 2;
			stroke-linecap: round;
			stroke-dasharray: 100;
			stroke-dashoffset: 100;
			animation: ats-spine-draw linear both;
			animation-timeline: scroll(root block);
		}

		@keyframes ats-spine-draw {
			to { stroke-dashoffset: 0; }
		}

		/*
		 * Узлы зажигаются по очереди: у каждого свой отрезок прокрутки через
		 * animation-range. Это не украшение — узел меняет цвет ровно тогда,
		 * когда груз до него доехал, то есть показывает, какая часть пути
		 * пройдена.
		 */
		.ats-spine__node {
			fill: var(--neutral-400);
			fill-opacity: .5;
			animation: ats-spine-node linear both;
			animation-timeline: scroll(root block);
		}

		.ats-spine__node--1 { animation-range: 0% 4%; }
		.ats-spine__node--2 { animation-range: 33% 37%; }
		.ats-spine__node--3 { animation-range: 66% 70%; }
		.ats-spine__node--4 { animation-range: 94% 98%; }

		/*
		 * --accent-600, а не --accent-500: хребет проходит и по светлому холсту,
		 * где яркий #EF6A2C даёт всего 2.67:1 при норме 3:1 для значимой
		 * графики. Затемнённая ступень проходит на обеих подложках сразу.
		 * Поймано scripts/contrast.py при ревизии композиции 2026-08-22.
		 */
		@keyframes ats-spine-node {
			to {
				fill: var(--accent-600);
				fill-opacity: 1;
			}
		}

		/* Груз. offset-path продублирован из "d" в partials/route-spine.php. */
		.ats-spine__cargo {
			fill: var(--accent-600);
			offset-path: path('M 30 20 C 10 140, 10 200, 30 300 C 50 400, 50 460, 30 560 C 10 660, 10 700, 30 780');
			animation: ats-spine-ride linear both;
			animation-timeline: scroll(root block);
		}

		@keyframes ats-spine-ride {
			from { offset-distance: 0%; }
			to { offset-distance: 100%; }
		}

		/*
		 * При «уменьшить движение» линия остаётся, но перестаёт быть
		 * анимацией: показывается пройденной целиком, груз стоит в конце.
		 * Глобальное правило в base.css глушит длительность, но у
		 * scroll-timeline длительности нет — прогресс задаёт прокрутка,
		 * поэтому отключать нужно саму привязку к таймлайну.
		 */
		@media (prefers-reduced-motion: reduce) {
			.ats-spine__line,
			.ats-spine__node,
			.ats-spine__cargo {
				animation: none;
			}

			.ats-spine__line { stroke-dashoffset: 0; }
			.ats-spine__node { fill: var(--accent-600); fill-opacity: 1; }
			.ats-spine__cargo { offset-distance: 100%; }
		}
	}
}

/*
 * min-width: 0 снимает у колонки грид-минимум по содержимому: без него длинное
 * условие из настроек (например, слитная строка реквизитов) распирало бы свою
 * половину и ломало пропорцию 1fr 1fr.
 */
.ats-conditions__col {
	min-width: 0;
}

/* =====================================================
   Полоса доверия внутри первого экрана
   ===================================================== */

.ats-hero .ats-trust-bar {
	justify-content: flex-start;
	gap: var(--space-4) var(--space-8);
	margin-top: var(--space-12);
	padding-block: var(--space-6) 0;
	/* Только верхняя граница: нижняя отрезала бы полосу от тёмной плоскости,
	   которая продолжается за первым экраном. */
	border-block: none;
	border-top: 1px solid rgba(255, 255, 255, .14);
}

.ats-hero .ats-trust-bar__item {
	color: var(--text-inverse-muted);
}

.ats-hero .ats-trust-bar__item .ats-icon {
	color: var(--brand-300);
}

/* =====================================================
   Списки внутри разворота условий

   .ats-guarantees и .ats-terms на широком экране раскладываются в две колонки
   каждый — внутри .ats-conditions, который сам делит место надвое, получалось
   четыре узких колонки мелких карточек. Здесь оба списка идут в одну колонку:
   ширины половины разворота им достаточно.
   ===================================================== */

.ats-conditions .ats-guarantees,
.ats-conditions .ats-terms {
	grid-template-columns: 1fr;
}

/* =====================================================
   Исправления, найденные осмотром в браузере 2026-08-22
   ===================================================== */

/*
 * CTA-баннер: заголовок и текст были тёмными на тёмном.
 *
 * Правило выше написано как ".ats-cta-banner > h2" — прямой потомок. Но во всех
 * шаблонах внутри баннера сначала идёт <div class="ats-container">, и заголовок
 * лежит уже в нём: комбинатор не срабатывал никогда, h2 получал --text-primary
 * из base.css и почти сливался с фоном ink-950. То же с абзацем: класс
 * .ats-cta-banner__desc в разметке не проставлен, выводится голый <p>.
 * Ровно та же семья, что описана в комментарии к самому правилу («класс в CSS
 * ≠ разметка»), только здесь промахнулся комбинатор, а не имя класса.
 */
.ats-cta-banner h1,
.ats-cta-banner h2,
.ats-cta-banner .ats-cta-banner__title {
	color: var(--text-inverse);
}

.ats-cta-banner p {
	color: var(--text-inverse-muted);
}

/*
 * Внутри баннера лежит белая карточка формы, и правило выше красило её абзацы
 * в почти белый: пропадали «* — обязательные поля, остальные можно не
 * заполнять» и «Перезвоним в течение 15 минут». От пометки обязательных полей
 * оставалась красная звёздочка без объяснения, а обещание перезвонить —
 * прямой конверсионный текст — не видел никто.
 *
 * h1 в селекторе выше по той же причине: «Спасибо» и 404 выводят заголовок
 * первого уровня внутри баннера, и человек, только что отправивший заявку,
 * попадал на тёмную карточку с призрачным заголовком.
 */
.ats-cta-banner .ats-form-full p,
.ats-cta-banner .ats-form-quick p {
	color: var(--text-muted);
}

/*
 * Город в маршрутном листе оставался ссылочно-синим: правило
 * .ats-spread--dark a:not(.ats-btn) имеет специфичность (0,2,1) за счёт
 * аргумента :not и перебивало .ats-spread--dark .ats-routes__link (0,2,0).
 * Добавлен тег в селектор — специфичности сравнялись, побеждает то, что ниже.
 */
.ats-spread--dark a.ats-routes__link,
.ats-spread--dark a.ats-routes__link:hover {
	color: var(--text-inverse);
}

/*
 * Гарантии и условия стоят рядом в одном развороте, и до этой правки левая
 * колонка была белыми карточками с рамкой, а правая — заливкой без рамки.
 * Две половины одного блока не должны выглядеть как два разных блока.
 */
.ats-conditions .ats-terms__item {
	background: var(--surface-base);
	border: 1px solid var(--border-default);
	border-radius: var(--r-md);
}

/*
 * Две соседние светлые секции складывали свои отступы: 96px снизу у первой
 * плюс 96px сверху у второй давали 192px пустоты, и «Условия» с «Отзывами»
 * читались как разные страницы. Верхний отступ у второй снимается — расстояние
 * между секциями остаётся одним значением, а не суммой двух.
 */
.ats-section + .ats-section {
	padding-top: 0;
}

/*
 * Высота первого экрана задаётся только с планшета. На телефоне 66vh при
 * центрировании оставляли пустое тёмное поле под полосой доверия: содержимое
 * короче отведённой высоты, и низ экрана пустовал. Здесь высоту определяет
 * само содержимое.
 */
@media (max-width: 767.98px) {
	.ats-hero--home {
		min-height: 0;
		padding-block: var(--space-10) var(--space-10);
	}
}

/* =====================================================
   Фактура и состояние «есть видео» на первом экране
   ===================================================== */

/*
 * Фоновая фактура — контурная карта, сгенерирована Krea, см.
 * public_html/assets/media/README.md. Лежит в самом низу стопки слоёв
 * (background элемента, ниже видео, подложки, сети и текста) и нужна затем,
 * чтобы тёмная плоскость не была плоской заливкой: у неё появляется материал.
 * Картинка сама по себе почти чёрная, поэтому дополнительного гашения не
 * требует. Левая треть у неё пустая — ровно там, где идёт текст.
 */
.ats-hero--home {
	background-image: url("../media/hero-texture.jpg");
	background-repeat: no-repeat;
	background-position: right center;
	background-size: cover;
}

/* На телефоне фактура не читается (её видно только на широком кадре), а
   лишние 60 КБ на первом экране мобильному каналу заметны. */
@media (max-width: 767.98px) {
	.ats-hero--home { background-image: none; }
}

/*
 * --- Состояние «есть видео» ---
 * Класс ставит app/Views/pages/home.php, когда файл лежит в assets/media.
 */

/* Сеть маршрутов рассчитана на пустой тёмный фон: тонкие светящиеся линии
   поверх движущегося кадра читаются как царапины на плёнке, а не как карта. */
.ats-hero--media .ats-hero__network {
	display: none;
}

/*
 * Подложка под текстом поверх видео. Это то самое «чтобы под текстом ничего не
 * мешалось»: горизонтальный слой держит левую колонку с заголовком и кнопками,
 * вертикальный гасит верх под шапкой и низ под полосой доверия.
 *
 * Плотность подобрана замером по реальным кадрам, а не назначена на глаз.
 * Первая версия исходила из расчёта на абстрактно яркий дневной кадр (светлота
 * около 0.5) и давала суммарную альфу 0.92. Кадр оказался другим: левая часть —
 * тёмно-зелёное поле, средний цвет rgb(42,92,10), и без всякой подложки белый
 * текст получал 7.97:1 по среднему и 5.68:1 по самым светлым 5% пикселей, то
 * есть норму 4.5:1 брал с запасом. Прежняя плотность давила кадр до почти
 * чёрного (18.7:1) — ради контраста, которого и так хватало, терялась вся
 * зелень, ради которой видео и снималось.
 *
 * Здесь суммарная альфа над текстом около 0.43: это примерно 12.6:1, запас
 * втрое от нормы, и кадр остаётся кадром. Подложка тут не столько про контраст,
 * сколько про то, чтобы текст лежал на плоскости, а не плавал поверх травы, и
 * про страховку от кадра посветлее.
 *
 * 2026-09-17, второй замер — кадр заменён на стоковый (Pexels 7183495), и
 * «посветлее» наступило: слева не тёмно-зелёное поле, а туманные пашни,
 * средний цвет левой трети rgb(142,139,128). На прежней плотности (.74/.62/.26)
 * подзаголовок (белый 72%) на самых светлых 5% пикселей под ним давал 4.64:1 —
 * норму 4.5 брал на волоске, а самые светлые точки уже 3.1. Первые три стопа
 * горизонтального слоя подняты на .10/.12/.04: по рендеру главной в 1440px
 * H1 держит 13.2:1 по среднему и 8.9:1 по светлым 5%, подзаголовок — 8.2:1 и
 * 5.9:1. Правая половина (поля, трасса) не тронута — ради неё кадр и выбран.
 *
 * Как мерить: срендерить главную headless Chrome с .ats-hero__content скрытым,
 * вырезать области под H1 и подзаголовком, посчитать WCAG-контраст текста
 * к среднему и к самым светлым 5% пикселей. При замене видео — перемерить.
 */
.ats-hero--media::before {
	background:
		linear-gradient(
			100deg,
			rgba(11, 13, 18, .84) 0%,
			rgba(11, 13, 18, .74) 34%,
			rgba(11, 13, 18, .3) 68%,
			rgba(11, 13, 18, .12) 100%
		),
		linear-gradient(
			to bottom,
			rgba(11, 13, 18, .34) 0%,
			rgba(11, 13, 18, .06) 38%,
			rgba(11, 13, 18, .12) 64%,
			rgba(11, 13, 18, .3) 84%,
			/*
			 * Последние проценты уводят кадр в цвет фона. Без этого низ первого
			 * экрана обрывался ровной горизонтальной линией: зелёное поле
			 * упиралось в почти чёрный маршрутный лист, и стык читался как
			 * граница двух картинок, а не как продолжение страницы.
			 */
			rgba(11, 13, 18, .92) 100%
		);
}


/* Видео яркое и само по себе несёт кадр — приглушать его, как абстрактную
   графику, больше не нужно: за контраст отвечает подложка выше. */
.ats-hero--media .ats-hero__video {
	opacity: 1;
}

/* =====================================================
   Разворот ЭТрН (.ats-etrn), 2026-09-14

   Третий тон плоскости на главной: не тёмный (их ровно два — первый экран и
   «как мы работаем») и не холст, а brand-soft, тот же, что у опорных ячеек
   плитки услуг. Стоит сразу после тёмного разворота: тёмный → голубой →
   холст, и середина страницы получает ступень, а не обрыв с чёрного на серый.

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

.ats-spread--soft {
	background: var(--surface-brand-soft);
}

.ats-etrn {
	display: grid;
	gap: var(--space-10);
	align-items: center;
}

@media (min-width: 960px) {
	.ats-etrn {
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		gap: var(--space-16);
	}
}

/*
 * Аббревиатура над заголовком набрана моноширинным: на сайте так выводятся
 * цифры и коды (ИНН, километраж), и «ЭТрН» читается как код документа, а не
 * как ещё один надзаголовок-эйбрау, от которых страница избавлена.
 */
/* Текстовая колонка не шире 60ch: на широком экране заголовок и абзац иначе
   растягивались бы на всю половину, и строки лида становились длиннее, чем
   удобно читать. */
.ats-etrn__text {
	max-width: 60ch;
}

.ats-etrn__label {
	margin: 0 0 var(--space-4);
	font-size: .875rem;
	font-weight: 600;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--brand-700);
}

.ats-etrn__title {
	margin: 0;
	max-width: 22ch;
}

.ats-etrn__lead {
	margin: var(--space-5) 0 0;
	max-width: 56ch;
	font-size: 1.0625rem;
	line-height: 1.6;
	color: var(--text-secondary);
}

.ats-etrn__facts {
	list-style: none;
	margin: var(--space-8) 0 0;
	padding: 0;
	display: grid;
	gap: var(--space-4);
}

.ats-etrn__fact {
	display: flex;
	align-items: flex-start;
	gap: var(--space-3);
}

.ats-etrn__fact .ats-icon {
	margin-top: 2px;
	color: var(--brand-600);
}

.ats-etrn__fact-body {
	display: flex;
	flex-direction: column;
	gap: var(--space-1);
}

.ats-etrn__fact-title {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.0625rem;
	line-height: 1.3;
	color: var(--text-primary);
}

.ats-etrn__fact-text {
	max-width: 52ch;
	line-height: 1.5;
	color: var(--text-secondary);
}

/* Оговорка про бумажную накладную — мельче и приглушённее фактов: это не
   четвёртое преимущество, а ответ на возражение «а мы не подключены». */
.ats-etrn__note {
	margin: var(--space-6) 0 0;
	max-width: 52ch;
	font-size: .9375rem;
	line-height: 1.5;
	color: var(--text-muted);
}

/* ---- Бланк накладной ---- */

.ats-etrn__visual {
	display: flex;
	justify-content: center;
}

.ats-etrn__doc {
	width: 100%;
	max-width: 30rem;
	padding: var(--space-6);
	background: var(--surface-base);
	border: 1px solid var(--brand-100);
	border-radius: var(--r-lg);
	box-shadow: var(--shadow-lg);
	/* Лёгкий наклон — чтобы бланк читался как предмет, лежащий на столе, а
	   не как ещё одна карточка сетки. Один градус: больше — и текст в нём
	   начинает выглядеть криво, а не «положено». */
	transform: rotate(-1deg);
}

@media (min-width: 960px) {
	.ats-etrn__doc {
		padding: var(--space-8);
	}
}

.ats-etrn__doc-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-2) var(--space-4);
	padding-bottom: var(--space-4);
	border-bottom: 2px solid var(--ink-900);
}

.ats-etrn__doc-kind {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: .9375rem;
	letter-spacing: .02em;
	text-transform: uppercase;
	color: var(--text-primary);
}

.ats-etrn__doc-badge {
	display: inline-flex;
	align-items: center;
	gap: var(--space-1);
	padding: 2px var(--space-2);
	border-radius: var(--r-sm);
	background: var(--surface-brand-soft);
	font-size: .75rem;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--brand-700);
}

.ats-etrn__doc-rows {
	margin: var(--space-5) 0 0;
	display: grid;
	gap: var(--space-3);
}

.ats-etrn__doc-row {
	display: grid;
	grid-template-columns: 8.5rem minmax(0, 1fr);
	align-items: center;
	gap: var(--space-3);
	font-size: .875rem;
}

@media (max-width: 479px) {
	.ats-etrn__doc-row {
		grid-template-columns: 1fr;
		gap: var(--space-1);
	}
}

.ats-etrn__doc-row dt {
	color: var(--text-muted);
}

.ats-etrn__doc-row dd {
	margin: 0;
	display: flex;
	align-items: center;
	gap: var(--space-2);
	min-height: 1.5rem;
	font-weight: 600;
	/* Город отправления не переносится: «Санкт-» на одной строке и
	   «Петербург →» на другой читалось как сломанная таблица. Пустая линия
	   рядом сжимается первой. */
	white-space: nowrap;
	color: var(--text-primary);
}

.ats-etrn__arrow {
	color: var(--text-muted);
}

/* Пустая строка бланка: линия, на которой в бумажной накладной пишут
   от руки. Ширина — доля от ячейки, чтобы линии не были одинаковыми. */
.ats-etrn__blank {
	display: block;
	height: 2px;
	width: 70%;
	border-radius: var(--r-full);
	background: var(--neutral-200);
}

.ats-etrn__blank--short {
	flex: 1 1 2rem;
	width: auto;
	min-width: 2rem;
}
.ats-etrn__blank--long { width: 90%; }

.ats-etrn__signs {
	list-style: none;
	margin: var(--space-6) 0 0;
	padding: var(--space-4) 0 0;
	border-top: 1px dashed var(--border-strong);
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-3);
}

.ats-etrn__sign {
	display: flex;
	flex-direction: column;
	gap: var(--space-2);
	min-width: 0;
}

.ats-etrn__sign-who {
	font-size: .75rem;
	color: var(--text-muted);
}

.ats-etrn__sign-state {
	display: inline-flex;
	align-items: center;
	gap: var(--space-1);
	align-self: flex-start;
	padding: 2px var(--space-2);
	border-radius: var(--r-sm);
	background: var(--success-bg);
	font-size: .75rem;
	font-weight: 600;
	white-space: nowrap;
	color: var(--success-text);
}

@media (max-width: 479px) {
	.ats-etrn__signs {
		grid-template-columns: 1fr;
	}

	.ats-etrn__sign {
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
	}
}

/* =====================================================
   Поиск маршрута на /napravleniya (.ats-route-finder), 2026-09-14

   Одна строка: «Откуда» → «Куда» → кнопка. Это не форма заявки, а фильтр
   над списком, поэтому без белой карточки с тенью, как у форм: полоса на
   brand-soft с рамкой, той же тональности, что опорные ячейки плитки услуг.
   На телефоне поля идут столбиком, стрелка между ними разворачивается вниз.
   ===================================================== */

.ats-route-finder {
	margin-block: var(--space-10) var(--space-12);
	padding: var(--space-6);
	background: var(--surface-brand-soft);
	border: 1px solid var(--brand-100);
	border-radius: var(--r-xl);
}

@media (min-width: 1024px) {
	.ats-route-finder {
		margin-block: var(--space-12) var(--space-16);
		padding: var(--space-8);
	}
}

/* Сама форма — без собственной геометрии: отступы и фон несёт секция, чтобы
   форма и сообщение под ней лежали в одном прямоугольнике. */
.ats-route-finder__form {
	display: block;
}

.ats-route-finder__head {
	margin-bottom: var(--space-5);
}

.ats-route-finder__title {
	margin: 0;
	font-size: clamp(1.25rem, 1.1rem + .7vw, 1.625rem);
}

.ats-route-finder__note {
	margin: var(--space-2) 0 0;
	max-width: 60ch;
	color: var(--text-secondary);
}

.ats-route-finder__fields {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-3);
	align-items: end;
}

.ats-route-finder__field {
	margin-bottom: 0;
}

/* Подпись поля — как в остальных формах, но фон здесь голубой, и подпись
   набрана вторичным цветом (4.5:1 на brand-soft проверено contrast.py). */
.ats-route-finder__field > span {
	color: var(--text-secondary);
}

.ats-route-finder__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--brand-600);
	/* На телефоне стрелка стоит между полями и смотрит вниз. */
	transform: rotate(90deg);
}

.ats-route-finder__submit {
	width: 100%;
	min-height: 48px;
}

.ats-route-finder__result {
	margin: var(--space-4) 0 0;
	color: var(--text-secondary);
}

.ats-route-finder__result:empty {
	display: none;
}

.ats-route-finder__result strong {
	color: var(--text-primary);
}

@media (min-width: 768px) {
	.ats-route-finder__fields {
		grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto;
		gap: var(--space-3);
	}

	.ats-route-finder__arrow {
		/* Стрелка на высоте поля, а не подписи: подпись 1.4em + зазор сверху. */
		height: 48px;
		transform: none;
	}

	.ats-route-finder__submit {
		width: auto;
	}
}

@media (min-width: 1024px) {
	.ats-route-finder__fields {
		gap: var(--space-4);
	}
}
