/* ===== Design tokens ===== */
:root {
  --color-accent: #e75748;
  --color-accent-dark: #d1453a;
  --color-navy: #2c405b;
  --color-navy-light: #7591b7;
  /* Осветлённый навий — для отбивок, которые обозначают границу блока, а не
     привлекают внимание (верхние полоски боковых карточек на странице
     заказа). Красный там был занят кнопкой и ошибками, тёмно-синий оказался
     тяжеловат, --color-navy-light всё ещё заметен. */
  --color-navy-pale: #A5B7D0;
  --color-bg-soft: #e9ebf3;
  --color-white: #ffffff;
  --color-text: #3c4a5e;
  --color-text-muted: #7a8699;
  /* Подсказка в незаполненном поле — один тон на весь сайт: и для нативного
     ::placeholder, и для самописных селектов, где «плейсхолдер» это просто
     строка текста и в ::placeholder не попадает. */
  --color-placeholder: #B5BABD;

  --radius-lg: 20px;
  --radius-md: 14px;
  --radius-sm: 8px;
  --radius-pill: 999px;

  --shadow-card: 0 10px 30px rgba(44, 64, 91, 0.08);
  --shadow-card-hover: 0 16px 40px rgba(44, 64, 91, 0.14);

  --container-width: 1400px;
  --header-height: 84px;

  --font-main: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; overflow-x: hidden; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* Background stops scrolling while the mobile menu is open. Locking on <html>
   rather than <body> matters: overflow:hidden on body turns body itself into
   a distinct scroll container, which breaks the header's position:sticky
   (it ends up sticking relative to body's frozen scrollTop instead of the
   real page scroll, and jumps out of view). html has no sticky descendants
   depending on it as a scroll container, so it's safe to lock there. */
html.nav-open { overflow-y: hidden; }
/* Пока открыто окно входа, страница под ним тоже не должна прокручиваться.
   Класс на <html> вешался, но правила к нему не было: на телефоне при
   появлении клавиатуры браузер прокручивал страницу к полю ввода, и после
   закрытия окна липкая шапка оказывалась выше видимой области — на её месте
   в открытом меню просвечивал сайт, без логотипа и крестика. */
html.lk-modal-open { overflow-y: hidden; }
/* Same idea for the address map picker: without this, scrolling inside its
   fixed-position panel (e.g. flicking through suggestions on mobile) can
   chain into the page behind it once an inner scroll area bottoms out,
   leaving the page scrolled to an unrelated spot once the modal closes. */
html.order-map-open { overflow-y: hidden; }

body {
  margin: 0;
  font-family: var(--font-main);
  color: var(--color-text);
  font-size: 16px;
  line-height: 1.6;
  background: var(--color-white);
  /* Прижимаем подвал к низу окна на коротких страницах (например, экран
     «Заявка принята»): колонка во всю высоту экрана, а подвалу отдаём весь
     остаток через margin-top: auto. На длинных страницах ничего не меняется —
     контент и так выше окна. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.site-footer { margin-top: auto; }

img { max-width: 100%; display: block; }

/* opacity: 1 обязателен: Firefox по умолчанию гасит плейсхолдер прозрачностью
   поверх цвета, без сброса оттенок там выйдет светлее заданного. */
input::placeholder,
textarea::placeholder {
  color: var(--color-placeholder);
  opacity: 1;
}
/* Нативный <select> не поддерживает ::placeholder — красим саму пустую строку.
   Красить весь <select> через :invalid нельзя: раскрытый список тогда унаследует
   этот цвет и настоящие пункты тоже станут серыми. */
select option[value=""] { color: var(--color-placeholder); }

a { color: inherit; text-decoration: none; }

h1, h2, h3, h4, h5, h6 {
  color: var(--color-navy);
  font-weight: 700;
  line-height: 1.25;
  margin: 0 0 16px;
}

h1 { font-size: clamp(28px, 4vw, 44px); }
h2 { font-size: clamp(24px, 3vw, 32px); }
.why-us-title { font-size: clamp(24px, 2.9vw, 31px); font-weight: 600; }
.services-title {
  font-size: clamp(32px, 4vw, 42px);
  font-weight: 600;
  margin-bottom: 28px;
}
h3 { font-size: 20px; }

p { margin: 0 0 16px; }

.container {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 16px;
}

.section { padding: 72px 0; }
.section--soft { background: var(--color-bg-soft); }
.section--navy { background: var(--color-navy); color: #cfd8e6; }
.section--navy h2, .section--navy h3 { color: var(--color-white); }

.section-header {
  text-align: center;
  max-width: 680px;
  margin: 0 auto 48px;
}
.section-header p { color: var(--color-text-muted); }

.eyebrow {
  display: inline-block;
  color: var(--color-accent);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 13px;
  letter-spacing: 0.08em;
  margin-bottom: 12px;
}

/* ===== Buttons ===== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 32px;
  border-radius: var(--radius-pill);
  font-weight: 700;
  font-size: 15px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: all 0.2s ease;
  white-space: nowrap;
}
.btn--primary {
  background: var(--color-accent);
  color: var(--color-white);
}
.btn--primary:hover { background: var(--color-accent-dark); }
.btn--outline {
  background: transparent;
  border-color: var(--color-white);
  color: var(--color-white);
}
.btn--outline:hover { background: rgba(255,255,255,0.12); }
.btn--outline-navy {
  background: transparent;
  border-color: var(--color-navy);
  color: var(--color-navy);
}
.btn--outline-navy:hover { background: var(--color-navy); color: var(--color-white); }
/* Кнопка на два пункта крупнее обычной. Отдельным классом, а не правкой
   .btn--outline-navy: тем же классом набраны «Связаться с нами», кнопки
   личного кабинета и страницы 404 — их размер менять не просили. */
.btn--lg { font-size: 17px; }
.btn--soft {
  background: #F7F8FB;
  color: var(--color-navy);
}
.btn--soft:hover { background: #ffffff; }
.btn--block { width: 100%; font-size: 17px; }
/* Градиент, а не заливка: переход задаём через background-image, чтобы
   у .btn--primary из общих стилей осталась своя background-color как
   запасной вариант, если градиент почему-то не отрисуется. */
#calc-submit-btn { background-color: #839fc2; background-image: linear-gradient(135deg, #99b3d1 0%, #839fc2 100%); font-size: 19px; transition: filter 0.2s ease; }
#calc-submit-btn:hover { filter: brightness(0.93); }
#calc-submit-btn.is-ready { background-image: none; background-color: #E4584A; }
#calc-submit-btn.is-ready:hover { background-color: #c94537; }

/* Срок под кнопкой расчёта: появляется, когда выбраны СВХ и город. Место под
   строку держим всегда (min-height) и прячем её видимостью, а не display:
   иначе при появлении текста калькулятор вырастает и вся страница прыгает. */
.calc-eta {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 12px;
  min-height: 20px;
  font-size: 14px;
  line-height: 1.4;
  color: var(--color-navy);
}
.calc-eta.is-empty { visibility: hidden; }
.calc-eta svg { flex: 0 0 auto; margin-top: 1px; color: #1c7a34; }

/* ===== Header ===== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--color-white);
  box-shadow: 0 2px 16px rgba(44, 64, 91, 0.14);
  height: var(--header-height);
  display: flex;
  align-items: center;
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
}
.site-header__logo {
  display: flex;
  align-items: center;
  margin: 0;
  flex-shrink: 0;
}
.site-header__logo img { height: 64px; width: auto; display: block; }

.site-nav {
  display: flex;
  gap: 28px;
  flex: 1;
  justify-content: center;
}
.site-nav a {
  font-weight: 400;
  font-size: 16px;
  color: var(--color-navy);
  padding: 8px 0;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.site-nav a:hover, .site-nav a.is-active {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}
.site-nav a.btn--primary, .site-nav a.btn--primary:hover {
  color: var(--color-white);
  border-width: 2px;
  border-color: transparent;
  font-weight: 700;
  font-size: 18px;
}
.site-nav a.btn--outline-navy {
  border-width: 2px;
  border-color: var(--color-navy);
  color: var(--color-navy);
  font-size: 18px;
}
.site-nav a.btn--outline-navy:hover {
  border-width: 2px;
  border-color: var(--color-navy);
  background: var(--color-navy);
  color: var(--color-white);
  font-size: 18px;
}
.site-nav__mobile-actions { display: none; }

.has-dropdown { position: relative; display: flex; align-items: center; }
.has-dropdown__row { display: flex; align-items: center; }
.has-dropdown__toggle {
  display: none;
  width: 35px;
  height: 35px;
  border: none;
  background: transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
/* Галочка нарисована двумя границами квадрата — правой и нижней, — а сам
   квадрат повёрнут на 45°. Из-за этого её «чернила» лежат не в центре
   элемента, а в его нижнем правом углу: центр закрашенной части смещён от
   центра квадрата на 2,42px по обеим осям, что после поворота даёт ровно
   3,4px вниз. На эту величину и поднимаем — тогда галочка стоит по центру
   серой кнопки. Прежние translateX(-3px) и margin-top:-6px делали это на
   глаз и уводили её к левому краю. */
.has-dropdown__chevron {
  width: 14px;
  height: 14px;
  border-right: 3px solid var(--color-navy);
  border-bottom: 3px solid var(--color-navy);
  transform: translateY(-3.4px) rotate(45deg);
  transition: transform 0.25s ease;
}
.dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 8px;
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-hover);
  padding: 10px;
  min-width: 240px;
}
/* invisible bridge so the pointer stays within the hover area while
   crossing the visual gap between the nav link and the dropdown box */
.has-dropdown::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 8px;
}
.has-dropdown:hover .dropdown-menu { display: block; }
.dropdown-menu a {
  display: block;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border-bottom: none !important;
  font-weight: 600;
  font-size: 14px;
}
.dropdown-menu a:hover { background: var(--color-bg-soft); }

/* Порог бургер-меню — 1119px, а не 960. Полная строка шапки (логотип 197 +
   пять пунктов 432 + телефон и две кнопки 576 + просветы) требует 1253px, и
   на окне 1024 или 1180 она вылезала за экран на 229 и 73 пикселя, утаскивая
   вбок всю страницу. Ниже 1120 показываем бургер, от 1120 до 1280 — ужатую
   строку (см. блок в конце файла), от 1281 — обычную. */
@media (max-width: 1119px) {
  .has-dropdown { display: block; width: 100%; }
  .has-dropdown__row {
    width: 100%;
    justify-content: space-between;
    /* Линию рисует не строка, а ссылка внутри неё — см. ниже. */
    border-bottom: none;
  }
  /* Подчёркивание принадлежит ссылке и заканчивается перед стрелкой: это
     два разных действия — по названию открывается раздел, по стрелке
     раскрывается список. Общая линия под ними читалась как одна ссылка.
     flex: 1 сохраняет большую область нажатия по названию, margin-right —
     тот самый просвет, которым стрелка отделяется от подчёркивания.
     Селектор с .site-nav обязателен: правило .site-nav a ниже по файлу и
     при равной силе перебило бы эти свойства. */
  .site-nav .has-dropdown__row a {
    flex: 1;
    width: auto;
    margin-right: 10px;
    border-bottom: 2px solid var(--color-bg-soft);
  }
  /* Активный раздел — красная линия. Отдельным правилом и с большей силой:
     иначе серый цвет выше по файлу перекрыл бы .site-nav a.is-active. */
  .site-nav .has-dropdown__row a.is-active { border-bottom-color: var(--color-accent); }
  .has-dropdown__toggle { display: flex; }
  /* Раскрытый пункт — галочка смотрит вверх. Смещение зеркальное: при 225°
     закрашенная часть уходит на те же 3,4px вверх. */
  .has-dropdown.is-open .has-dropdown__chevron { transform: translateY(3.4px) rotate(225deg); }
  .dropdown-menu {
    display: block;
    position: static;
    box-shadow: none;
    padding: 0 0 0 16px;
    margin-top: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.25s ease;
  }
  .has-dropdown.is-open .dropdown-menu { max-height: 300px; }
  .site-nav .dropdown-menu a { font-size: 16px; }
  .site-nav a {
    padding: 10px 0;
    border-bottom: 2px solid var(--color-bg-soft);
    width: 100%;
    font-weight: 600;
    font-size: 17px;
  }
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: 10px;
}
.site-header__actions .btn {
  padding: 8px 16px;
  font-size: 16px;
  font-weight: 400;
}
.site-header__actions .btn--primary.site-header__cta {
  padding-left: 24px;
  padding-right: 24px;
}
.site-header__actions .btn.site-header__cta--icon {
  padding: 0;
  width: 38px;
  height: 38px;
}
/* The icon must never be the thing that gives up space when a long company
   name is squeezed in next to it (see .lk-cta-label below) — without this
   flex's default shrink:1 would let it get compressed too. */
.js-lk-cta svg { flex-shrink: 0; }
/* Logged-in clients see their company name here instead of "Личный кабинет"
   (set by JS in main.js from /lk/whoami_api.php, which also adds the
   .lk-cta--active class below). Scoped to that class — not just .lk-cta-label
   — so a logged-out visitor's button renders with zero new CSS involved,
   identical to a plain icon+text pill with no flex overrides in play. Once
   active, the label only *shrinks* (never grows) below its own content
   width when there isn't room — a short name still sits at its natural
   size, so it stays paired with the icon as one centered group exactly like
   "Личный кабинет" did; only a name that's actually too long gets clipped
   against the fixed button width instead of stretching it. --fade (added
   by JS only when the name actually overflows) switches to left-aligned
   text with the right edge masked out, rather than a hard cut or "…". */
.lk-cta--active .lk-cta-label {
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-align: center;
}
.lk-cta--active .lk-cta-label--fade {
  text-align: left;
  mask-image: linear-gradient(to right, #000 70%, transparent 100%);
  -webkit-mask-image: linear-gradient(to right, #000 70%, transparent 100%);
}
/* The person icon uses fill="currentColor" — recoloring just the svg's own
   `color` (not the whole button) keeps it independent of the label next to it.
   На светло-голубой заливке (правило ниже) красный смотрелся чужеродно,
   поэтому иконка того же тёмно-синего, что и текст. Отдельное правило на
   ховер обязательно: там кнопка заливается navy, и тёмная иконка без него
   слилась бы с фоном. */
.lk-cta--active svg { color: #2f405b; }
.lk-cta--active:hover svg { color: var(--color-white); }
/* Залогиненная кнопка отличается от гостевой не только красной иконкой, но и
   заливкой. #F0F5FE — тот же цвет, которым на сайте залиты корректно
   заполненные поля (.order-field input.is-valid и др.), то есть «состояние,
   а не действие»: рамка и текст остаются navy, поэтому кнопка не спорит с
   красной «Создать заказ» рядом. Ховер не трогаем — правило
   .btn--outline-navy:hover специфичнее и по-прежнему заливает кнопку navy. */
.lk-cta--active { background: #F0F5FE; }

/* Account menu — clicking the button while logged in opens this instead of
   navigating straight to /lk/, so "Выйти" (log out) is reachable from any
   page without going into the cabinet first (see performLkLogout() /
   initLkCta() in main.js). Built and appended by JS, not present in the
   static markup. */
.js-lk-cta { position: relative; }
.lk-account-menu {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  min-width: 200px;
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-hover);
  padding: 6px;
  z-index: 200;
  text-align: left;
}
.lk-account-menu.is-open { display: block; }
.lk-account-menu__item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border: none;
  background: none;
  font-family: var(--font-main);
  font-size: 14px;
  font-weight: 600;
  color: var(--color-navy);
  cursor: pointer;
  white-space: nowrap;
}
.lk-account-menu__item:hover { background: var(--color-bg-soft); }
.lk-account-menu__item--logout { color: #e53935; border-top: 1px solid var(--color-bg-soft); margin-top: 4px; padding-top: 14px; }
/* Desktop only — the mobile nav button opens the fullscreen login-modal
   shell instead (see openLkAccountModal() in main.js), not this dropdown. */

/* Login modal, opened from the header's "Личный кабинет" button instead of
   navigating to /lk/login.php — the visitor never leaves the page they were
   on (see initLkModal() in main.js). */
.lk-modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(44, 64, 91, 0.55);
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.lk-modal-overlay.is-open { display: flex; }
.lk-modal {
  position: relative;
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card-hover);
  padding: 40px 32px 32px;
  width: 400px;
  max-width: 100%;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
}
/* Список подсказок почты лежит поверх содержимого окна, как и везде на сайте.
   Раньше окно обрезало его своей прокруткой, поэтому список ставили в поток —
   но тогда окно раздвигалось на каждый символ и прыгало. Теперь на время
   показа списка окно перестаёт обрезать содержимое (класс ниже ставит скрипт),
   а сам список ограничен тремя вариантами — прокручивать нечего. */
.lk-modal--suggest-open { overflow: visible; }
.lk-modal .calc-city-suggestions { max-height: 168px; }
.lk-modal__close {
  position: absolute;
  top: 14px;
  right: 14px;
  border: none;
  background: none;
  font-size: 28px;
  line-height: 1;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 4px;
}
.lk-modal__close:hover { color: var(--color-navy); }
.lk-modal__badge {
  display: inline-block;
  background: var(--color-bg-soft);
  color: var(--color-navy);
  font-size: 13px;
  font-weight: 700;
  padding: 4px 12px;
  border-radius: var(--radius-pill);
  margin-bottom: 16px;
}
.lk-modal h2 { font-size: 22px; margin: 0 0 16px; }
.lk-modal p.hint { font-size: 13px; color: var(--color-text-muted); margin: 14px 0 0; }
.lk-modal__error { color: #e53935; font-size: 14px; margin: 0 0 12px; }
.lk-modal__message { font-size: 15px; color: var(--color-text); margin: 0; }
/* Кнопка под пояснением стояла вплотную к тексту — читалось как одна строка,
   а не как ответ на вопрос «что делать дальше». */
.lk-modal__action { margin-top: 20px; }
/* Второе действие — ссылкой, а не кнопкой: главное здесь одно, остальное не
   должно спорить с ним за внимание. */
.lk-modal__secondary {
  display: block;
  margin-top: 14px;
  text-align: center;
  font-size: 14px;
  color: var(--color-text-muted);
}
.lk-modal__secondary:hover { color: var(--color-navy); }
.lk-modal__company-btn {
  display: block;
  width: 100%;
  margin-bottom: 10px;
  padding: 12px 16px;
  border: 2px solid var(--color-navy);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-navy);
  font-weight: 700;
  font-size: 15px;
  cursor: pointer;
  text-align: center;
  font-family: var(--font-main);
}
.lk-modal__company-btn:hover { background: var(--color-navy); color: var(--color-white); }
.lk-modal__company-btn--danger { border-color: #e53935; color: #e53935; margin-top: 10px; }
.lk-modal__company-btn--danger:hover { background: #e53935; color: var(--color-white); }
.lk-modal__resend {
  display: block;
  width: 100%;
  margin-top: 10px;
  background: none;
  border: none;
  color: var(--color-accent);
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  padding: 8px;
  font-family: var(--font-main);
}
.lk-modal__resend:hover { color: var(--color-accent-dark); }
.lk-modal__resend:disabled { color: var(--color-text-muted); cursor: default; }
.lk-modal .order-field { margin-bottom: 16px; }
.lk-modal .order-field input {
  text-align: left;
}
/* Экран после успешного входа: галочка, название компании и строка о том,
   что происходит дальше. Показывается секунду — ровно чтобы человек увидел
   результат там, куда смотрит. */
.lk-done { text-align: center; padding: 8px 0 4px; }
.lk-done__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin-bottom: 14px;
  border-radius: 50%;
  background: #E6F5EC;
  color: #1c9a5e;
}
.lk-done h2 { margin: 0 0 6px; }
.lk-done p { margin: 0 0 4px; font-weight: 700; color: var(--color-navy); }
.lk-done .hint { font-weight: 400; }

/* Код из письма — четыре отдельные ячейки, как в банковских приложениях:
   сразу видно длину кода и сколько цифр осталось ввести. */
.lk-code { display: flex; gap: 10px; justify-content: center; }
.lk-modal .order-field .lk-code input.lk-code__digit {
  width: 56px;
  flex: 0 0 56px;
  padding: 12px 0;
  text-align: center;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.2;
}
@media (max-width: 380px) {
  /* На узких экранах четыре ячейки по 56px с промежутками не помещаются. */
  .lk-code { gap: 8px; }
  .lk-modal .order-field .lk-code input.lk-code__digit { width: 100%; flex: 1 1 0; }
}
/* Same "full screen, any phone size" convention as the admin's own modals
   (.modal-box/.send-modal-box in admin.css) — kept here instead of shared
   since this modal lives in the public site's own stylesheet. */
@media (max-width: 700px) {
  .lk-modal-overlay { padding: 0; align-items: stretch; justify-content: stretch; }
  .lk-modal {
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
    border-radius: 0;
    overflow-y: auto;
    /* Форма занимает весь экран, но содержимого в ней немного — прижатое к
       верху, оно висело в пустоте. Центрируем по вертикали: короткий шаг
       окажется посередине, а длинный (выбор из нескольких компаний) упрётся
       в края и будет прокручиваться как обычно. */
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
  .lk-modal #lk-modal-body { flex: 0 0 auto; }
  /* Крестик переносим из угла всего листа к самой форме, в её правый верхний
     угол. В углу экрана он терялся: при появлении клавиатуры браузер
     подкручивает страницу к полю ввода, верх листа уходит из видимой области,
     и выйти из окна становится нечем. Рядом с формой он остаётся на виду
     всегда — куда бы браузер ни подкрутил. */
  .lk-modal__close {
    position: static;
    align-self: flex-end;
    margin: 0 -8px 2px 0;
    font-size: 34px;
    padding: 4px 10px;
  }
}
.site-header__phone {
  font-weight: 700;
  color: var(--color-navy);
  font-size: 18px;
  white-space: nowrap;
  margin-right: 40px;
}
/* The three bars are positioned absolutely rather than laid out by flex `gap`.
   With gap the open cross is only centred if the ±10px counter-translate below
   exactly cancels the gap the browser applied — anywhere gap is unsupported or
   rounded differently (older iOS Safari in particular) the two strokes stop
   meeting in the middle and the X comes out skewed. Pinned to the centre of
   the button, each bar already sits on the crossing point, so the open state is
   a pure rotation and cannot drift. */
.nav-toggle {
  display: none;
  position: relative;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  background: var(--color-white);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.25s ease;
}
/* Полоски 28px в длину — на 29% длиннее исходных 22px. Толщина 3px: при
   4px просветы между полосками (6px) переставали читаться и значок
   выглядел сплошным пятном; на 3px просвет 7px — больше двойной толщины,
   и три линии снова различимы. Кнопка
   осталась 44×44: она и так минимально удобная для пальца, а её изменение
   вместе с поворотом полосок делало крестик кривым на реальных устройствах
   (см. комментарий ниже). Отрицательные margin — ровно половина ширины и
   высоты: полоска обязана стоять центром в центре кнопки, иначе крестик
   разъедется. */
.nav-toggle span {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 28px;
  height: 3px;
  margin: -1.5px 0 0 -14px;
  background: var(--color-navy);
  display: block;
  transition: transform 0.25s ease, opacity 0.2s ease, background 0.25s ease;
}
.nav-toggle span:nth-child(1) { transform: translateY(-10px); }
.nav-toggle span:nth-child(3) { transform: translateY(10px); }
/* Burger morphs into a close cross while the menu is open — sits in the same
   top-right corner of the header, right next to the logo, so it's an obvious,
   easy-to-tap way to close the full-width mobile menu. Same background and
   same line color/thickness as the burger itself, just rotated into an X.
   The button itself stays a fixed 44×44 (no longer grows to 48×48) — resizing
   the container at the same time the spans rotate made the cross render
   lopsided mid-transition on real devices. */
.nav-toggle.is-active span:nth-child(1) { transform: rotate(45deg); }
.nav-toggle.is-active span:nth-child(2) { opacity: 0; }
.nav-toggle.is-active span:nth-child(3) { transform: rotate(-45deg); }

/* ===== Hero ===== */
.hero {
  background: linear-gradient(135deg, var(--color-navy) 0%, #1c2c42 100%);
  color: var(--color-white);
  padding: 30px 0 32px;
  position: relative;
  /* No overflow clipping here: the calculator's «Откуда» dropdown is taller
     than the space left below it and has to spill over the next section. */
}
.hero h1 {
  font-size: clamp(24px, 2.9vw, 36px);
  font-weight: 600;
  color: var(--color-white);
  /* Подзаголовку нужен воздух с обеих сторон: втиснутый между заголовком и
     кнопками, он читался как их подпись, а не как отдельная мысль. */
  margin-bottom: 22px;
}
/* Калькулятор шире левой колонки на 20 точек: полям в нём тесновато, а у
   заголовка с подзаголовком запас есть. Отступ между колонками не трогаем —
   разницу берём у текста, поэтому ширина считается, а не делится поровну. */
.hero__grid {
  --hero-gap: 40px;
  --hero-calc-extra: 20px;
  display: grid;
  grid-template-columns:
    calc((100% - var(--hero-gap)) / 2 - var(--hero-calc-extra))
    calc((100% - var(--hero-gap)) / 2 + var(--hero-calc-extra));
  gap: var(--hero-gap);
  align-items: center;
}
.hero p.lead {
  font-size: 16px;
  color: #c3cedf;
  margin: 0 0 32px;
  max-width: 520px;
}
.hero__actions { display: flex; gap: 16px; flex-wrap: wrap; }
.hero__actions .btn { font-size: 18px; }
.hero__services-btn { font-weight: 400; }
.hero__image {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card-hover);
}

/* ===== Calculator widget (visual placeholder for now) ===== */
.calc-widget {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card-hover);
  padding: 32px 32px 26px;
  position: relative;
  z-index: 5;
}
.calc-widget__title {
  margin: 0 0 16px;
  font-size: 20px;
  font-weight: 700;
  color: var(--color-navy);
}
.calc-widget__tabs {
  display: flex;
  /* Метка «скоро» у запертых вкладок вынесена на верхнюю границу плашки и
     ширины ряда не занимает — поэтому три кнопки помещаются в строку без
     ужимания текста. Отступ сверху — место под саму метку, иначе её срежет
     край блока. Зазор между кнопками небольшой, но заметный: впритык они
     читались как одна длинная плашка с перегородками. Ряд от этого не
     переносится — кнопки берут ширину по тексту, а свободное место делят
     между собой. */
  gap: 8px;
  padding-top: 7px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.calc-widget__tab {
  /* flex-basis по содержимому, а не поровну: при равной ширине длинная
     «Доставка с АВИА СВХ» ужималась до предела, а короткая «Доставка по РФ»
     держала лишнее место. Теперь каждая берёт своё, а свободное место
     делится сверх того. */
  position: relative;
  /* Ширина — треть ряда: пока названия помещаются, все три кнопки ровно
     одинаковые. Если места не хватит, кнопка возьмёт по содержимому и ряд
     перенесётся — лучше перенос, чем обрезанное название услуги. */
  flex: 1 1 calc(33.333% - 10px);
  padding: 9px 6px;
  border-radius: var(--radius-pill);
  /* Те же вкладки, что в форме заказа: невыбранная белая с тёмной рамкой,
     выбранная — голубая. Человек приходит на форму отсюда, и переключатель
     услуги должен выглядеть одинаково в обоих местах. */
  background: var(--color-white);
  border: 2px solid var(--color-navy);
  color: var(--color-navy);
  font-weight: 600;
  font-size: 13px;
  white-space: nowrap;
  text-align: center;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.calc-widget__tab:hover {
  background: var(--color-navy);
  color: var(--color-white);
}
.calc-widget__tab.is-active {
  background: #E8F0FD;
  border-color: var(--color-navy);
  color: var(--color-navy);
  cursor: default;
}
.calc-widget__tab.is-active:hover {
  background: #E8F0FD;
  color: var(--color-navy);
}
.calc-widget__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  margin-bottom: 18px;
}
/* Колонка не должна растягиваться под длинное название терминала: у сетки
   ячейка по умолчанию не уже своего содержимого, и «АО "Грузовой Терминал
   Пулково" (LED)» раздвигал левую половину, а правая («Куда») на столько же
   сжималась. min-width: 0 возвращает половины к равным, а длинное название
   просто не помещается целиком — как в любом обычном списке. */
.calc-field { min-width: 0; }
.calc-field label {
  display: block;
  font-size: 13px;
  font-weight: 700;
  color: var(--color-text-muted);
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.calc-field label .required { color: var(--color-accent); }
.calc-field input, .calc-field select {
  width: 100%;
  min-width: 0;
  padding: 10px 14px;
  border: 2px solid var(--color-bg-soft);
  border-radius: var(--radius-sm);
  font-family: var(--font-main);
  /* 16px — общий кегль полей на сайте. Заодно снимает автозум iOS: он
     срабатывает на всём, что мельче 16px. */
  font-size: 16px;
  color: var(--color-navy);
  background: var(--color-white);
}
.calc-field input:focus, .calc-field select:focus {
  outline: none;
  border-color: var(--color-navy-light);
}
.calc-field input.is-invalid, .calc-field select.is-invalid {
  border-color: #e53935 !important;
}
/* Заполненное поле калькулятора — как на форме заказа: рамка чуть темнее,
   без заливки. */
.calc-field input.is-valid, .calc-field select.is-valid {
  border-color: #c9d3e0;
}
.calc-field input:focus, .calc-field select:focus { border-color: var(--color-navy-light); }
/* Colour the placeholder row itself (not the whole <select> via :invalid) —
   otherwise the open dropdown's real options inherit whatever colour the
   select currently has, so they'd render grey the first time and only turn
   dark from the second open onwards, once a real option had been picked. */
.calc-field select option { color: var(--color-navy); }
.calc-field select option[value=""] { color: var(--color-placeholder); }
/* Native select arrows sit flush against the right edge and can't be moved
   with CSS — swap in our own so it can be nudged further in from the edge. */
.calc-field select,
.order-field select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1L6 6L11 1' stroke='%232c405b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: right 14px top calc(50% + 1px) !important;
  background-color: var(--color-white) !important;
  padding-right: 40px !important;
  cursor: pointer;
}
.calc-input-wrap { position: relative; }
/* Обёртка поля с крестиком очистки. Блочная и во всю ширину — поле внутри
   ведёт себя как раньше; во флекс-строках («тот же», адрес) обёртка забирает
   себе долю, которая раньше принадлежала полю. */
.input-clear-wrap { position: relative; display: block; width: 100%; }
.order-same-row .input-clear-wrap,
/* Обёртка поля с подсказками ведёт себя в строке так же, как поле: без этого
   она сжималась по содержимому, и ввод превращался в узкую щель рядом с
   галочкой. */
.order-same-row .calc-input-wrap { flex: 1; min-width: 0; }
.input-clear {
  position: absolute;
  /* Выше полоски растворения: она рисуется после кнопки и накрывала бы её. */
  z-index: 1;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: none;
  color: var(--color-placeholder);
  cursor: pointer;
}
.input-clear:hover { color: var(--color-navy); }
/* Длинный текст не должен упираться в крестик и лезть под него: у правого
   края поле растворяется в белый. Полоска лежит поверх текста, но клики
   пропускает — под ней и сам крестик, и конец строки. */
.input-clear-wrap.has-clear::after {
  content: "";
  position: absolute;
  top: 3px;
  bottom: 3px;
  right: 3px;
  width: 54px;
  pointer-events: none;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--color-white) 45%);
}
/* Текст не должен заезжать под крестик. */
.input-clear-wrap input { padding-right: 38px; }
.calc-city-suggestions {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-hover);
  max-height: 240px;
  overflow-y: auto;
  padding: 8px;
  z-index: 40;
}
.calc-city-suggestions.is-open { display: block; }
/* «Откуда» carries a search box the «Куда» dropdown doesn't, so its default
   max-height would render taller. Match the two here — side by side in the
   calculator they have to line up, and both end inside the dark hero block. */
.calc-widget .custom-select__panel { max-height: 240px; }
/* Подсказки под полем переносим целиком, а не по слогам: «Шереметьево-Карго»,
   разорванное на две строки, читается как два разных терминала. */
.calc-quick-cities { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 6px; }
.calc-quick-city {
  border: none;
  background: none;
  padding: 0;
  white-space: nowrap;
  color: var(--color-text-muted);
  font-size: 12px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.calc-quick-city:hover { color: var(--color-navy); }
.calc-city-suggestions__item {
  padding: 10px 14px;
  font-size: 14px;
  color: var(--color-navy);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.calc-city-suggestions__item:hover, .calc-city-suggestions__item.is-active { background: var(--color-bg-soft); }
.calc-widget__note {
  font-size: 13px;
  line-height: 1.3;
  color: var(--color-text-muted);
  text-align: center;
  margin-top: 18px;
  margin-bottom: 0;
}
.badge-soon {
  display: inline-block;
  background: var(--color-bg-soft);
  color: var(--color-navy-light);
  font-size: 12px;
  font-weight: 700;
  padding: 4px 12px;
  border-radius: var(--radius-pill);
  margin-left: 8px;
  vertical-align: middle;
}

/* ===== Cards / grids ===== */
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 28px;
}
.grid-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}
/* Та же история, что и с .two-col: колонка сетки по умолчанию не сжимается
   уже своего содержимого. На контактах карточка с адресом почты требовала
   348px против 328px колонки, и страница ехала вбок на 44px при экране 320.
   min-width:0 разрешает колонке сжиматься, overflow-wrap ломает длинный
   адрес — переносить его по буквам некрасиво, но лучше, чем сдвинутая
   страница, и срабатывает только на совсем узких экранах. */
.grid-3 > *, .grid-2 > *, .grid-4 > * { min-width: 0; }
.card, .card p, .card a { overflow-wrap: break-word; }

.card {
  background: var(--color-white);
  border-radius: var(--radius-md);
  padding: 32px 28px;
  box-shadow: var(--shadow-card);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.card:hover { box-shadow: var(--shadow-card-hover); transform: translateY(-4px); }
.card--static:hover { box-shadow: var(--shadow-card); transform: none; }
.card--compact { padding: 30px 28px 6px; }
.card--map { padding: 0; overflow: hidden; }
.card--map:hover { box-shadow: var(--shadow-card); transform: none; }
.card--map__frame { width: 100%; height: 440px; overflow: hidden; }
.card--map__frame iframe { width: 100%; height: 440px; border: none; }
.card--map__body { padding: 24px 28px; }
.card p { color: var(--color-text-muted); }
.card__icon {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-sm);
  background: var(--color-bg-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  color: var(--color-accent);
  margin-bottom: 20px;
}

.card--icon-left {
  display: flex;
  align-items: flex-start;
  gap: 22px;
}
.card--icon-left .card__icon {
  width: auto;
  height: auto;
  background: none;
  border-radius: 0;
  font-size: 54px;
  line-height: 1;
  color: var(--color-navy);
  margin-bottom: 0;
  flex-shrink: 0;
}
/* min-width:0 обязателен: у элемента флекса минимальная ширина по умолчанию
   равна самому узкому состоянию содержимого, и адрес почты одной строкой не
   давал колонке сжаться — на экране 320 текст уезжал за карточку. */
.card--icon-left .card__body { flex: 1; min-width: 0; }
.card--icon-left h3 { margin-bottom: 10px; }
.card__link {
  color: var(--color-accent);
  font-weight: 700;
  font-size: 14px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
}

/* ===== Stats ===== */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  text-align: center;
}
.stat__number {
  font-family: 'Nunito', var(--font-main);
  font-style: italic;
  font-size: 84px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #2D405A;
  margin-bottom: 8px;
  white-space: nowrap;
}
.stat__label { color: var(--color-text-muted); font-size: 16px; }

/* ===== Content pages ===== */
.page-hero {
  padding: 24px 0 8px;
}
.page-hero + .section { padding-top: 32px; }
/* Форма заказа начинается сразу под заголовком: здесь за ним идёт не текст, а
   первая карточка с полями, и большой отступ читался как пустое место.
   До карточки должно получиться ровно 25 пикселей, а к ним уже прибавлены
   отступ под самим заголовком (10) и низ шапки страницы (8) — отсюда 7. */
.page-hero + .section--order { padding-top: 7px; }
.page-hero h1 {
  font-family: 'Nunito', var(--font-main);
  font-style: italic;
  font-weight: 700;
  font-size: clamp(38px, 4.5vw, 48px);
  margin-bottom: 10px;
}
/* Заголовок статьи на телефоне.

   В clamp() нижняя граница 38px, и на узком экране берётся именно она: 4.5vw
   при ширине 390px — это 17px, то есть меньше минимума. Для коротких
   заголовков разделов («Блог», «Контакты») крупный кегль хорош, а заголовок
   статьи — предложение на десяток слов: он разваливался на семь строк и
   занимал весь первый экран, оттесняя и картинку, и начало текста.

   Поэтому уменьшаем только на странице статьи и только на телефоне.
   24px читалось уже мелко для главного заголовка страницы — 29px держит
   заголовок явно крупнее подзаголовка и текста, но всё ещё умещает его
   в три-четыре строки. */
@media (max-width: 720px) {
  .page-hero--post h1 {
    font-size: 29px;
    line-height: 1.3;
  }
}
.breadcrumbs {
  font-size: 12px;
  color: var(--color-text-muted);
  margin-bottom: 12px;
}
.breadcrumbs a { color: #7A8699; }
.breadcrumbs a:hover { color: var(--color-accent); }

.prose { max-width: 820px; }
.prose p { margin-bottom: 26px; }
/* lede paragraph: bolded/enlarged automatically, no manual formatting needed
   in the editor — only fires when the article actually opens with a
   paragraph right after the featured image (skips list-first articles) */
/* Обложка теперь обёрнута в <picture> (лёгкие копии в WebP), поэтому соседом
   абзаца стал он, а не сама картинка — перечисляем оба варианта. */
.prose picture + p,
.prose img.prose__featured-img + p {
  font-weight: 700;
  font-size: 1.15em;
  line-height: 1.5;
}
.prose ul, .prose ol { padding-left: 20px; }
.prose li { margin-bottom: 8px; }
.prose a { color: var(--color-accent); text-decoration: underline; text-underline-offset: 2px; }
.prose a:hover { color: var(--color-accent-dark); }
/* Картинка внутри статьи занимает всю ширину колонки. Раньше ширина шла от
   самого файла, и вертикальный снимок вставал узким столбиком по центру —
   рядом с ним оставались пустые поля, а по высоте он съедал пол-экрана.
   Поэтому и генерируем их горизонтальными. */
.prose img {
  border-radius: var(--radius-md);
  margin: 28px 0;
  width: 100%;
  /* Пропорция задана здесь, а не берётся от файла: картинку в статью может
     загрузить кто угодно и какую угодно, а полоса должна быть одинаковой во
     всех статьях и не съедать пол-экрана по высоте. Что не влезло —
     обрезается по краям, а не сжимается. */
  aspect-ratio: 7/2;
  object-fit: cover;
  height: auto;
}
/* the logo placeholder used when a news post has no photo is white-on-white
   against the page background — a thin border keeps it reading as an
   intentional photo slot instead of a missing image */
img.is-placeholder { border: 1px solid var(--color-bg-soft); }
/* the featured image at the top of a post always gets a fixed, uniform
   banner shape regardless of what size photo was actually uploaded —
   admins won't reliably crop/resize before uploading, so we crop for them */
.prose img.prose__featured-img {
  width: 100%;
  height: auto;
  max-height: none;
  aspect-ratio: 14/3;
  object-fit: cover;
  border-radius: var(--radius-lg);
  margin: 0 0 32px;
}
/* display: block нужен был, чтобы широкая таблица прокручивалась на телефоне,
   но у блочной таблицы колонки перестают растягиваться: на десктопе она
   прижималась к левому краю, оставляя пустое место справа. Прокрутку отдаём
   обёртке, а сама таблица остаётся таблицей и занимает всю ширину. */
.prose table {
  width: 100%;
  font-size: 1em;
  border-collapse: collapse;
  margin: 24px 0;
  table-layout: auto;
}
.prose .table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin: 24px 0;
}
.prose .table-wrap table { margin: 0; }
.prose table th, .prose table td { padding: 14px 16px; text-align: left; border-bottom: 1px solid var(--color-bg-soft); }
.prose table th { background: var(--color-bg-soft); font-weight: 600; white-space: nowrap; }

/* Выделенный кусок текста в статье: важное предупреждение или короткий вывод,
   который должен цепляться взглядом при беглом чтении. Полоса слева, а не
   рамка со всех сторон, — так блок не выглядит вставленной чужой карточкой. */
.prose .note {
  background: #E8F0FD;
  border-left: 4px solid var(--color-navy-light);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 18px 22px;
  margin: 28px 0;
}
.prose .note p:last-child { margin-bottom: 0; }
.prose .note__title {
  display: block;
  font-weight: 700;
  color: var(--color-navy);
  margin-bottom: 6px;
}
/* Второй вид — предупреждение: то же построение, но акцентным цветом, для
   случаев «сделаете так — потеряете деньги или время». */
.prose .note--warning { background: #FDEDEB; border-left-color: var(--color-accent); }

.blog-post-layout {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 48px;
}
.blog-post-layout .prose { max-width: none; min-width: 0; }
.blog-aside__recent {
  background: var(--color-white);
  border-radius: var(--radius-md);
  padding: 24px;
  box-shadow: var(--shadow-card);
  /* Тот же отступ, что между колонками статьи (gap у .blog-post-layout):
     блоки правой колонки стоят на одной сетке с ней, и разное расстояние
     по горизонтали и вертикали читается как сбой вёрстки. */
  margin-bottom: 48px;
}
.blog-aside__recent h3 { font-size: 16px; margin-bottom: 18px; }
.blog-recent-item {
  display: block;
  margin-bottom: 20px;
  color: inherit;
}
/* Разделитель — линией сверху у каждой статьи, кроме первой. Через
   :last-child его не сделать: после списка идёт кнопка «Перейти в блог»,
   поэтому последняя статья последним ребёнком не является и линия осталась
   бы висеть перед кнопкой. */
.blog-recent-item + .blog-recent-item {
  padding-top: 20px;
  border-top: 1px solid var(--color-bg-soft);
}
.blog-recent-item img, .blog-recent-item__placeholder {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16/7;
  border-radius: 8px;
  object-fit: cover;
  background: var(--color-bg-soft);
  margin-bottom: 10px;
}
/* Category and publication date share one line so the sidebar list stays as
   compact as it was before the date was added. */
.blog-recent-item__meta {
  display: block;
  font-size: 12px;
  color: var(--color-text-muted);
  margin-bottom: 10px;
}
/* Дата на пункт крупнее рубрики: плашка и так выделена цветом, а дате
   размер нужен, иначе она теряется рядом с ней. */
.blog-recent-item__meta time { font-size: 13px; }
/* Category badge. The tint is what separates it from the date next to it, so
   the palette stays soft — these sit above article titles and must not
   outshout them. Unknown categories (the admin field is free text) fall back
   to .blog-badge--default. */
.blog-badge {
  display: inline-block;
  padding: 3px 10px;
  margin-right: 10px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  vertical-align: baseline;
  background: #eef0f5;
  color: var(--color-navy);
}
.blog-badge--instructions { background: #e4ecfa; color: #33507f; }
.blog-badge--tariffs      { background: #fbe9e7; color: #b8402f; }
.blog-badge--news         { background: #e2f0ea; color: #1f6a55; }
.blog-badge--about        { background: #f9eede; color: #91602a; }
/* Article header: the date is set larger there than in the cards, so pull the
   badge up to sit on the same optical line. */
.post-meta time { font-size: 15px; }
.blog-recent-item__title {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--color-navy);
  line-height: 1.35;
  transition: color 0.2s ease;
}
.blog-recent-item:hover .blog-recent-item__title { color: #7590b3; }
.blog-aside__more {
  width: 100%;
  margin-top: 4px;
  padding: 8px 18px;
  font-size: 13px;
  border-width: 1px;
}

/* Прилипший баннер отстоит от шапки на те же 48px, что и остальные отступы
   правой колонки: вплотную под шапкой он выглядел её продолжением. Считаем от
   высоты шапки, а не жёстким числом, — она разная на разных экранах. */
.blog-aside__sticky { position: sticky; top: calc(var(--header-height) + 48px); }
.blog-aside__banner {
  background: #E9EBF3;
  color: var(--color-navy);
  border-radius: var(--radius-md);
  padding: 32px 24px;
  text-align: center;
}
.blog-aside__banner h3 { color: var(--color-navy); font-size: 20px; margin-bottom: 10px; }
.blog-aside__banner p { color: var(--color-text-muted); font-size: 14px; margin-bottom: 20px; }
.blog-aside__banner .btn { width: 100%; }

@media (max-width: 960px) {
  .blog-post-layout { grid-template-columns: 1fr; }
  .blog-aside__sticky { position: static; top: auto; margin-top: 24px; }
}

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: center;
}
/* У колонки сетки минимальная ширина по умолчанию — не ноль, а самое узкое,
   до чего сжимается её содержимое. На экране 320 это 315px против 288px
   доступных, и главная ездила вбок на 11px. min-width:0 разрешает колонке
   быть уже содержимого, дальше картинку держит max-width:100%, а текст
   переносится по словам. */
.two-col > * { min-width: 0; }
.two-col img { max-width: 100%; height: auto; }

/* ===== Blog ===== */
.blog-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}
/* <picture> по умолчанию строчный: без этого под картинкой в карточке
   появляется лишний зазор от базовой линии строки. */
.blog-card picture, .blog-recent-item picture, .prose picture { display: block; }
.blog-card img {
  width: 100%;
  /* height: auto обязателен: в разметке у картинки проставлены её настоящие
     ширина и высота (чтобы место под неё занималось сразу и текст не прыгал),
     а браузер понимает атрибут height как высоту в пикселях и без этой строки
     растянул бы карточку на всю высоту оригинала. */
  height: auto;
  aspect-ratio: 20/9;
  border-radius: var(--radius-md);
  object-fit: cover;
  margin-bottom: 16px;
}
.blog-card h3 { font-size: 18px; font-weight: 600; transition: color 0.2s ease; }
.blog-card:hover h3 { color: #7590b3; }
.blog-card .date { color: var(--color-text-muted); font-size: 13px; margin-bottom: 8px; display: block; }

.blog-pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 48px;
}
.blog-pagination__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding: 0 14px;
  border-radius: var(--radius-pill);
  background: var(--color-white);
  border: 2px solid var(--color-bg-soft);
  color: var(--color-navy);
  font-weight: 600;
  font-size: 14px;
  transition: all 0.2s ease;
}
.blog-pagination__link:hover { border-color: var(--color-navy); text-decoration: none; }
.blog-pagination__link.is-active {
  background: var(--color-navy);
  border-color: var(--color-navy);
  color: var(--color-white);
}
.blog-pagination__dots { color: var(--color-text-muted); padding: 0 4px; }

/* ===== Contact ===== */
.contact-item__link {
  font-size: 20px;
  transition: color 0.2s ease;
}
.contact-item__link:hover {
  color: #7590b3;
}

/* ===== Footer ===== */
.site-footer {
  background: #223047;
  color: #a9b6cb;
  padding: 64px 0 32px;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr 0.7fr 0.7fr 1.3fr;
  gap: 20px;
  margin-bottom: 40px;
}
.footer-grid h4 {
  color: var(--color-white);
  font-size: 15px;
  margin-bottom: 18px;
}
.footer-grid ul { list-style: none; padding: 0; margin: 0; }
.footer-grid li { margin-bottom: 10px; font-size: 15px; }
.footer-grid a:hover { color: #D6E0F0; }
.footer-logo img { height: 34px; margin-bottom: 16px; }
/* Название компании в подвале набрано тем же шрифтом, что крупные цифры в
   блоке преимуществ (.stat__number) — Nunito курсивом. Кегль оставляем
   прежний, он задан инлайном в разметке подвала. */
.footer-logo {
  line-height: 1.25;
  font-family: 'Nunito', var(--font-main);
  font-style: italic;
  letter-spacing: -0.02em;
}
.footer-bottom {
  border-top: 1px solid rgba(255,255,255,0.1);
  padding-top: 24px;
  display: flex;
  justify-content: space-between;
  font-size: 15px;
  flex-wrap: wrap;
  gap: 12px;
}

/* ===== Mobile ===== */
@media (max-width: 960px) {
  .hero__grid { grid-template-columns: 1fr; }
  .grid-3, .grid-2, .grid-4, .stats, .blog-grid, .footer-grid { grid-template-columns: 1fr 1fr; }
  .two-col { grid-template-columns: 1fr; }
  .calc-widget__grid { grid-template-columns: 1fr 1fr; }

  /* iOS Safari (and other mobile browsers with the same behaviour)
     auto-zooms the whole page on focus if the focused field's font-size is
     under 16px — keep every text input/select/textarea at 16px+ below this
     breakpoint so tapping any field on the site doesn't trigger that
     zoom-in. Поля калькулятора, формы заказа и списков набраны 16px в
     базовых правилах, поэтому отдельных переопределений здесь больше нет —
     остался только поиск внутри списка (см. ниже). Любое новое поле должно
     быть 16px в своём базовом правиле. */
}

@media (max-width: 1119px) {
  /* Бургер вместо строки меню: полная строка не помещается ни в 1024, ни в
     1119 — см. пояснение у первого блока с этим же порогом. */
  :root { --header-height: 68px; }
  .site-nav {
    position: fixed;
    top: var(--header-height);
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(100dvh - var(--header-height));
    background: var(--color-white);
    flex-direction: column;
    justify-content: flex-start;
    padding: 20px 24px calc(40px + env(safe-area-inset-bottom));
    gap: 4px;
    box-shadow: 0 12px 24px rgba(0,0,0,0.08);
    transform: translateY(-150%);
    opacity: 0;
    transition: all 0.25s ease;
    overflow-y: auto;
  }
  .site-nav.is-open { transform: translateY(0); opacity: 1; }
  .nav-toggle { display: flex; }
  /* Пока открыто меню, шапку прибиваем к верху намертво. Липкой ей быть
     нечего: страница под меню заморожена, а от прокрутки, которую устраивает
     появившаяся клавиатура, липкая шапка уезжает вверх — и в полосе над меню
     видно страницу вместо логотипа и крестика. */
  html.nav-open .site-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
  }
  .site-header__phone { display: none; }
  /* the CTA button moves into the slide-down menu on mobile so the header
     row (logo + burger) never has to fight it for space and overflow */
  .site-header__cta { display: none; }
  .site-nav__mobile-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 100%;
    margin-top: 12px;
    padding-top: 12px;
  }
  .site-nav a.site-nav__mobile-phone {
    text-align: center;
    font-weight: 700;
    font-size: 24px;
    color: var(--color-navy);
    border-bottom: none;
  }
  .site-nav__mobile-cta { width: 100%; }
  .site-nav__mobile-divider { height: 1px; background: var(--color-bg-soft); width: 100%; }
}

@media (max-width: 720px) {
  .hero { padding: 32px 0 40px; }
  .calc-widget { padding: 20px 20px 14px; }
  /* На телефоне вкладки идут столбиком во всю ширину, и зазор между ними один
     и тот же по обеим сторонам. Раньше две первые кнопки вставали в строку, и
     промежуток между ними (3 точки) спорил с промежутком до третьей (12). */
  .calc-widget__tabs { gap: 12px; }
  .calc-widget__grid { grid-template-columns: 1fr; }
  /* На узком экране срок занимает две строки — столько места под него и
     держим, чтобы страница не дёргалась при появлении текста. */
  .calc-eta { min-height: 40px; }
  .grid-3, .grid-2, .grid-4, .blog-grid, .footer-grid { grid-template-columns: 1fr; }
  .section { padding: 48px 0; }
  .footer-bottom { flex-direction: column; text-align: center; }
  .prose img.prose__featured-img { aspect-ratio: 20/9; }

  /* ===== Карусели: показатели «Почему выбирают» и новости блога =====
     В столбик четыре плашки занимали пол-экрана и пролистывались мимо.
     Лента двигается трансформацией, а не прокруткой браузера: поведение
     программной прокрутки внутри лент с примагничиванием у Safari своё,
     и карусель на ней замирала. Здесь положение задаёт скрипт. */
  .stats, .blog-grid {
    display: block;
    grid-template-columns: none;
    gap: 0;
    overflow: hidden;
    /* Вертикальную прокрутку страницы пальцем не перехватываем — только
       горизонтальное листание, и то решает скрипт по направлению жеста. */
    touch-action: pan-y;
    /* Слайды — не текст для чтения: выделение мешает листать. */
    -webkit-user-select: none;
    user-select: none;
  }
  .carousel-track {
    display: flex;
    /* Подсказка браузеру заранее подготовить слой: без неё на слабых
       телефонах первый шаг ленты дёргается. */
    will-change: transform;
  }
  .stats .stat, .blog-grid .blog-card {
    flex: 0 0 100%;
    /* min-width: 0 обязателен: без него ширину слайда задаёт самое длинное
       слово внутри, и лента разъезжается. */
    min-width: 0;
  }
  .stats .stat { padding: 0 4px; }
  /* Кегль по ширине экрана: 84px не помещались даже на 360px, «1 кг»
     распирало страницу и появлялась горизонтальная прокрутка всего сайта. */
  .stat__number { font-size: clamp(52px, 17vw, 84px); }

  .carousel-dots {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: 18px;
  }
  .carousel-dots__dot {
    width: 8px;
    height: 8px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: var(--color-bg-soft);
    cursor: pointer;
    transition: background 0.25s ease, width 0.25s ease;
  }
  .carousel-dots__dot.is-active { width: 22px; border-radius: 999px; background: var(--color-accent); }
}

/* ===== Форма «Создать заказ» ===== */
/* Ширину не ограничиваем: страница заказа занимает ту же полосу, что и весь
   сайт (--container-width), и три колонки раскладываются по ней. Ограничение
   в 760px возвращается ниже, когда колонки схлопываются в один столбец. */
.order-form { margin: 0 auto; }
.order-card {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 32px;
  margin-bottom: 24px;
}
.order-card h2 { font-size: 22px; margin: 0 0 24px; }
.order-field { margin-bottom: 18px; }
.order-field label {
  display: block;
  font-size: 15px;
  font-weight: 700;
  color: var(--color-text-muted);
  margin-bottom: 6px;
}
/* Звёздочка обязательности красная везде, где встречается: у подписи поля
   и у заголовка карточки «Откуда», где подпись поля не нужна — она
   дублировала бы заголовок. Без второго селектора звёздочка в заголовке
   наследовала бы его тёмно-синий и переставала читаться как пометка. */
.order-field label .required,
.order-card__label .required,
.order-card h2 .required { color: var(--color-accent); }
/* Подписи групп внутри карточки «Маршрут»: услуга, откуда, куда. Выглядят как
   обычные подписи полей — раньше на их месте стояли заголовки карточек, и
   форма из-за этого выглядела втрое длиннее, чем есть. Отступ сверху отбивает
   группу от предыдущей, у первой его нет: над ней и так заголовок карточки. */
.order-card__label {
  display: block;
  font-size: 15px;
  font-weight: 700;
  color: var(--color-text-muted);
  margin: 22px 0 6px;
}
.order-card h2 + .order-card__label { margin-top: 0; }
/* Ошибка «Выберите услугу» висит под вкладками — без неё вкладки отбивались бы
   от следующей подписи только её собственным отступом. */
.order-service-tabs + input + .field-error { margin-top: 6px; }
.order-field input[type="text"],
.order-field input[type="tel"],
.order-field input[type="email"],
.order-field input[type="number"],
.order-field select,
.order-field textarea {
  width: 100%;
  line-height: 1.4;
  padding: 12px 14px;
  border: 2px solid var(--color-bg-soft);
  border-radius: var(--radius-sm);
  font-family: var(--font-main);
  font-size: 16px;
  color: var(--color-navy);
  background: var(--color-white);
}
/* textarea по умолчанию строчный элемент, и браузер оставляет под ним место
   под «хвосты» букв — лишние 6–8 пикселей, из-за которых низ карточки не
   сходился с её боковыми отступами. */
.order-field textarea { resize: vertical; min-height: 80px; display: block; }
/* Последнее поле карточки своего нижнего отступа не добавляет: иначе снизу
   получалось 18 + 32 пикселя против 32 по бокам, и низ выглядел провисшим. */
.order-card > .order-field:last-child { margin-bottom: 0; }
/* То же самое для строк контактов: под ними стоят ярлыки сохранённых
   получателей и контактов, но у гостя их нет — строка оказывается последней,
   и её отступ ложился поверх отступа карточки. Зазор до ярлыков возвращаем
   им самим, и только когда они есть (:not(:empty)). */
#order-contacts-row .order-field,
#order-customer-contacts-row .order-field { margin-bottom: 0; }
#order-saved-addresses:not(:empty),
#order-saved-contacts:not(:empty) { margin-top: 18px; }
.order-field input:focus, .order-field select:focus, .order-field textarea:focus { outline: none; border-color: var(--color-navy-light); }
/* Запертое поле — светлее общей серой заливки (#e9ebf3): в блоке документов
   таких полей сразу четыре подряд, и на общем фоне они читались как тяжёлая
   серая полоса. Оттенка хватает, чтобы отличить «сюда не печатают». */
.order-field input[readonly] { background: #f0f2f7; color: var(--color-text-muted); }
.order-field .hint { font-size: 12px; color: var(--color-text-muted); margin-top: 4px; }
.order-card p.hint { font-size: 13px; color: var(--color-text-muted); margin: 0; }
.order-card p.hint a { color: var(--color-accent); text-decoration: underline; }
.order-card p.hint a:hover { color: var(--color-accent-dark); }

/* Заполненное поле: без заливки, только рамка на тон темнее пустой (#c9d3e0
   против #e9ebf3). Голубую заливку убрали — с ней заполненная форма пестрила,
   а фокус (синяя рамка) и ошибка (красная) остаются заметны сами по себе.
   Фон не трогаем: у скопированного галочкой поля он серый от [readonly],
   и это единственный признак, что в нём не печатают. */
.order-field input.is-valid, .order-field select.is-valid, .order-field textarea.is-valid { border-color: #c9d3e0; }
/* Фокус важнее «поле заполнено»: правило заполненного стоит ниже, той же силы,
   и без повтора синяя рамка курсора им перебивалась. */
.order-field input:focus, .order-field select:focus, .order-field textarea:focus { border-color: var(--color-navy-light); }
/* Толщина рамки та же, что у обычного состояния поля (2px): при ошибке
   менялся только цвет, а рамка становилась тоньше — поле будто подпрыгивало
   и выглядело неаккуратно рядом с соседними. */
.order-field input.is-invalid, .order-field select.is-invalid, .order-field textarea.is-invalid {
  border: 2px solid #e53935 !important;
  background: var(--color-white);
}
/* Проверка доверенности на СВХ. Тон решает всё: зелёная — всё в порядке,
   жёлтая — надо что-то сделать до вывоза. Красной здесь нет намеренно: это не
   ошибка заполнения, заявку можно отправлять и так, а красный в этой форме
   означает «поле не заполнено». */
.order-poa { margin: 4px 0 18px; display: grid; gap: 8px; }
.order-poa__item {
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  line-height: 1.45;
}
.order-poa__item--ok { background: #e9f6ee; color: #1c5233; }
/* Жёлтая — «что-то не так, разберитесь»: срок не указан, платит не экспедитор.
   Красная — «в таком виде груз не выдадут»: доверенности нет или она
   просрочена. Разница по цвету нужна именно здесь: первое можно отложить,
   второе останавливает вывоз. */
.order-poa__item--warn { background: #fff4e2; color: #8a4b08; }
.order-poa__item--alert { background: #fdeceb; color: #a3241a; }

.field-error { display: none; color: #e53935; font-size: 13px; margin-top: 4px; }
.field-error.is-visible { display: block; }

/* "Контактное лицо" as a checkbox multiselect (logged-in /lk/ client with
   several saved contacts — see the fetch('/lk/recipient_api.php') call
   below) — same interaction as the admin CRM's client filters
   (.multiselect* in admin.css), restyled here to match this page's own
   .order-field inputs instead of the admin's compact filter-bar sizing. */
.multiselect { position: relative; }
.multiselect__toggle {
  box-sizing: border-box;
  min-height: 46px;
  width: 100%;
  padding: 10px 40px 10px 14px;
  border: 2px solid var(--color-bg-soft);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-navy);
  font-size: 16px;
  font-family: var(--font-main);
  text-align: left;
  cursor: pointer;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  position: relative;
}
.multiselect__toggle::after {
  content: "";
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 12px;
  height: 8px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1L6 6L11 1' stroke='%232c405b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
}
.multiselect__toggle.is-valid { border-color: #c9d3e0; }
.multiselect__toggle:focus { border-color: var(--color-navy-light); }
.multiselect__placeholder { color: var(--color-placeholder); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.multiselect__chips { display: flex; flex-wrap: wrap; gap: 4px; overflow: hidden; }
/* The picked contact renders as plain text — same size/weight/color as the
   ИНН field right above it — not a removable pill; to change it, reopen
   the list (click the toggle) or use "+ Указать другого получателя". */
.multiselect__selected-text {
  font-size: 16px;
  font-weight: 400;
  color: var(--color-navy);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.multiselect__panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  width: 100%;
  max-height: 260px;
  overflow-y: auto;
  background: var(--color-white);
  border: 1px solid var(--color-bg-soft);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card-hover);
  z-index: 50;
  box-sizing: border-box;
}
.multiselect__panel.is-open { display: block; }
/* Specificity needs to beat .order-field label (a class+tag selector) —
   this panel lives inside an .order-field, and without the extra
   .multiselect__panel ancestor class here that rule's display:block/bold
   text would otherwise win and collapse the checkbox+text layout. */
.multiselect__panel .multiselect__option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  font-size: 15px;
  font-weight: 400;
  color: var(--color-navy);
  cursor: pointer;
  border-bottom: 1px solid var(--color-bg-soft);
}
.multiselect__option:last-child { border-bottom: none; }
.multiselect__option:hover { background: var(--color-bg-soft); }
.multiselect__option.is-selected { background: var(--color-bg-soft); font-weight: 700; }
/* The "fill in manually" row at the end of the contact list — set off from
   the real contacts above it with a rule and accent color instead of a
   checkbox, since it isn't itself a selectable person. */
.multiselect__option--manual {
  border-top: 1px solid var(--color-bg-soft);
  color: var(--color-accent);
  font-weight: 700;
}
.multiselect__option--manual:hover { background: var(--color-bg-soft); }

.order-inline-link {
  display: inline-block;
  margin-top: 8px;
  background: none;
  border: none;
  padding: 0;
  color: var(--color-accent);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: underline;
}
.order-inline-link:hover { color: var(--color-accent-dark); }

/* Replaces a plain <select class="js-custom-select"> with a panel styled
   like the city-autocomplete dropdown above, instead of the OS-native list —
   sized to match both .calc-field and .order-field inputs so it drops
   into either form unchanged. */
.custom-select { position: relative; }
.custom-select__toggle {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 12px 40px 12px 14px;
  border: 2px solid var(--color-bg-soft);
  border-radius: var(--radius-sm);
  font-family: var(--font-main);
  /* Тот же кегль, что у полей ввода: список и поле часто стоят в одном ряду,
     и разница в пункт в паре читается. */
  font-size: 16px;
  color: var(--color-navy);
  background: var(--color-white);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  position: relative;
}
/* В калькуляторе селект стоит в одном ряду с полем города: у поля padding
   10px, у переключателя было 12px — и селект выходил на 48px против 44px.
   Разница в четыре пикселя бросается в глаза именно в паре. */
.calc-widget .custom-select__toggle { padding-top: 10px; padding-bottom: 10px; }

.custom-select__toggle::after {
  content: "";
  position: absolute;
  right: 14px;
  top: calc(50% - 3px);
  width: 12px;
  height: 8px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1L6 6L11 1' stroke='%232c405b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
}
.custom-select__toggle:focus { outline: none; border-color: var(--color-navy-light); }
.custom-select__toggle--placeholder { color: var(--color-placeholder); }
.custom-select__toggle.is-invalid { border: 2px solid #e53935 !important; }
.custom-select__toggle.is-valid { border-color: #c9d3e0; }
.custom-select__toggle:focus { border-color: var(--color-navy-light); }
.custom-select__panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-hover);
  max-height: 260px;
  overflow-y: auto;
  padding: 8px;
  z-index: 40;
}
.custom-select__panel.is-open { display: block; }
.custom-select__option {
  padding: 6px 12px;
  /* Тот же кегль, что у самого поля: иначе выбранное значение меняло бы
     размер при открытии списка. */
  font-size: 16px;
  /* Межстрочный интервал здесь свой, поменьше общего по сайту: в списке строки
     идут вплотную друг к другу, и общий расчёт на текст абзаца раздвигал
     пункты так, что в окно помещалось три штуки вместо шести. */
  line-height: 1.3;
  color: var(--color-navy);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
@media (max-width: 720px) {
  /* На телефоне по пункту попадают пальцем — строка не должна быть ниже
     сорока точек. */
  .custom-select__option { padding: 9px 12px; }
}
.custom-select__option:hover { background: var(--color-bg-soft); }
.custom-select__option.is-selected { background: var(--color-bg-soft); font-weight: 700; }
.custom-select__option.is-disabled { color: var(--color-text-muted); cursor: default; pointer-events: none; opacity: 0.5; }
.custom-select__option--placeholder { color: var(--color-placeholder); }
/* Пустой пункт ответом не является — это приглашение выбрать. Поэтому пометки
   выбранного он не получает: ни жирного начертания, ни серой заливки. Заливка
   к тому же съедала и без того светлый текст подсказки (#B5BABD на #e9ebf3 —
   почти не читается). На белом фоне он выглядит как placeholder в поле, чем и
   является. Наведение мышью подсвечивается как у всех — оно про курсор, а не
   про выбор. */
.custom-select__option--placeholder.is-selected { font-weight: 400; background: transparent; }
.custom-select__option--placeholder.is-selected:hover,
.custom-select__option--placeholder.is-highlighted { background: var(--color-bg-soft); }
.custom-select__search { padding: 4px 8px 8px; }
.custom-select__search input {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--color-bg-soft);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-size: 16px;
  font-family: var(--font-main);
  outline: none;
}
.custom-select__search input:focus { border-color: var(--color-navy-light); }
/* Вкладка калькулятора, форма которой ещё не готова: приглушена, с замком и
   пометкой «скоро». Выглядит как часть набора, но видно, что не нажимается. */
.calc-widget__tab--locked {
  /* Приглушаем не прозрачностью, а самими цветами. Прозрачность гасит тонкие
     буквы сильнее, чем сплошную рамку: при одном и том же значении цвета
     слово «скоро» выглядело светлее рамки, хотя по коду они совпадали. */
  cursor: default;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--color-white);
  border-color: #8b96a5;
  color: #8b96a5;
}
.calc-widget__tab--locked:hover { background: var(--color-white); color: #8b96a5; }
/* Пометка «скоро» на белой вкладке: прежний полупрозрачный белый фон на
   светлом стал невидимым. */
/* Метка сидит верхом на верхней границе плашки: ширины ряда не занимает, а
   слово «скоро» читается сразу, без наведения. Белая обводка отделяет её от
   рамки, иначе они сливаются в одну линию. */
.calc-widget__soon {
  position: absolute;
  top: -8px;
  right: 10px;
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .02em;
  line-height: 1.4;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  background: #eef1f5;
  border: 1px solid var(--color-white);
  /* Тот же цвет, что у рамки выбранной вкладки «Доставка с АВИА СВХ», —
     тёмно-синий фирменный. Запертая вкладка приглушена, а метка остаётся
     тёмной: она про срок, а не про недоступность. */
  color: var(--color-navy);
}
/* Прежнее правило, прятавшее пометку на узких экранах, больше не нужно:
   метка вынесена из строки и ширину вкладки не увеличивает. */

.order-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
/* Контактное лицо, телефон и почта — тремя равными колонками. Выравнивание по
   верху: у поля с ошибкой появляется подпись, и без этого соседние поля
   поднимались бы над ним ступенькой. */
.order-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: start; }
@media (max-width: 720px) {
  /* В столбик промежуток задаёт собственный отступ поля (18px) — иначе к нему
     прибавлялся ещё и зазор сетки, и поля расходились почти на 40px. */
  .order-grid-3 { grid-template-columns: 1fr; gap: 0; }
}

/* Блок «Грузополучатель»: подписи-пояснения под полем и галочка «тот же»
   рядом с полем, а не под ним — она относится к соседнему полю, и на
   отдельной строке эта связь пропадала. */
.order-hint { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--color-text-muted); }

/* Услуги в блоке «Грузополучатель» — списком галочек: их отмечают по
   нескольку, и выпадающий список с одним выбором заставлял бы оформлять
   заказ в три захода. */
/* Отступ от подписи до первой галочки: с 4px список прилипал к заголовку и
   читался как его продолжение. */
/* Две равные колонки: услуг много и подписи короткие, в один столбик список
   тянулся вниз, а справа оставалась пустая половина карточки. Выравнивание по
   верху — иначе строка с раскрытым списком количеств растягивала соседнюю. */
.order-services {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
  gap: 10px 24px;
  margin-top: 12px;
}
/* Осталась одна услуга (например, при самовывозе, когда доставка в выходной
   не предлагается) — отдаём ей всю ширину: в половине карточки её название
   переносилось на вторую строку, а справа пустовало полкарточки. */
.order-services--single { grid-template-columns: 1fr; }
/* На узких экранах половина карточки — это полторы сотни пикселей, названия
   услуг там ломались бы по слогам. Возвращаем один столбик. */
@media (max-width: 720px) {
  .order-services { grid-template-columns: 1fr; }
}
/* Список количеств у услуги с градациями: с отступом под галочкой, чтобы
   было видно, к какой именно услуге он относится. */
.order-service-item { display: flex; flex-direction: column; gap: 8px; }
.order-service-tier { padding-left: 30px; max-width: 420px; }
.order-service-tier .field-error { margin-top: 4px; }
/* Оформление то же, что у галочки «тот же» ниже в блоке: обычное начертание
   и такой же квадратик. Жирным набрана подпись поля (.order-field label), и
   названия услуг, будучи тоже label, наследовали её вес — девять жирных
   строк подряд читались как девять заголовков. */
/* Селектор с .order-field обязателен: правило .order-field label задаёт
   жирное начертание и по силе выше одного класса — без этого названия услуг
   оставались бы жирными, как подписи полей. */
.order-field .order-service-check {
  display: flex;
  align-items: flex-start;
  /* Просвет между квадратиком и названием — как у «Есть опасный груз» с его
     переключателем: вплотную текст читался тяжелее. */
  gap: 10px;
  cursor: pointer;
  /* Кегль и цвет — как у подписи «Есть опасный груз» рядом: это соседние
     строки одного блока, и разнобой в них был заметен. */
  font-size: 14px;
  font-weight: 400;
  line-height: 1.6;
  color: var(--color-text);
  margin-bottom: 0;
}
/* Квадратик рисуем сами — точно так же, как у «Цоколя» в окне выбора адреса:
   системный чекбокс в разных браузерах выглядит по-своему, а форма заказа
   должна быть одинаковой везде. Отмеченный — заливка #2D405A с белой
   галочкой. */
.order-field .order-service-check input {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin: 1px 0 0;
  border: 2px solid #d3d7e4;
  border-radius: 4px;
  background: var(--color-white);
  position: relative;
  flex: 0 0 auto;
  cursor: pointer;
}
.order-field .order-service-check input:checked {
  background: #2D405A;
  border-color: #2D405A;
}
.order-field .order-service-check input:checked::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 2px;
  width: 4px;
  height: 9px;
  border: solid var(--color-white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
/* Линия над блоком дополнительных услуг: отделяет их от веса, габаритов и
   отметки об опасном грузе — это разные вопросы к одному отправлению. */
.order-field--after-line {
  border-top: 1px solid var(--color-bg-soft);
  margin-top: 18px;
  padding-top: 18px;
}
.order-label-note { font-weight: 400; color: var(--color-text-muted); font-size: 13px; }

/* Подсказка под ярлыками получателей: почему адрес остался прежним. */
.lk-saved-addresses__hint { margin-top: 6px; font-size: 13px; color: var(--color-text-muted); }

/* Ярлыки получателей идут сразу под строкой «Контактное лицо / Телефон» —
   там уже есть отступ самой строки, и собственный сверху только раздваивал
   зазор. У «Моих контактов» в блоке заказчика он остаётся. */
#order-saved-addresses { margin-top: 0; }

/* Галочка «Выпуск есть» стоит под номером накладной, внутри его ячейки:
   отвечает на вопрос об этой же отправке, а не об условиях перевозки. */
.order-release-check { margin-top: 10px; }
/* Место для файлов появляется вместе с галочкой. Пунктир — тот же язык, что
   у «Указать габариты» и «+ Добавить место»: здесь можно что-то положить. */
/* Селектор с .order-field обязателен: правило `.order-field label` делает
   подписи блочными, жирными и с отступом снизу — зона от него получала
   лишние 6 точек под текстом и жирное начертание, хотя это не подпись поля,
   а место, куда кладут файлы. */
.order-field label.order-dropzone,
.order-dropzone {
  display: flex;
  /* Пока файлов нет — одна строка по центру. С файлами зона становится
     контейнером: шапка со скрепкой, плашки, подсказка снизу. */
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Высоту держит содержимое: сверху и снизу поровну. */
  padding: 22px 18px;
  margin-bottom: 0;
  border: 2px dashed var(--color-bg-soft);
  border-radius: var(--radius-sm);
  /* Заливка едва заметная — чтобы зона читалась как поверхность, на которую
     кладут файл, но не спорила с полями рядом. */
  background: rgba(44, 64, 91, 0.03);
  text-align: center;
  color: var(--color-text-muted);
  font-size: 15px;
  font-weight: 400;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.order-dropzone:hover, .order-dropzone.is-over { border-color: var(--color-navy-light); background: rgba(44, 64, 91, 0.06); }
/* Поле выбора прячем, но не через display:none: так по зоне работает клик
   (label), а клавиатура по-прежнему находит само поле. */
.order-dropzone input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.order-dropzone__link { color: var(--color-navy); text-decoration: underline; }

/* Содержимое зоны, когда файлы приложены: слева направо, по левому краю —
   иначе шапка и плашки «плавали» бы в центре, как одинокая подсказка. */
/* Селектор с .order-field — чтобы перебить выравнивание по центру из правила
   выше: у него специфичность больше одного класса. */
.order-field label.order-dropzone.has-files,
.order-dropzone.has-files { align-items: stretch; text-align: left; }
.order-dropzone__head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 700;
  color: var(--color-navy);
}
/* Скрепка одна на всё: она отвечает на вопрос «что-то приложено?», а не
   подписывает каждый файл. */
.order-attached__clip { flex: 0 0 auto; line-height: 0; }
.order-dropzone__chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* Пустой контейнер плашек прячем совсем: у зоны есть промежуток между
   строками, и пустая полоска добавляла его над текстом — сверху получалось
   на 10 точек больше, чем снизу. */
.order-dropzone:not(.has-files) .order-dropzone__chips { display: none; }
.order-dropzone.has-files .order-dropzone__text { font-size: 14px; }

.order-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 6px 8px 6px 12px;
  border: 1px solid var(--color-bg-soft);
  border-radius: 999px;
  background: var(--color-white);
  font-size: 14px;
  color: var(--color-navy);
}
/* Длинное имя сжимается многоточием: размер и крестик важнее хвоста имени. */
.order-chip__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.order-chip__size { flex: 0 0 auto; color: var(--color-text-muted); font-size: 13px; white-space: nowrap; }
.order-chip.is-bad { border-color: #e7bdb7; }
.order-chip.is-bad .order-chip__name, .order-chip.is-bad .order-chip__size { color: #b3261e; }
.order-chip__remove {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 50%;
  background: var(--color-bg-soft);
  color: var(--color-navy);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.order-chip__remove:hover { background: #f3ddda; color: #b3261e; }
/* Получатель внутри карточки «Услуга»: отделён линией от адреса и подъёма
   на этаж — это уже не «куда везём», а «кому отдать», хотя вопрос тот же. */
.order-recipient-fields {
  border-top: 1px solid var(--color-bg-soft);
  margin-top: 18px;
  padding-top: 18px;
}

/* MAWB, HAWB и номер заявки клиента — в одну строку. Ниже 700px три поля
   становятся слишком узкими для номера накладной, поэтому расходятся по
   строкам. */
/* Третья колонка шире: подпись «Ваш номер заявки необязательное» в равной
   трети не помещалась, уезжала на вторую строку — и поле под ней вставало
   ниже соседних, ломая ряд. */
/* Три равные колонки. Третья была шире остальных под длинную подпись «Ваш
   внутренний номер» — после переименования в «Ваш номер» запас не нужен. */
.order-awb-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.order-awb-row label { white-space: nowrap; }
@media (max-width: 700px) {
  .order-awb-row { grid-template-columns: 1fr; gap: 0; }
}
.order-same-row { display: flex; align-items: center; gap: 12px; --order-same-col: 232px; }
.order-same-row input[type="text"] { flex: 1; min-width: 0; }
/* Колонка под галочку фиксированной ширины: подписи разной длины, и без этого
   поля получались разной ширины — ступенькой. Ширину задаёт самая длинная
   подпись из всех («Экспедитор (Смарт Экспресс)», 229px вместе с квадратиком):
   подписи не переносятся, и колонка уже самой длинной из них всё равно не
   станет — поле рядом с ней просто оказалось бы у́же остальных. */
.order-same-row .order-same { flex: 0 0 var(--order-same-col); }
/* Две галочки у одного поля («Экспедитор» и «Совпадает с плательщиком»)
   встают колонкой в ту же ширину, что и одиночная. Без этого .order-field-options
   растягивался по высоте строки, и поле уезжало вниз, а галочки — в разные
   концы. Строку выравниваем по верху: колонка выше инпута. */
.order-same-row--stack { align-items: flex-start; }
.order-same-row .order-field-options { flex: 0 0 var(--order-same-col); margin-top: 0; gap: 6px; }
/* Внутри колонки основная ось — вертикаль, и flex-basis из правила выше
   растягивал каждую галочку в высоту на всю ширину колонки. Здесь размер по
   содержимому. Длинные подписи переносим по строкам: колонка одна на все поля
   блока, и подпись шире её утаскивала бы за собой ширину поля рядом. */
.order-same-row .order-field-options .order-same {
  flex: 0 0 auto;
  white-space: normal;
  align-items: flex-start;
}
.order-same-row .order-field-options .order-same input { margin-top: 2px; }
/* Подпись с названием компании вместо «Совпадает с…». Колонка под галочку
   фиксированной ширины, поэтому длинное название не переносим, а сжимаем с
   растворением к правому краю: форма от этого не едет, а полное название
   видно в подсказке при наведении. */
.order-same--named { align-items: center; }
.order-same--named > span { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.order-same__name { max-width: 100%; overflow: hidden; white-space: nowrap; }
/* Растворение, а не многоточие: у многоточия обрыв читается как часть
   названия, а мягкий край — как «здесь ещё есть текст». Включается только
   для тех названий, что не поместились (класс ставит скрипт). */
.order-same__name.is-cut {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent 100%);
}
/* Роль — мелкой серой припиской под названием: она нужна, когда у двух полей
   похожие компании, и не мешает, когда названия и так различимы. */
.order-same__role { font-size: 11px; line-height: 1.2; color: var(--color-text-muted); text-transform: lowercase; }

/* На телефоне подпись «Совпадает с плательщиком» вместе с полем в строку не
   помещается — от инпута оставалось бы около сотни пикселей. Опускаем галочку
   под поле: строка узкая, а подпись длинная, и укорачивать её значило бы
   снова прятать, с чем именно совпадение. */
@media (max-width: 560px) {
  .order-same-row { flex-wrap: wrap; }
  /* Поле лежит в обёртке с крестиком очистки — долю строки забирает она,
     а не сам инпут: правило по input перестало работать, и поле ужималось
     до сотни пикселей рядом с галочкой. */
  .order-same-row input[type="text"],
  .order-same-row .calc-input-wrap,
  .order-same-row .input-clear-wrap { flex: 1 0 100%; }
}
/* Оформление то же, что у галочек дополнительных услуг: одна форма на всю
   страницу заказа. Селектор с .order-field — правило .order-field label
   задаёт жирное начертание и по силе выше одного класса. */
.order-field label.order-same,
.order-same {
  display: flex;
  align-items: center;
  gap: 10px;
  white-space: nowrap;
  font-size: 14px;
  font-weight: 400;
  color: var(--color-text);
  cursor: pointer;
  margin-bottom: 0;
}
/* Общая галочка «те же» подписана длинной фразой — ей перенос нужен, иначе
   на телефоне строка уезжала за край. Короткие «Совпадает с…» по-прежнему
   держатся в одну строку. Квадратик прижимаем к верхней строке текста. */
/* Плашка «Мои контакты» идёт сразу за строкой полей, у которой снизу свой
   отступ 18px — вместе с её собственными 10px получалось 28px, и ярлыки
   отрывались от полей. Свой отступ убираем, хватает отступа строки. */
#order-saved-contacts { margin-top: 0; }
/* Опции под полем — колонкой, с общим отступом от самого поля. Раньше одна
   галочка стояла справа от поля, другая под ним, и пара читалась как два
   несвязанных элемента. */
.order-field-options { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
/* Селектор с .order-field — как у правила .order-field label.order-same выше:
   оно задаёт nowrap и по силе перебивало один класс. */
.order-field label.order-one-company,
.order-one-company { white-space: normal; align-items: flex-start; }
.order-one-company input { margin-top: 1px; }

.order-same input {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 2px solid #d3d7e4;
  border-radius: 4px;
  background: var(--color-white);
  position: relative;
  flex: 0 0 auto;
  cursor: pointer;
}
.order-same input:checked {
  background: #2D405A;
  border-color: #2D405A;
}
.order-same input:checked::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 2px;
  width: 4px;
  height: 9px;
  border: solid var(--color-white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
/* Пока копировать нечего, гасим строку целиком — так сразу видно, что
   галочка ждёт заполненного поля выше. Как только юр. лицо указано, строка
   возвращается в обычный цвет, тот же, что у названий услуг. */
.order-same.is-disabled { cursor: default; opacity: .45; }
.order-same.is-disabled input { cursor: default; }
/* Самовывоз: получателя на форме нет, и «Совпадает с получателем» прячется
   вместе с ним. Классом, а не inline-стилем — схлопывание одинаковых галочек
   переписывает им style.display и вернуло бы галочку на экран. */
/* Селектор длиннее обычного нарочно: display у галочки задаёт правило
   `.order-field label.order-same`, и более короткое сюда не пробивается. */
.order-same.is-pickup-hidden,
.order-field label.order-same.is-pickup-hidden { display: none; }
@media (max-width: 560px) {
  /* На узком экране поле и галочка в одну строку не помещаются: поле
     сжималось до неюзабельного. Переносим галочку под поле. */
  .order-same-row { flex-wrap: wrap; }
  .order-same-row input[type="text"] { flex: 1 1 100%; }
  /* MAWB и HAWB рядом на телефоне не помещаются: подпись «если применимо»
     переносилась на вторую строку и поле под ней становилось вдвое ниже
     соседнего. Ставим их друг под другом. */
  /* row-gap здесь по той же причине, что и у контактов: в столбик поля
     разделяет их собственный отступ, зазор сетки был бы вторым. */
  #order-consignee-card .order-grid-2 { grid-template-columns: 1fr; row-gap: 0; }
}
.order-piece {
  margin-bottom: 20px;
  position: relative;
}
/* Шапка блока «Груз»: заголовок слева, сводка по всем местам в правом углу. */
.order-cargo-head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.order-cargo-totals { display: flex; gap: 20px; font-size: 14px; color: var(--color-text-muted); }
.order-cargo-totals strong { color: var(--color-navy); font-size: 16px; }
/* Ссылка вместо трёх полей габаритов: пунктирная рамка, как у «+ Добавить», —
   это тоже кнопка, открывающая скрытую часть формы, а не поле. */
.order-dims-toggle {
  /* Во всю ширину колонки — ровно столько же, сколько занимают три поля
     габаритов. Иначе между короткой кнопкой и корзиной оставался провал в
     полторы сотни пикселей, а при раскрытии полей корзина прыгала на место. */
  display: flex;
  width: 100%;
  justify-content: center;
  align-items: center;
  gap: 8px;
  background: none;
  border: 2px dashed var(--color-bg-soft);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-family: var(--font-main);
  /* Тот же кегль и межстрочный, что у полей рядом: иначе кнопка получается
     на пару пикселей ниже и строка выглядит неровной. */
  font-size: 16px;
  line-height: 1.4;
  color: var(--color-navy);
  cursor: pointer;
  white-space: nowrap;
}
.order-dims-toggle:hover { border-color: var(--color-navy-light); }
/* Подпись над кнопкой габаритов — на месте подписей соседних полей, но
   зелёная и не жирная: это не название поля, а выгода. Гостю дописываем
   условие, вошедшему — за что скидка. */
/* Селектор с .order-field — правило .order-field label задаёт жирное
   начертание и серый цвет и по силе выше одного класса. */
/* Пока не пришёл ответ личного кабинета, подпись держим невидимой: в разметке
   лежат оба варианта, и гостевой успевал мелькнуть у вошедшего клиента.
   visibility, а не display: место под строку остаётся, и ничего не прыгает. */
.order-dims-label { visibility: hidden; }
body.order-auth-known .order-dims-label { visibility: visible; }
.order-field label.order-dims-label,
.order-dims-label {
  display: block;
  /* По центру колонки, над кнопкой: подписи полей слева, и общий левый край
     делал её похожей на ещё одну подпись. */
  text-align: center;
  font-size: 15px;
  font-weight: 400;
  color: #1f9254;
  margin-bottom: 6px;
  white-space: nowrap;
}
/* «если войти» — только гостю: вошедшему клиенту скидка начисляется сразу.
   Само слово — ссылка, открывающая окно входа (класс js-lk-cta): подчёркнута,
   цвет наследует от подписи, чтобы строка осталась одной мыслью. */
body.order-authed .order-dims-label__guest { display: none; }
.order-dims-label__link { color: inherit; text-decoration: underline; }
.order-dims-label__link:hover { color: var(--color-navy); }
/* Кнопка стоит в строке места и не должна вылезать за свою колонку, а колонка
   тем уже, чем уже экран. Поэтому подпись ужимается по шагам: сначала уходит
   слово «скидки», потом «Указать». На телефоне колонка снова во всю ширину —
   там подпись полная. */
.order-dims-toggle__short { display: none; }
/* Подпись и кнопка ужимаются по ширине колонки: сначала из подписи уходит
   пояснение («после авторизации» / «за габариты»), потом из кнопки слово
   «Указать». Обрезать подпись до «2%» нельзя: без слова «скидка» процент
   читается как надбавка к цене. */
.order-dims-toggle__short { display: none; }
/* Только тесная десктопная полоса: на телефоне колонка снова во всю ширину,
   и полная подпись там помещается. */
@media (min-width: 721px) and (max-width: 1339px) {
  .order-dims-label__word { display: none; }
}
@media (min-width: 721px) and (max-width: 1239px) {
  .order-dims-toggle__full { display: none; }
  .order-dims-toggle__short { display: inline; }
}
@media (max-width: 360px) {
  .order-dims-toggle__full { display: none; }
  .order-dims-toggle__short { display: inline; }
}


.order-piece__dims { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
/* Одно место — одна строка: вес, количество, три габарита и кнопки справа.
   align-items: end выравнивает всё по нижнему краю, так что степпер и кнопки
   стоят на одной линии с инпутами, а подписи над ними могут быть разной высоты. */
/* Ширины первых трёх колонок заданы в пикселях: они держат текст известной
   длины («Коробки/Ящики», степпер из двух кнопок), а вся оставшаяся ширина
   карточки уходит габаритам — так подписи и плейсхолдеры никогда не режутся. */
/* Колонка «Тип» на 6px шире прежних 122px: самый длинный пункт списка —
   подсказка «Выберите», ей нужно 78px под текст плюс 46px на поля со
   стрелкой. На 122px она обрезалась многоточием. */
/* Колонка «Вес» — 127px под подпись «Вес общий, кг *»: она не переносится
   (см. ниже) и на прежних 86px вылезала за свою ячейку, наезжая на заголовок
   «Габариты, см». Недостающее забираем у габаритов — три поля ужимаются
   поровну, потому что делят остаток строки. */
.order-piece__row { display: grid; grid-template-columns: 136px 118px 127px minmax(0, 1fr) auto; gap: 8px; align-items: end; }
.order-piece__row .order-field { margin-bottom: 0; }
.order-weight-label__short { display: none; }
/* Пять полей и кнопка живут в 696px карточки, поэтому боковые поля инпутов
   здесь уже базовых 14px — иначе плейсхолдер «Ширина» не помещается.
   Справа у селекта поле не трогаем: там лежит стрелка (::after, right: 14px). */
.order-piece__row input[type="text"] { padding-left: 10px; padding-right: 10px; }
/* Габаритам достаётся остаток ширины на три инпута — им поля ещё уже,
   иначе плейсхолдер «Ширина» (самый длинный) обрезается многоточием. */
.order-piece__dims input[type="text"] { padding-left: 8px; padding-right: 8px; }
/* Самая узкая десктопная полоса: там габаритам тесно и после этого, поэтому
   поля внутри них теряют по паре точек боковых полей — плейсхолдер «Ширина»
   важнее воздуха вокруг него. */
@media (min-width: 721px) and (max-width: 1339px) {
  .order-piece__dims input[type="text"] { padding-left: 6px; padding-right: 6px; }
  /* Там же короткая подпись веса — и колонка под неё прежней ширины, чтобы
     габариты не теряли ни точки. */
  .order-weight-label__full { display: none; }
  .order-weight-label__short { display: inline; }
  .order-piece__row { grid-template-columns: 136px 118px 86px minmax(0, 1fr) auto; }
}
.order-piece__row .custom-select__toggle { padding-left: 10px; padding-right: 36px; }
/* Подписи в один уровень: "Количество, шт" длиннее соседних и на узком
   десктопе переносилась бы, роняя свою ячейку ниже остальных. */
.order-piece__row .order-field > label { white-space: nowrap; }
/* Строка места выравнивается по нижнему краю, поэтому появившаяся ошибка
   поднимала своё поле выше соседних — «Тип» и «Вес» вставали ступенькой над
   «Кол-во». Подпись вешаем под полем отдельным слоем: она видна, а высоту
   строки не меняет. На телефоне строка разложена в три ряда, там подпись
   остаётся в потоке — иначе она легла бы на следующий ряд. */
@media (min-width: 721px) {
  .order-piece__row .order-field { position: relative; }
  .order-piece__row .field-error.is-visible { position: absolute; top: 100%; left: 0; white-space: nowrap; }
}
.order-piece__actions { display: flex; gap: 8px; }
/* Без рамки и фона: в строке и так шесть полей в рамках, седьмая коробочка
   вокруг иконки только шумит. Высота остаётся как у инпутов, чтобы иконка
   попадала ровно в их вертикальный центр (у ряда align-items: end). */
.order-piece__icon-btn {
  width: 32px;
  height: 47px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: color .2s ease;
}
.order-piece__remove:hover { color: var(--color-accent); }
/* Кнопка добавления — под списком мест, прижата влево (не на всю ширину). */
.order-add-piece {
  display: inline-block;
  background: none;
  border: 2px dashed var(--color-bg-soft);
  border-radius: var(--radius-md);
  padding: 12px 20px;
  color: var(--color-navy);
  font-family: var(--font-main);
  font-weight: 700;
  font-size: 16px;
  cursor: pointer;
}
.order-add-piece:hover { border-color: var(--color-navy-light); }
/* Тот же степпер, что у количества мест в форме заказа, — в калькуляторе на
   главной у веса и объёма. Селекторы перечислены вместе, чтобы вид совпадал
   и правился в одном месте. */
.order-piece-qty-stepper,
.calc-stepper { display: flex; align-items: stretch; border: 2px solid var(--color-bg-soft); border-radius: var(--radius-sm); overflow: hidden; }
/* У поля внутри степпера своя рамка не нужна — её рисует обёртка. */
.calc-field .calc-stepper input { border: none; border-radius: 0; }
.calc-field .calc-stepper input:focus { outline: none; }
/* Родные стрелки у number прячем: рядом свои, две пары выглядели бы ошибкой. */
.calc-stepper input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.calc-stepper input[type="number"]::-webkit-outer-spin-button,
.calc-stepper input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.calc-stepper__arrows { flex: 0 0 24px; display: flex; flex-direction: column; }
.calc-stepper__btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: var(--color-bg-soft);
  color: var(--color-navy);
  line-height: 1;
  cursor: pointer;
}
.calc-stepper__btn + .calc-stepper__btn { border-top: 1px solid var(--color-white); }
.calc-stepper__btn:hover { background: var(--color-navy-light); color: var(--color-white); }
/* Рамка степпера живёт на обёртке (у самого инпута border: none), поэтому
   состояние ошибки вешаем на неё, а не на .order-piece-qty. */
.order-piece-qty-stepper.is-invalid { border-color: #e53935; }
/* Заполненное «Кол-во» подсвечиваем как остальные поля формы. Фон кладём и на
   обёртку, и на сам инпут: у инпута свой белый фон, и без этого голубым стала
   бы только рамка. */
.order-piece-qty-stepper.is-valid { border-color: #c9d3e0; }
/* Кнопки не по бокам, а узкой колонкой справа, одна над другой — так
   степпер занимает 24px вместо двух кнопок по 44px. */
.order-piece-qty-arrows { flex: 0 0 24px; display: flex; flex-direction: column; }
.order-piece-qty-stepper .order-piece-qty-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: var(--color-bg-soft);
  color: var(--color-navy);
  line-height: 1;
  cursor: pointer;
}
/* Разделитель между стрелками — того же цвета, что рамка степпера. */
.order-piece-qty-arrows .order-piece-qty-btn + .order-piece-qty-btn { border-top: 1px solid var(--color-white); }
.order-piece-qty-stepper .order-piece-qty-btn:hover { background: var(--color-navy-light); color: var(--color-white); }
.order-piece-qty-stepper input.order-piece-qty {
  flex: 1;
  width: 100%;
  min-width: 0;
  border: none;
  border-radius: 0;
  padding: 12px 8px;
  text-align: center;
}
.order-piece-qty-stepper input.order-piece-qty:focus { outline: none; }

/* Кнопка «Добавить» и переключатель опасного груза — двумя колонками, теми же,
   что у списка услуг ниже: обе половины карточки заняты, и всё содержимое
   блока «Груз» стоит на одной сетке. На узких экранах — друг под другом, как
   и услуги: половина карточки там слишком мала. */
.order-cargo-row { display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: 10px 24px; }
@media (max-width: 720px) {
  .order-cargo-row { grid-template-columns: 1fr; }
}
/* Отступ сверху живёт на строке целиком: у переключателя он сдвигал бы его
   относительно кнопки-соседа. */
.order-cargo-row .order-toggle-row { margin-top: 0; }
/* Кнопка остаётся своей ширины: ячейка сетки растянула бы её на полколонки. */
.order-cargo-row .order-add-piece { margin-top: 0; justify-self: start; }
.order-toggle-row { display: flex; align-items: center; gap: 12px; margin-top: 20px; cursor: pointer; font-size: 14px; }
/* Тот же переключатель, но под полем «Куда», а не в карте: там он стоит между
   двумя блоками, здесь примыкает к своему полю — иначе читался бы как
   отдельный вопрос, не связанный с адресом. Кегль как у подписей полей.
   16px, а не 14: на телефоне подпись рядом с переключателем — обычный текст,
   и мельче остального в форме она выглядит второстепенной. */
/* inline-flex, а не flex: <label> шириной во весь блок ловил клик даже в
   пустоте справа от подписи, и переключатель срабатывал от нажатия по
   середине карточки. Теперь нажимается только сам тумблер и текст рядом. */
/* Размер не задаём — берётся общий для переключателей (14px из
   .order-toggle-row): «Подъём на этаж» и «Есть опасный груз» — один и тот же
   вид элемента, и разный кегль читался как разная важность. */
/* Подъём относится к адресу над ним — держим его поближе к полю «Куда», иначе
   читается как отдельный вопрос, не связанный с адресом. Поле «Куда» свой
   нижний отступ в этом случае отдаёт: 18 точек от него плюс отступ строки
   давали между ними просвет больше, чем между разными вопросами. */
.order-door-row { display: inline-flex; margin-top: 11px; margin-bottom: 4px; }
#order-address-field { margin-bottom: 4px; }
/* Самовывоз стоит сразу под «Откуда» и относится к нему: сверху прижат к полю,
   снизу отделён — дальше начинается другой вопрос, куда везти. */
.order-pickup-row { display: inline-flex; margin-top: 1px; margin-bottom: 13px; }
/* При самовывозе всё, что ниже (адрес, получатель), с формы убрано, и
   переключатель оказывается последним в карточке: свой отступ он тогда не
   добавляет — низ должен совпадать с боковыми отступами. */
.order-pickup-row.is-card-last { margin-bottom: 0; }
#order-door-fields { margin-top: 12px; }
/* Четвёртая колонка — комментарий водителю. Правило только для блока под
   полем «Куда»: в карте эта же строка остаётся на три колонки, там
   «Дополнительная информация» лежит отдельным полем ниже.
   Подъезд и этаж ужаты на 35% против равных долей (1fr → 0.65fr): в них
   стоит двузначное число, и вся освободившаяся ширина отдана комментарию —
   туда пишут фразу. */
#order-door-fields .order-map-floor-row { grid-template-columns: 0.65fr 0.65fr auto 2.7fr; }
.order-toggle {
  position: relative;
  width: 44px;
  height: 24px;
  flex-shrink: 0;
}
.order-toggle input { opacity: 0; width: 0; height: 0; }
.order-toggle__track {
  position: absolute; inset: 0;
  background: var(--color-bg-soft);
  border-radius: 999px;
  cursor: pointer;
  transition: background .2s ease;
}
.order-toggle__track::before {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 18px; height: 18px;
  background: var(--color-white);
  border-radius: 50%;
  transition: transform .2s ease;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
}
/* Включённый тумблер — тёмно-синий. Их на сайте два: «Есть опасный груз» в
   блоке «Груз» и «Доставить до двери» в модалке карты, и раскрашивать их
   по-разному незачем. Красный акцент оставлен кнопкам действия. */
.order-toggle input:checked + .order-toggle__track { background: #30405a; }
.order-toggle input:checked + .order-toggle__track::before { transform: translateX(20px); }

.order-info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--color-bg-soft);
  color: var(--color-text-muted);
  font-size: 12px;
  font-style: italic;
  font-weight: 700;
  cursor: pointer;
  position: relative;
}
.order-tooltip {
  display: none;
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  width: 320px;
  background: var(--color-navy);
  color: var(--color-white);
  font-style: normal;
  font-size: 13px;
  font-weight: 400;
  line-height: 1.5;
  padding: 16px;
  border-radius: var(--radius-sm);
  text-align: left;
  z-index: 50;
  box-shadow: var(--shadow-card-hover);
  /* Подпись «Габариты, см» в строке груза стоит с white-space: nowrap, чтобы
     не переносилась. Подсказка внутри неё наследовала это и вытягивалась в
     одну строку, обрезаясь по своей ширине — возвращаем перенос. */
  white-space: normal;
}
.order-info-icon.is-open .order-tooltip { display: block; }

.order-city-suggestions { position: relative; }
.order-checkbox-row { display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--color-text); margin-top: 16px; }
.order-checkbox-row input {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  margin: 0;
  border: 2px solid #d3d7e4;
  border-radius: 4px;
  background: var(--color-white);
  position: relative;
  cursor: pointer;
}
.order-checkbox-row input:checked {
  background: #2D405A;
  border-color: #2D405A;
}
.order-checkbox-row input:checked::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 2px;
  width: 4px;
  height: 9px;
  border: solid var(--color-white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.order-summary {
  background: var(--color-bg-soft);
  border-radius: var(--radius-md);
  padding: 24px;
  text-align: center;
  margin-bottom: 24px;
}
.order-summary__price { font-size: 32px; font-weight: 700; color: var(--color-navy); }
.order-summary__note { font-size: 13px; color: var(--color-text-muted); margin-top: 6px; }
.order-submit-hint { font-size: 15px; color: var(--color-text-muted); text-align: center; margin: 12px 0 0; }
#order-submit-btn { font-size: 19px; }

.order-success { text-align: center; padding: 60px 20px; }
.order-success h1 { margin-bottom: 16px; }
.order-success__lead { font-size: 18px; color: var(--color-text); max-width: 560px; margin: 0 auto 28px; }
/* Что будет дальше — списком по шагам: человек читает его один раз и уходит,
   поэтому важнее ясность, чем краткость. Нумерация слева, текст выровнен по
   левому краю: по центру список читается тяжело. */
.order-success__steps {
  max-width: 520px;
  margin: 0 auto 24px;
  padding-left: 22px;
  text-align: left;
  color: var(--color-text);
  line-height: 1.6;
}
.order-success__steps li { margin-bottom: 8px; }
.order-success__lead strong { white-space: nowrap; }
.order-success__hint { max-width: 520px; margin: 0 auto 32px; font-size: 14px; color: var(--color-text-muted); }
/* Номер заявки — единственное, что человеку понадобится от этой страницы
   потом, поэтому он вынут из текста в плашку: тот же светло-голубой, что у
   подсказок в расчёте, — сообщение выгодное, не тревожное. */
.order-success__number {
  max-width: 520px;
  margin: 0 auto 20px;
  padding: 16px 20px;
  background: #E8F0FD;
  border-radius: var(--radius-sm);
  text-align: center;
}
.order-success__number-label { display: block; font-size: 13px; color: var(--color-text-muted); }
/* Номер — кнопка копирования, но выглядит как текст: рамка и фон превратили
   бы её в ещё одну кнопку рядом с двумя настоящими внизу. Значок подсказывает,
   что на номер можно нажать. */
.order-success__number-value {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: none;
  background: none;
  padding: 2px 4px;
  cursor: pointer;
  font-family: inherit;
  font-size: 26px;
  font-weight: 800;
  color: var(--color-navy);
  line-height: 1.2;
  margin: 2px 0 6px;
  word-break: break-word;
  border-radius: 6px;
}
.order-success__number-value svg { flex-shrink: 0; color: var(--color-navy-light); }
.order-success__number-value:hover { background: rgba(255,255,255,.6); }
.order-success__number-value:hover svg { color: var(--color-navy); }
/* Подтверждение копирования — тем же зелёным, что скидка в расчёте: это
   сообщение об удачном действии, а не часть подписи. */
.order-success__number-note.is-copied { color: #177a3e; font-weight: 700; }
.order-success__number-note { display: block; font-size: 13px; color: var(--color-text); line-height: 1.45; }
/* Кегль на два пункта крупнее базовых 15px: на этом экране кнопки —
   единственное действие, и мельче остального текста они читались как
   второстепенные. */
.order-success__actions { display: flex; flex-wrap: wrap; justify-content: center; margin: 0 -9px; }
.order-success__actions .btn { margin: 9px; }
.order-success__actions .btn { font-size: 17px; }

@media (max-width: 720px) {
  .order-grid-2 { grid-template-columns: 1fr 1fr; }
  /* Контактное лицо и телефон — исключение из пары: у первого подпись длинная
     («кто встретит груз»), и вдвоём в строке на телефоне оба поля становятся
     уже, чем в них помещается имя. Ставим друг под другом. */
  /* В один столбец расстояние между полями задаёт их собственный отступ
     (18px), как у всех остальных полей формы. Зазор сетки здесь к нему
     прибавлялся, и над «Телефоном» получался двойной промежуток. */
  #order-contacts-row { grid-template-columns: 1fr; row-gap: 0; }
  .order-card { padding: 20px; }
  /* Пять инпутов и две кнопки в одну строку на телефон не влезают —
     раскладываем в три ряда: вес + количество, габариты, кнопки. */
  /* Раскладка места на телефоне: тип во всю ширину, под ним количество и вес
     пополам, ещё ниже габариты. Корзина не уезжает в отдельный ряд (он был
     почти пустой и отбивал кнопку «Добавить» от полей на полсотни пикселей),
     а стоит узкой третьей колонкой в одном ряду с габаритами — как на
     десктопе. Позиции заданы явно: при авторазмещении корзина сползала бы
     в следующий ряд. */
  .order-piece__row { grid-template-columns: 1fr 1fr 32px; }
  .order-piece__cell--type   { grid-column: 1 / -1; grid-row: 1; }
  .order-piece__cell--qty    { grid-column: 1; grid-row: 2; }
  /* «Кол-во» и «Вес» стоят в одном ряду, подписи у них одинаковой высоты —
     выравниваем по верху. Иначе ошибка под одним из полей поднимала его
     над соседним: ряд-то выровнен по нижнему краю. */
  .order-piece__cell--qty,
  .order-piece__cell--weight { align-self: start; }
  .order-piece__cell--weight { grid-column: 2 / -1; grid-row: 2; }
  .order-piece__cell--dims   { grid-column: 1 / 3; grid-row: 3; }
  .order-piece__actions      { grid-column: 3; grid-row: 3; justify-content: flex-end; }
  /* Три показателя в строку на телефоне не помещаются — переносим и убираем
     лишний воздух между ними. */
  .order-cargo-totals { flex-wrap: wrap; gap: 4px 16px; }
}

.order-address-row { display: flex; gap: 10px; align-items: flex-start; margin-top: 6px; }
.order-address-display {
  flex: 1;
  box-sizing: border-box;
  min-height: 47px;
  padding: 12px 14px;
  border: 2px solid var(--color-bg-soft);
  border-radius: var(--radius-sm);
  font-family: var(--font-main);
  /* Кегль и межстрочный — как у инпутов формы, иначе строка адреса даёт
     коробку другой высоты, чем соседние поля. */
  font-size: 16px;
  line-height: 1.4;
  color: var(--color-navy);
  background: var(--color-white);
  display: flex;
  align-items: center;
}
.order-address-display.is-valid { border-color: #c9d3e0; }
/* Поле ручного ввода адреса стоит на месте блока с готовым адресом и должно
   совпадать с ним по размеру: те же 47px, что у всех полей формы. */
.order-address-input-wrap { flex: 1; position: relative; min-width: 0; }
/* Отдельных стилей у поля нет намеренно: оно внутри .order-field, и общее
   правило делает его точно таким же, как «ИНН» и «Контактное лицо» —
   один кегль, одни отступы, одна высота. */

.order-address-display.is-invalid { border: 2px solid #e53935 !important; background: var(--color-white); }

/* Личный кабинет: сохранённые адреса клиента — see fetch('/lk/addresses_api.php')
   in the script below; only ever populated/shown for a logged-in /lk/ client. */
.lk-saved-addresses { margin-top: 10px; }
.lk-saved-addresses__label { font-size: 13px; color: var(--color-text-muted); margin-bottom: 6px; }
.lk-saved-addresses__list { display: flex; flex-wrap: wrap; gap: 8px; }
.lk-saved-addresses__item {
  border: 2px solid var(--color-bg-soft);
  background: var(--color-white);
  color: var(--color-navy);
  border-radius: var(--radius-pill);
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font-main);
  cursor: pointer;
}
.lk-saved-addresses__item:hover { border-color: var(--color-navy-light); }
.order-map-link {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  /* Высоту не фиксируем: те же вертикальные поля и кегль, что у инпутов,
     дают одинаковую коробку при любых метриках шрифта. */
  padding: 12px 16px;
  /* Белая с тёмной рамкой, а не залитая: на форме залитая кнопка должна быть
     одна — «Создать заказ». Карта лишь помогает заполнить одно поле, и тёмным
     пятном она перетягивала внимание на себя. Оформление то же, что у
     «Личного кабинета» в шапке. */
  border: 2px solid #2D405A;
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: #2D405A;
  font-family: var(--font-main);
  font-size: 16px;
  line-height: 1.4;
  cursor: pointer;
}
/* При наведении заливаем тёмным — привычная реакция для кнопки с рамкой. */
.order-map-link:hover { border-color: #2D405A; background: #2D405A; color: var(--color-white); }
.order-map-link svg { flex-shrink: 0; }
/* Все поля формы заказа — 47px (19px строки + 24px padding + 4px рамки), а
   блок адреса выпадал на 52px: он не input, а div, и наследовал общий
   line-height 1.6 (24px на строку). Кнопка рядом со своими 47px из базового
   правила выглядела ниже. Задаём межстрочный интервал явно — и блок, и кнопка
   встают в общий ряд. Ниже 560px строка становится столбиком, где блок растёт
   под многострочный адрес: там интервал не трогаем. */
@media (max-width: 560px) {
  .order-address-row { flex-direction: column; }
  /* Поле ввода адреса нужно и на телефоне: с калькулятора приезжает только
     город, и дописать улицу с домом человек должен здесь же. Раньше поле на
     узких экранах пряталось, и оставалась одна кнопка карты. */
  .order-address-input-wrap { width: 100%; }
  /* flex:1 only grows along the row's main axis — once the row stacks to a
     column that axis becomes vertical, so the address text box needs an
     explicit full width or it just shrinks to fit its own text. */
  .order-address-display { width: 100%; }
  .order-map-link { width: 100%; justify-content: center; }
}

/* Fullscreen map address picker */
/* Небольшое окно подтверждения (сейчас — очистка формы). Отдельно от
   .order-map-modal: та во весь экран и живёт своей жизнью, а здесь нужна
   коробка по центру с двумя кнопками. */
.order-confirm {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(20, 30, 48, 0.45);
}
.order-confirm[hidden] { display: none; }
.order-confirm__box {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: 0 18px 50px rgba(20, 30, 48, 0.25);
  padding: 26px 28px;
  max-width: 420px;
  width: 100%;
}
.order-confirm__title { font-size: 20px; font-weight: 700; color: var(--color-navy); margin-bottom: 10px; }
.order-confirm__text { font-size: 14px; line-height: 1.5; color: var(--color-text-muted); margin: 0 0 20px; }
/* Кнопки в строку, «Очистить» первой: подтверждение — то действие, за которым
   сюда пришли. На узком экране становятся друг под другом во всю ширину. */
.order-confirm__actions { display: flex; gap: 10px; flex-wrap: wrap; }
@media (max-width: 420px) {
  .order-confirm__actions { flex-direction: column; }
  .order-confirm__actions .btn { width: 100%; }
}

.order-map-modal { display: none; position: fixed; inset: 0; z-index: 1000; }
.order-map-modal.is-open { display: block; }
.order-map-modal__map { position: absolute; inset: 0; background: var(--color-bg-soft); }
.order-map-modal__close {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 20;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--color-white);
  padding: 12px 24px;
  font-family: var(--font-main);
  font-weight: 700;
  font-size: 14px;
  color: var(--color-navy);
  box-shadow: var(--shadow-card-hover);
  cursor: pointer;
}
.order-map-modal__close:hover { color: var(--color-accent); }
.order-map-modal__close-icon { display: none; font-size: 22px; line-height: 1; }
.order-map-modal__panel {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 420px;
  max-width: 92vw;
  background: var(--color-white);
  box-shadow: var(--shadow-card-hover);
  z-index: 15;
  padding: 32px;
  overflow-y: auto;
}
.order-map-modal__panel-close {
  position: absolute;
  top: 16px;
  right: 16px;
  border: none;
  background: none;
  font-size: 26px;
  line-height: 1;
  font-weight: 700;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 4px;
}
.order-map-modal__panel-close:hover { color: var(--color-navy); }
.order-map-step h2 { font-size: 22px; margin: 30px 0 12px; padding-right: 32px; }
#order-map-step-search h2 { font-size: 24.2px; }
#order-map-step-confirm h2 { font-size: 18px; margin-bottom: 16px; }
/* The driver-note field's own default .order-field bottom margin (18px)
   leaves more air above "Доставить сюда" than it needs. */
.order-map-step .order-field:has(#order-map-driver-note) { margin-bottom: 10px; }
#order-map-submit { font-size: 18px; }
#order-map-step-search p { font-size: 16.4px; }
/* Starts at one line and grows to a second as needed (see the "input"
   listeners in create-order/index.php that set an explicit inline height
   from scrollHeight) — max-height caps it at two lines, same footprint as
   before, just collapsed by default instead of always reserving the space. */
.order-field textarea.order-map-address-textarea {
  /* textarea is inline-block by default, which reserves extra space below
     it for descenders/line-height in the .calc-input-wrap's inline
     formatting context — block removes that, so the error message below
     sits the same distance away as on every other field on this page. */
  display: block;
  height: 50px;
  min-height: 0;
  max-height: 72px;
  overflow-y: auto;
  resize: none;
}
#order-map-driver-note { height: 50px; min-height: 0; max-height: 72px; overflow-y: auto; }
.order-map-step p { font-size: 14px; color: var(--color-text-muted); margin: 0 0 20px; }
/* Десктопная панель карты. На мобильных это нижняя шторка со своей плотной
   вёрсткой (см. блок max-width: 720px ниже) — её эти правила не касаются. */
@media (min-width: 721px) {
  /* Заголовки двух шагов сменяют друг друга на одном месте, но у них разный
     кегль (24.2px и 18px) при одинаковом margin-top, из-за чего базовая линия
     «Уточните адрес доставки» оказывалась на ~5px выше. Компенсируем разницу
     полуинтерлиньяжа, чтобы текст вставал ровно туда же. */
  #order-map-step-confirm h2 { margin-top: 36px; }
  /* Больше воздуха над «Дополнительная информация» — она шла почти вплотную
     к тумблеру «Доставить до двери». */
  .order-map-step .order-field:has(#order-map-driver-note) { margin-top: 22px; }
  /* Поле комментария рассчитано ровно на четыре строки: межстрочный интервал
     задаём явно (22px), тогда высота считается однозначно —
     4 × 22 + 24 паддинга + 4 рамки = 116px. Именно min-height, а не height:
     autoGrowTextarea() выставляет height инлайном из scrollHeight и любое
     значение отсюда затирает, а min-height ограничивает итоговую высоту
     поверх инлайнового стиля. Потолок роста — шесть строк. */
  #order-map-driver-note { box-sizing: border-box; line-height: 22px; min-height: 116px; max-height: 160px; }
}
/* Grid (not flex) specifically so the error can live in its own row,
   placed under Этаж+«Цоколь» only (not the full row width, so it doesn't
   start under Подъезд) — without disturbing row 1's own height/alignment.
   A flex row with align-items:flex-end doesn't have that isolation: putting
   the error inside one flex item made that item taller, which shoved the
   other items down to keep their bottoms aligned with it (an ugly "only
   part of the row moves" effect). Grid's row 2 is sized independently of
   row 1, so Подъезд/Этаж/«Цоколь» never move regardless of whether (or how
   many lines) the error is showing. */
.order-map-floor-wrap { margin-bottom: 18px; }
.order-map-floor-row { display: grid; grid-template-columns: 1fr 1fr auto; column-gap: 14px; align-items: end; }
/* Подъезд and Этаж are equal-width 1fr columns (identical on every screen
   size, since neither carries a fixed pixel width) and "Цоколь" is a
   fixed-content column right after them — together they fill the row's
   full width with no dead space. */
.order-map-floor-row .order-field { margin-bottom: 0; min-width: 0; }
.order-map-floor-row .field-error { grid-column: 2 / 4; }
.order-map-floor-row input[type="text"]:disabled { background: var(--color-bg-soft); color: var(--color-text-muted); }
/* The site-wide .is-invalid rule drops border-width from 2px to 1px, which
   — combined with align-items:flex-end above — nudges just this one input
   down by that 1px difference while Подъезд/«Цоколь» don't move, the same
   "part of the row shifts" problem this whole row was just fixed for.
   Keeping the border width constant (only the colour changes) avoids it. */
.order-map-floor-row input[type="text"].is-invalid { border-width: 2px !important; }
/* Aligned to the bottom of the inputs (padding-bottom matches their own
   vertical position), ignoring the "Этаж"/"Подъезд" label row above them.
   Size/color/font match .order-checkbox-row — the "site-wide one checkbox
   style" rule (see also admin.css). */
.order-map-basement-check {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 16px;
  color: var(--color-text);
  white-space: nowrap;
  padding-bottom: 12px;
  cursor: pointer;
  flex: 0 0 auto;
}
.order-map-basement-check input {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 2px solid #d3d7e4;
  border-radius: 4px;
  background: var(--color-white);
  position: relative;
  cursor: pointer;
  flex: 0 0 auto;
}
.order-map-basement-check input:checked {
  background: #2D405A;
  border-color: #2D405A;
}
.order-map-basement-check input:checked::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 2px;
  width: 4px;
  height: 9px;
  border: solid var(--color-white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
/* Greys out the "Цоколь" word itself to match the greyed-out checkbox,
   instead of leaving it looking clickable while the control underneath
   isn't. */
.order-map-basement-check:has(input:disabled) { cursor: not-allowed; }
.order-map-basement-check:has(input:disabled) span { color: var(--color-text-muted); }
/* A native checkbox's own OS-drawn box ignores background-color entirely
   (it stays white regardless), so disabling it alone never actually looked
   grey — appearance:none lets our own background/border take over. It's
   only ever unchecked while disabled (floor disables this checkbox, and
   that only happens once "Цоколь" is off), so there's no checked-state
   checkmark to reproduce here. */
.order-map-basement-check input:disabled {
  cursor: not-allowed;
  -webkit-appearance: none;
  appearance: none;
  background: var(--color-bg-soft);
  border: 2px solid var(--color-bg-soft);
  border-radius: 4px;
}

/* Caption plate next to our custom map pin icon (see getMapPinLayout() in
   create-order/index.php) — same treatment as before: opaque, brand font,
   a touch larger, subtle shadow instead of Yandex's translucent default. */
.order-map-pin-caption {
  background: var(--color-white);
  font-family: var(--font-main);
  font-size: 16px;
  font-weight: 600;
  color: var(--color-navy);
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card);
  /* A full address easily runs off-screen as one line — pre-line renders
     the explicit \n between city/street (see placePinAndCenterAt) as a real
     break, while still wrapping either half further on its own if it's
     still too long by itself. */
  white-space: pre-line;
  text-align: center;
  /* Its containing block (the pin's own wrapper div) is width:0, which
     makes plain width:auto shrink-to-fit collapse to a near-zero width and
     wrap every couple of words — max-content sizes from the text itself
     instead, still capped by max-width for genuinely long addresses. */
  width: max-content;
  max-width: 260px;
  line-height: 1.3;
}

/* On phones the desktop's full-height 420px sidebar buries almost the whole
   map. Instead: the search step becomes a compact bar pinned to the top
   (leaving most of the screen as map), and the confirm step becomes a
   bottom sheet — order-map-modal__panel--confirm is toggled by
   showMapStep() in create-order/index.php. */
@media (max-width: 720px) {
  .order-map-modal__panel {
    left: 0;
    right: 0;
    bottom: auto;
    width: auto;
    max-width: none;
    max-height: 45vh;
    padding: 16px 20px;
    border-radius: 0 0 16px 16px;
    /* The search step's own address dropdown (.calc-city-suggestions) is
       taller than this compact top bar and is meant to float over the map
       below it — the inherited overflow-y:auto (desktop's full-height
       sidebar needs it) was instead clipping the dropdown to this bar's
       ~45vh, silently hiding it. The confirm step overrides this back to
       auto below, since that form can genuinely get tall enough to scroll. */
    overflow: visible;
  }
  .order-map-modal__panel--confirm {
    top: auto;
    bottom: 0;
    max-height: 78vh;
    border-radius: 16px 16px 0 0;
    overflow-y: auto;
  }
  .order-map-step h2 { margin: 4px 0 6px; padding-right: 34px; }
  #order-map-step-confirm h2 { margin-bottom: 10px; }
  #order-map-step-search h2 { font-size: 19px; }
  #order-map-step-search p { font-size: 14px; margin: 0 0 12px; }
  /* Cuts the gap below the search field roughly in half so the map's own
     zoom +/- control (top-left, just under the panel) isn't hidden behind
     it. */
  #order-map-step-search .order-field { margin-bottom: 8px; }
  /* Этаж/Офис lose their label row on mobile — the placeholder (swapped to
     the field name itself, see the JS) carries the meaning instead, saving
     the label line's height. */
  .order-field label.order-map-field-label { display: none; }
  /* Подъезд/Этаж/«Цоколь» must stay on one line even on the narrowest
     phones (320px) — a tighter gap than desktop, but the checkbox itself
     stays the same size as everywhere else on the site. */
  .order-map-floor-row { column-gap: 8px; }
  /* На телефоне комментарий в тот же ряд не влезает — фраза в колонке
     шириной с номер подъезда нечитаема. Уводим его на свою строку во всю
     ширину, а тройку номеров оставляем как была. */
  #order-door-fields .order-map-floor-row { grid-template-columns: 1fr 1fr auto; }
  #order-door-fields .order-door-note { grid-column: 1 / -1; margin-top: 10px; }
  /* Match the confirm sheet's own "×" (.order-map-modal__panel-close)
     exactly, so the two look like the same control. */
  .order-map-modal__close {
    /* Nudged up from the panel's own 16px edge — at this icon's font-size
       the "×" glyph's visual centre otherwise sits noticeably below the
       "Куда доставить?" heading's centre instead of level with it. */
    top: 6px;
    right: 16px;
    width: auto;
    height: auto;
    padding: 4px;
    background: none;
    box-shadow: none;
    color: var(--color-text-muted);
    font-weight: 700;
  }
  .order-map-modal__close:hover { color: var(--color-navy); }
  .order-map-modal__close-text { display: none; }
  .order-map-modal__close-icon { display: inline-block; font-size: 34px; }
  /* Same nudge for the confirm sheet's own "×" (smaller font-size than the
     one above, so it needs a smaller correction to level with "Уточните
     адрес доставки"). */
  .order-map-modal__panel-close { top: 14px; }
}

/* ===== Страница заказа: три колонки ===== */
/* Слева чек-лист заполнения, по центру форма, справа расчёт. Боковые колонки
   липкие: расчёт и прогресс должны оставаться на виду при прокрутке длинной
   формы — ради этого страница и стала трёхколоночной. */
.order-layout { display: grid; grid-template-columns: 190px minmax(0, 1fr) 300px; gap: 20px; align-items: start; }
/* Шапка сайта тоже липкая (position: sticky, высота --header-height),
   поэтому отсчитываем прилипание от её нижнего края — иначе верх
   чек-листа и расчёта уезжает под шапку и не виден. */
.order-side { position: sticky; top: calc(var(--header-height) + 20px); }
/* Своей прокрутки у карточки с расчётом нет: два ползунка на экране (страницы
   и карточки) сбивают с толку. Липнет она всегда верхом — переключать способ
   в зависимости от высоты пробовали, и карточка от этого прыгала. Вместо
   этого держим её низкой: всё, без чего расчёт понятен, вынесено наружу. */
.order-main { min-width: 0; }

/* Чек-лист виден и гостю, и вошедшему клиенту: он говорит, сколько осталось
   заполнить, а это одинаково полезно всем. Прячется он только вместе со всей
   левой колонкой — ниже 1200px, где раскладка становится одноколоночной
   (см. .order-side--steps). Порог 1200px: раньше был 1281px, но строка груза
   стала уже (габариты за ссылкой), и три колонки помещаются раньше. */
.order-steps {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 18px 16px;
  /* Та же отбивка сверху, что у блока со скидкой: боковые карточки набраны
     одинаково. Тёмно-синяя, а не красная: красный на этой странице занят
     кнопкой «Создать счёт» и подсветкой ошибок, и третьим смыслом —
     «просто украшение» — эти два размывались. */
  border-top: 4px solid var(--color-navy-pale);
}
/* Тот же кегль и насыщенность, что у «Ваш заказ» в правой колонке. */
.order-steps__title { font-size: 17px; font-weight: 800; color: var(--color-navy); line-height: 1.25; margin-bottom: 10px; }
/* 14px, а не общие 15px: в колонке 190px «Выбор услуги» иначе переносится
   на две строки и ломает ровный столбик пунктов. */
/* Кружок держим у первой строки подписи, а не по центру пункта: «Документы и
   оплата» переносится на две строки, и по центру галочка оказывалась между
   ними. Однострочные пункты от этого не меняются — высота строки та же. */
.order-step {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14px;
  color: var(--color-text-muted);
  padding: 7px 0;
  /* Пункт — ссылка на свою карточку: подчёркивания не нужно, но курсор и
     подсветка при наведении говорят, что по нему можно кликнуть. */
  text-decoration: none;
  cursor: pointer;
}
.order-step:hover { color: var(--color-navy); }
.order-step:hover .order-step__check { color: var(--color-navy-light); }
/* Прокрутка ведёт к карточке, а не под липкую шапку: отступ равен её высоте
   плюс воздух. */
/* Перечень ошибок сервера над формой: рамка акцентным цветом, строки —
   ссылки к своим полям. */
.order-server-errors { border: 2px solid var(--color-accent); }
.order-server-errors__title { margin: 0 0 10px; font-weight: 700; color: var(--color-navy); }
.order-server-errors__item { margin: 0 0 8px; color: var(--color-accent-dark); }
.order-server-errors__item a { color: inherit; }
.order-server-errors__item:last-child { margin-bottom: 0; }

.order-card { scroll-margin-top: calc(var(--header-height) + 20px); }
/* Кружок рисует сама иконка (обводкой), подложки под ней нет: незаполненный
   пункт — пустой контур, заполненный — тот же контур с галкой внутри. */
.order-step__check {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  color: #c9cede;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color .2s ease;
}
/* Галка появляется только у заполненного пункта — иначе бледная галка в сером
   кружке читается как «уже сделано, но неактивно». */
.order-step:not(.is-done) .order-step__tick { display: none; }
/* Заполненный пункт отличается цветом текста и зелёной галочкой; жирность
   не добавляем — иначе список «прыгает» по мере заполнения формы. */
.order-step.is-done { color: var(--color-navy); }
.order-step.is-done .order-step__check { color: #1c9a5e; }

.order-promo {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 20px;
  border-top: 4px solid var(--color-navy-pale);
}
/* Тот же промежуток, что между карточками формы (24px): блоки левой колонки
   и карточки посередине идут одной сеткой. Чек-лист теперь показывают всем,
   поэтому условие «только вошедшему» больше не нужно. */
.order-promo { margin-top: 24px; }
/* На телефоне блок не показываем. Скидка вошедшему всё равно посчитается, а
   на узком экране это лишний экран прокрутки между формой и расчётом; про
   вход там же говорит плашка «Авторизуйтесь — и получите скидку» под суммой.
   720px — та же граница, на которой на сайте схлопывается всё остальное. */
@media (max-width: 720px) {
  .order-promo { display: none !important; }
}
.order-promo__title { font-size: 17px; font-weight: 800; color: var(--color-navy); margin-bottom: 8px; }
/* На пункт крупнее прочих поясняющих строк: это единственный текст в блоке,
   и мелким он терялся под заголовком со скидкой. */
.order-promo__text { font-size: 14px; color: var(--color-text-muted); margin: 0 0 14px; line-height: 1.5; }
/* Выглядит как кнопка «Личный кабинет» в шапке: белый фон, тёмно-синяя рамка
   2px, обычное (не жирное) начертание — только без иконки человечка. */
.order-promo__btn {
  background: var(--color-white);
  border-color: #2f405b;
  color: #2f405b;
  font-weight: 400;
  font-size: 16px;
  /* Те же вертикальные поля, что у кнопки «Личный кабинет» в шапке
     (.site-header__actions .btn) — базовые 14px делают её заметно выше. */
  padding: 8px 16px;
}
.order-promo__btn:hover { background: #2f405b; color: var(--color-white); }

.order-calc {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 22px;
  border-top: 4px solid var(--color-navy-pale);
}
/* Тот же кегль и насыщенность, что у заголовка блока со скидкой
   (.order-promo__title) — боковые колонки набраны единообразно. */
.order-calc__title { font-size: 17px; font-weight: 800; color: var(--color-navy); line-height: 1.25; }
.order-calc__contract { font-size: 13px; color: var(--color-text-muted); margin-top: 6px; }
.order-calc__contract a { color: var(--color-accent); text-decoration: underline; }
.order-calc__route { margin: 18px 0; }
/* Плечо маршрута: маркер слева, подпись и значение справа. */
.order-calc__leg { display: flex; gap: 10px; position: relative; padding-bottom: 14px; }
.order-calc__leg:last-child { padding-bottom: 0; }
/* Линия тянется от маркера до низа плеча, то есть до маркера следующего —
   поэтому она не зависит от того, на сколько строк перенёсся адрес. */
.order-calc__leg:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 16px;
  bottom: 2px;
  width: 2px;
  background: var(--color-bg-soft);
}
/* Наконечник на конце линии — чтобы блок читался как направление «откуда
   куда», а не как два пункта, соединённых чертой. Уголок из двух границ,
   повёрнутый на 45°: его вершина приходится ровно на низ линии. */
.order-calc__leg:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 0;
  bottom: 2px;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--color-bg-soft);
  border-bottom: 2px solid var(--color-bg-soft);
  transform: rotate(45deg);
}
.order-calc__marker {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
  margin-top: 5px;
  border-radius: 50%;
  border: 2px solid var(--color-navy-light);
  background: var(--color-white);
}
/* Точка назначения залита — так видно, где маршрут заканчивается. */
.order-calc__marker--to { border-color: var(--color-navy); background: var(--color-navy); }
.order-calc__leg-body { min-width: 0; }
.order-calc__leg-label { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--color-text-muted); margin-bottom: 1px; }
.order-calc__point { font-size: 14px; line-height: 1.4; color: var(--color-navy); }
.order-calc__point.is-empty { color: var(--color-text-muted); }
/* Вес и расстояние: параметры заявки под маршрутом. Отступ между ними —
   margin, а не gap: gap не понимает рендерер, которым снимаются скриншоты
   вёрстки, и в отчётах строка слипалась. */
.order-calc__params { font-size: 13px; color: var(--color-text-muted); margin: -4px 0 14px; }
.order-calc__params > span { margin-right: 16px; white-space: nowrap; }
.order-calc__params b { color: var(--color-navy); font-weight: 700; }
/* Значения ещё нет — тем же приглушённым, что «Не выбрано» у адреса:
   это не результат расчёта, а незаполненное поле. */
.order-calc__params b.is-empty { color: var(--color-text-muted); font-weight: 400; }

.order-calc__rows { padding-top: 4px; }
/* Строка расшифровки: слева название, справа сумма. Названия компонентов
   бывают длинными («Экспедирование на Москва Карго/Шер. Карго») и переносятся,
   поэтому выравниваем по первой строке, а не по центру. */
.order-calc__item { display: flex; align-items: baseline; padding: 6px 0; font-size: 13px; color: var(--color-text-muted); }
.order-calc__item-name { line-height: 1.35; margin-right: 8px; }
.order-calc__item-price { margin-left: auto; font-size: 14px; font-weight: 600; color: var(--color-navy); white-space: nowrap; }
/* Расшифровка цены — единой группой на нейтральной подложке. Серая, а не
   голубая: голубым в этой же панели помечена плашка «Авторизуйтесь», а это
   сообщение, а не группа строк, и путать их нельзя.
   На подложке лежит вся расшифровка, включая доставку: доставка — такая же
   услуга, как экспедирование или подъём, и выделять её белым не за что.
   Подложка отделяет не услуги от доставки, а расчёт от итога. */
.order-calc__breakdown { background: #f4f5f8; border-radius: 8px; padding: 4px 10px; margin: 0 -10px; }
.order-calc__breakdown .order-calc__item { color: var(--color-text); }
.order-calc__row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 14px; color: var(--color-text-muted); padding: 7px 0; }
.order-calc__row strong { color: var(--color-navy); font-size: 15px; white-space: nowrap; }
.order-calc__percent { color: var(--color-navy); font-weight: 700; }
/* Карточка расчёта прокручивается внутри себя (max-height выше), поэтому всё,
   что вылезает за её границы, обрезается: подсказка шириной 320px в карточке
   на 300px не помещалась ни по ширине, ни вверх. Здесь раскрываем её внутрь —
   вниз и по ширине строки. Для этого снимаем позиционирование со значка,
   чтобы точкой отсчёта стала строка целиком, а не сам значок шириной 18px. */
/* Выбор услуги — кнопками, как в калькуляторе на главной: все три варианта
   видно сразу, без раскрытия списка. Палитра та же, что у кнопок калькулятора,
   размер — под ширину формы. */
.order-service-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  /* Место под метку «скоро»: она сидит верхом на верхней границе плашки, и без
     запаса её срезал бы край блока. */
  padding-top: 7px;
}
/* Невыбранная вкладка — белая с тёмной рамкой, как кнопка «Личный кабинет»
   в шапке: тёмная заливка читалась как нажатая, и рядом с действительно
   выбранной вкладкой было непонятно, какая из них активна. */
.order-service-tab {
  position: relative;
  /* Треть ряда на каждую — кнопки одинаковой длины, пока названия помещаются;
     см. то же правило у вкладок калькулятора на главной. */
  flex: 1 1 calc(33.333% - 8px);
  padding: 11px 10px;
  border: 2px solid var(--color-navy);
  border-radius: var(--radius-pill);
  background: var(--color-white);
  color: var(--color-navy);
  font-family: inherit;
  font-weight: 600;
  font-size: 15px;
  line-height: 1.2;
  white-space: nowrap;
  text-align: center;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.order-service-tab:hover { background: var(--color-navy); color: var(--color-white); }
/* Выбранная вкладка — голубая заливка с тёмной рамкой (вариант B). Рамку
   оставляем ту же, что у невыбранных: без неё светлая заливка читалась как
   «недоступна». */
.order-service-tab.is-active {
  background: #E8F0FD;
  border-color: var(--color-navy);
  color: var(--color-navy);
  cursor: default;
}
.order-service-tab.is-active:hover { background: #E8F0FD; color: var(--color-navy); }

/* Вкладка, форма которой ещё не готова: та же плашка, но приглушённая и с
   пометкой «скоро». Оформлена как в калькуляторе на главной, чтобы человек,
   пришедший оттуда, увидел ровно то же самое. */
.order-service-tab--locked {
  /* Как в калькуляторе на главной: гасим цвета, а не прозрачность. */
  cursor: default;
  border-color: #8b96a5;
  color: #8b96a5;
}
.order-service-tab--locked:hover { background: var(--color-white); color: #8b96a5; }
/* Метка сидит верхом на верхней границе плашки — ширины ряда не занимает, а
   слово читается сразу. Та же, что в калькуляторе на главной: человек приходит
   оттуда и должен увидеть ровно то же самое. */
.order-service-tab__soon {
  position: absolute;
  top: -8px;
  right: 12px;
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .02em;
  line-height: 1.4;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  background: #eef1f5;
  border: 1px solid var(--color-white);
  /* Тот же цвет, что у рамки выбранной вкладки «Доставка с АВИА СВХ», —
     тёмно-синий фирменный. Запертая вкладка приглушена, а метка остаётся
     тёмной: она про срок, а не про недоступность. */
  color: var(--color-navy);
}
/* Прежнее правило, прятавшее пометку на узком экране, больше не нужно: метка
   вынесена из строки и ширину вкладки не увеличивает. */

/* Запертое поле «Откуда»: выглядит неактивным, но остаётся кликабельным —
   по клику форма объясняет, что сперва нужна услуга. Настоящий disabled
   событий не шлёт, и сказать было бы нечем. */
.order-field.is-locked .custom-select__toggle,
.order-field.is-locked select {
  background: #f3f4f8;
  border-color: #e4e6ef;
  color: var(--color-placeholder);
  cursor: not-allowed;
}
.order-calc__row { position: relative; }
.order-calc .order-info-icon { position: static; }
.order-calc .order-tooltip {
  width: auto;
  left: 0;
  right: 0;
  transform: none;
  bottom: auto;
  top: calc(100% + 8px);
}
/* Пометка «(объёмный)» у веса — приглушённая, это уточнение, а не значение. */
.order-calc__weight-kind { font-size: 12px; }
/* Скидка — единственная строка расчёта, которая клиенту в плюс, поэтому её
   красим, а не оставляем в общем ряду: среди одинаковых строк её не замечали.
   Зелёный, а не фирменный красный: красным на этой странице помечены ошибки
   полей и сводка «не заполнено N полей», и выгода не должна выглядеть так же.
   Оттенок притушен до #177a3e — светлее он не набирал контраст 4.5:1 на белом
   фоне карточки.
   Зелёного бейджа у процента здесь больше нет: после того как у подключённых
   услуг появилась своя подложка, третье цветное пятно на карточке шириной
   300px превращало расчёт в пестроту. Цвет несёт смысл, подложка — группировку,
   и смешивать их в одной строке незачем. */
.order-calc__row--discount span,
.order-calc__row--discount strong { color: #177a3e; }
/* Подсказка внутри строки — тоже span, и зелёный доставался ей по наследству:
   текст на тёмно-синей плашке становился почти нечитаемым. Возвращаем белый. */
.order-calc__row--discount .order-tooltip { color: var(--color-white); }
.order-calc__row--discount .order-calc__percent { color: #177a3e; font-weight: 700; }
/* Итог заявки: скидка, НДС и сумма. Отделены чертой от расшифровки — это не
   позиции заказа, а свойства итоговой суммы, и стоять они должны при ней.
   Черта здесь, а не у самой строки суммы: иначе НДС остаётся по ту сторону,
   впритык к группе услуг, и читается как ещё одна услуга. */
.order-calc__totals { border-top: 1px solid var(--color-bg-soft); margin-top: 12px; padding-top: 6px; }
.order-calc__row--total { margin-top: 2px; padding-top: 4px; }
/* Подпись итога — того же кегля, что и сама сумма: это одна строка, а не
   заголовок с числом при нём. */
.order-calc__row--total span { font-size: 22px; color: var(--color-navy); font-weight: 700; }
.order-calc__row--total strong { font-size: 22px; }
/* Сколько гость теряет, не войдя в кабинет: тот же светло-голубой, которым на
   сайте помечено «заполнено верно», — сообщение выгодное, не тревожное. */
.order-calc__lost { background: #E8F0FD; border-radius: var(--radius-lg); padding: 14px 16px; font-size: 13px; color: var(--color-navy); line-height: 1.45; margin: 14px 0 0; }
/* Первое слово плашки — ссылка на окно входа: за скидкой не нужно никуда
   уходить со страницы заказа. Красим акцентным, чтобы её было видно как
   действие, а не как часть текста. */
.order-calc__lost-link { color: var(--color-accent); text-decoration: underline; }
.order-calc__lost-link:hover { color: var(--color-accent-dark); }
.order-calc #order-submit-btn { margin-top: 16px; font-size: 19px; }
/* Сводка «не заполнено N полей» под кнопкой отправки и в нижней панели:
   красным, как ошибки под полями, — это та же ошибка, только собранная. */
.order-calc__errors { margin: 10px 0 0; font-size: 13px; color: #e53935; text-align: center; }
.order-sticky-bar__errors { margin: 0; font-size: 12px; color: #e53935; flex: 1 0 100%; text-align: center; }

.order-calc__note { font-size: 13px; color: var(--color-text-muted); line-height: 1.5; margin: 12px 0 0; }

/* Ниже 1280px центральной колонке уже не хватает ширины на строку места в
   блоке «Груз» (ей нужно ~655px внутри карточки, а колонки съедают 530px):
   раскладываем в один столбец — чек-лист наверх строкой, расчёт под форму,
   где он и нужен, прямо перед отправкой. */
@media (max-width: 1199px) {
  .order-form { max-width: 760px; }
  .order-layout { grid-template-columns: 1fr; }
  .order-side { position: static; }
  /* Левая колонка целиком — принадлежность широкой раскладки: и чек-лист, и
     блок со скидкой. В одну колонку они вклинивались между шапкой и формой,
     отодвигая вниз то, ради чего страница открыта. Роль «покажи, сколько
     осталось заполнить» здесь берёт на себя нижняя панель с суммой.
     Баннер со скидкой при этом не пропадает: скрипт переносит его в колонку
     расчёта, под карточку с суммой (см. placePromo). */
  .order-side--steps { display: none; }
  /* В одну строку три названия не помещаются — отдаём каждой кнопке свою. */
  .order-service-tab { flex: 1 1 100%; }
  /* Карточка расчёта в одноколоночной раскладке уже не приклеена, а стоит в
     потоке — собственная прокрутка ей больше не нужна и мешала бы: кнопка
     отправки внутри неё могла оказаться за пределами видимой части карточки. */
}

/* Панель с итогом и кнопкой отправки, прижатая к низу экрана в узкой
   раскладке. Появляется только когда настоящая кнопка «Создать заказ» ушла
   из кадра (класс is-visible ставит IntersectionObserver на странице). */
.order-sticky-bar { display: none; }
@media (max-width: 1280px) {
  .order-sticky-bar {
    display: flex;
    align-items: center;
    /* Сводка ошибок ложится второй строкой во всю ширину — для неё разрешаем
       перенос, сумма и кнопка остаются в первой строке. */
    flex-wrap: wrap;
    gap: 14px;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    background: var(--color-white);
    box-shadow: 0 -6px 20px rgba(44, 64, 91, 0.16);
    padding: 10px 16px;
    /* Домашний индикатор iPhone перекрывает нижние ~34px — без этого отступа
       кнопка оказывается ровно под ним и половина нажатий уходит системе. */
    padding-bottom: calc(10px + env(safe-area-inset-bottom));
    /* Уезжает вниз целиком, а не гасится прозрачностью: скрытая панель не
       должна перехватывать нажатия по тому, что под ней.
       translate3d, а не translateY: iOS рисует прилипшие панели задним числом
       и во время инерционной прокрутки бросает их посреди экрана. Своя
       графическая прослойка заставляет Safari двигать панель вместе с
       экраном. */
    transform: translate3d(0, 120%, 0);
    will-change: transform;
    -webkit-backface-visibility: hidden;
    transition: transform .25s ease;
  }
  .order-sticky-bar.is-visible { transform: translate3d(0, 0, 0); }
  .order-sticky-bar__total { min-width: 0; line-height: 1.2; }
  .order-sticky-bar__total span { display: block; font-size: 12px; color: var(--color-text-muted); }
  .order-sticky-bar__total strong { font-size: 20px; color: var(--color-navy); white-space: nowrap; }
  /* Кнопка занимает всю оставшуюся ширину — сумма слева фиксирована по
     содержимому, тянуться должна кнопка. */
  .order-sticky-bar .btn { flex: 1; min-width: 0; font-size: 19px; }
}

/* Короткий подвал страницы заказа: одна строка, копирайт слева, ссылка на
   политику справа. Фон тот же тёмно-синий, что у большого футера. */
.site-footer--compact { padding: 16px 0; }
.site-footer--compact .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  flex-wrap: wrap;
  font-size: 13px;
  color: rgba(255,255,255,0.75);
}
.site-footer--compact a { color: rgba(255,255,255,0.75); text-decoration: underline; }
.site-footer--compact a:hover { color: var(--color-white); }

/* Текст политики: узкая колонка для читаемости длинного юридического текста. */
.policy-doc { max-width: 820px; }
.policy-doc__meta { color: var(--color-text-muted); font-size: 14px; margin: 0 0 28px; }
.policy-doc h2 { font-size: 20px; margin: 32px 0 12px; }
.policy-doc h2:first-of-type { margin-top: 0; }
.policy-doc p { margin: 0 0 14px; line-height: 1.7; }
.policy-doc ul { margin: 0 0 18px; padding-left: 22px; }
.policy-doc li { margin-bottom: 8px; line-height: 1.7; }
.policy-doc a { color: var(--color-accent); text-decoration: underline; }

/* Облегчённая шапка страницы заказа: логотип слева, телефон и вход справа.
   Меню и бургера в ней нет, поэтому прижимаем действия к правому краю —
   в обычной шапке это делает растянутая посередине навигация. */
.site-header--compact .container { justify-content: space-between; }
.site-header--compact .site-header__actions { margin-left: auto; }
/* Телефон в обычной шапке прячется на узких экранах вместе с меню, потому что
   дублируется в выехавшей панели. Здесь панели нет — телефон нужен всегда. */
@media (max-width: 960px) {
  .site-header--compact .site-header__phone { display: inline-block; }
  .site-header--compact .site-header__cta { display: inline-flex; }
}
/* На совсем узких экранах телефон убираем, иначе логотип и кнопка кабинета
   не помещаются в одну строку; кнопка остаётся — вход важнее. */
@media (max-width: 560px) {
  .site-header--compact .site-header__phone { display: none; }
  /* Логотип 64px в паре с кнопкой кабинета не помещался: 197px эмблемы плюс
     199px кнопки плюс поля — это 428px при экране 390. Строка уезжала за край,
     и вся страница оформления заказа ездила вбок. */
  .site-header--compact .site-header__logo img { height: 46px; }
  /* Кроме 404: там телефон и есть единственное действие в шапке, прятать
     его не за что — кнопки кабинета рядом нет. */
  .site-header--phone-only .site-header__phone { display: inline-block; }
}
/* 320px: логотип 46px и номер кеглем 17px в строку не сходятся — номер
   выезжал за правый край и тянул вбок всю страницу. Ужимаем и то, и другое:
   прятать здесь нечего, телефон в этой шапке единственный. */
@media (max-width: 360px) {
  .site-header--phone-only .site-header__logo img { height: 34px; }
  .site-header--phone-only .site-header__phone { font-size: 15px; }
  .site-header--phone-only .container { padding-left: 14px; padding-right: 14px; }
}
/* На узких экранах карточка отдаёт содержимому свои поля: с полями 28px и
   отступом 22px под текст оставалось 216px, и телефон рвался на две строки
   посреди номера. Ужатая карточка вмещает номер целиком. */
@media (max-width: 400px) {
  .card { padding: 22px 18px; }
  .card--icon-left { gap: 14px; }
  .card--icon-left .card__icon { font-size: 40px; }
}
/* Кнопки набраны в одну строку (white-space:nowrap) — так они выглядят
   аккуратно и не рвутся посреди фразы. Но «Узнать больше о компании» кеглем
   17px — это 315px, а на экране 320 под текст остаётся 288: кнопка вылезала
   за край и тянула вбок всю главную. На узких экранах разрешаем перенос по
   словам и чуть поджимаем боковые поля. */
@media (max-width: 420px) {
  .btn { white-space: normal; text-align: center; }
  .btn--lg { padding-left: 24px; padding-right: 24px; }
}
/* Ниже 400px даже уменьшённый логотип и кнопка кабинета словами не сходятся:
   на 320px не хватает 62px. Подпись у кнопки убираем, остаётся иконка —
   она узнаётся сама, а вход с узкого экрана нужен не реже, чем с широкого. */
@media (max-width: 400px) {
  .site-header--compact .lk-cta-label { display: none; }
  .site-header--compact .site-header__cta { padding-left: 14px; padding-right: 14px; }
}

/* Кнопка «Личный кабинет» в облегчённой шапке выровнена по левому краю правой
   колонки с расчётом заказа. Сама кнопка обычного размера — ширину держит
   обёртка: она ровно 300px (ширина колонки) и, как последний элемент, упирается
   в правый край контейнера, поэтому её левый край совпадает с левым краем
   колонки. Кнопка внутри прижата влево, справа от неё остаётся воздух.
   Только там, где колонки вообще есть: ниже 1280px раскладка одноколоночная. */
.site-header__cta-slot { display: flex; }
@media (min-width: 1281px) {
  .site-header--compact .site-header__cta-slot { width: 300px; flex-shrink: 0; }
}

/* Подсветка пункта, выбранного стрелками на клавиатуре, — тот же фон, что при
   наведении мышью, чтобы оба способа навигации выглядели одинаково. */
.custom-select__option.is-highlighted { background: var(--color-bg-soft); }

/* Промежуток между бургером и полноразмерной шапкой: строка помещается, но
   впритык. Ужимаем просветы и поля кнопок — без этого на окне 1120–1280
   телефон и «Личный кабинет» выходили за правый край. */
@media (min-width: 1120px) and (max-width: 1280px) {
  .site-header__logo img { height: 44px; }
  .site-nav { gap: 18px; }
  .site-nav a { font-size: 15px; }
  .site-header__actions { gap: 8px; }
  .site-header__actions .btn { padding-left: 12px; padding-right: 12px; }
  .site-header__actions .btn--primary.site-header__cta { padding-left: 16px; padding-right: 16px; }
  .site-header__phone { font-size: 15px; }
}

/* Строка о восстановленном черновике. Голубой не годился: тем же цветом на
   форме залиты корректно заполненные поля, и полоса читалась как часть формы.
   Берём песочный — он выделяется, но не кричит об ошибке, как красный. */
.order-draft-note {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px 14px;
  margin-bottom: 20px;
  padding: 12px 18px;
  border-radius: var(--radius-md);
  border: 1px solid #EED9A8;
  background: #FFF6E3;
  color: #7a5a1a;
  font-size: 14px;
  text-align: center;
}
.order-draft-note__icon { display: inline-flex; color: #B5822A; }
/* Кнопка очистки — обычная кнопка сайта в уменьшенном виде: действие
   заметное, но не спорит с «Создать заказ». */
.order-draft-note .btn { padding: 6px 14px; font-size: 13px; }

/* ===== Видимый фокус с клавиатуры =====
   У полей своя реакция на фокус — синяя рамка вместо системной обводки. Своей
   обводки им не добавляем: получались две рамки вокруг одного поля.

   Цвет рамки один и тот же, откуда бы фокус ни пришёл — с мыши или с
   клавиатуры. Одно время рамка с клавиатуры была темнее, но разница читалась
   как «поле в другом состоянии», хотя состояние то же самое. Требование
   доступности выполняет сама рамка: она заметно отличается от обычной
   границы поля.

   Обводка нужна там, где своей рамки нет: кнопки, вкладки, ярлыки, ссылки. */
:focus-visible { outline: 2px solid var(--color-navy-light); outline-offset: 2px; }
.order-field input:focus-visible,
.order-field select:focus-visible,
.order-field textarea:focus-visible,
.calc-field input:focus-visible,
.calc-field select:focus-visible,
.custom-select__toggle:focus-visible,
.custom-select__search input:focus-visible,
.lk-auth-box .form-row input:focus-visible {
  outline: none;
  border-color: var(--color-navy-light);
}
.order-service-tab:focus-visible,
.order-dims-toggle:focus-visible,
.order-add-piece:focus-visible,
.order-map-link:focus-visible,
.lk-saved-addresses__item:focus-visible,
.order-step:focus-visible { outline-offset: 3px; }
