/* ГаражЛог — лендінг (статичний, роздається edge-nginx).

   ТОКЕНИ КОЛЬОРУ між маркерами нижче — МАШИНОПИСНІ. Джерело —
   темна половина `packages/ui/src/tokens.css`, переписує їх
   `scripts/gen-landing-tokens.mjs`. Лендінг статичний і packages/ui
   імпортувати не може, тож «синхронні самі собою» вони не будуть ніколи:
   тільки згенеровані або звірені машиною.

   ВЛАСНИЙ ШАР лендінгу (радіуси, тіні, плівки, рух) оголошений ОКРЕМИМ :root
   ПІСЛЯ маркерів, і це не стилістика. Генератор зупиняється, коли всередині
   маркерів бачить змінну, якої немає ні в MAP, ні в LANDING_OWN — тобто
   покласти нове туди означало б зламати звірку токенів наступним же прогоном.

   РЕДИЗАЙН 08.08.2026: змінено ПОВЕРХНЮ (глибина, типографіка, рух,
   стани наведення), а не КАРКАС. Три речі лишились недоторканими навмисно, бо
   кожну з них тримає замір, а не смак:
     1. розміри в шапці (кеглі, проміжки, поля кнопок) — з них виведені межі
        медіазапитів 1099 і 1023, див. коментарі там;
     2. падінг .aud 24px — з нього виведена ширина треків .grid-4;
     3. співвідношення вертикальних розривів герой:секція — його міряє
        `scripts/check-landing.mjs` і воно мусить лишатись помітним.
   Кольори теж НЕ чіпав: вони спільні з пʼятьма застосунками через tokens.css,
   і правка тут була б правкою всієї платформи. Новий вигляд зібраний з
   наявної палітри плюс власний шар прозорих плівок і градієнтів. */

/* gl-tokens:start — вміст між маркерами МАШИНОПИСНИЙ.
   Правки руками тут переживуть рівно до наступного прогону генератора.
   Змінюєте колір — змінюйте у packages/ui/src/tokens.css. */
:root {
  --bg: #0F1115;
  --surface: #1A1D23;
  --surface2: #232730;
  --line: #2F343E;
  --ink: #E6E8EC;
  --muted: #9AA3B2;
  --accent: #F5A524;
  --accent-ink: #0F1115;
  --success: #22C55E;
  --info: #60A5FA;
  --radius: 16px;
  --maxw: 1120px;
}
/* gl-tokens:end */

/* --- Власний шар лендінгу -----------------------------------------------
   Усе тут ПОХІДНЕ від токенів вище через color-mix: нових констант кольору
   не заводимо, інакше палітра почне жити двома життями. Єдиний домішок —
   #FF4D3D у --accent-2: це не самостійний колір, а другий стоп градієнта,
   ніде не вживаний як заливка чи текст. */
:root {
  /* Радіуси. --radius (16px) лишається за машинописним блоком і вживається
     там, де його вже чекає розмітка; шкала нижче — для нового. */
  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;

  /* Плівки поверх поверхонь. Саме плівки, а не нові поверхні: так глибина
     працює на будь-якому тлі, і додавання секції не вимагає нового токена. */
  --edge: color-mix(in srgb, #FFFFFF 7%, transparent);
  --edge-strong: color-mix(in srgb, #FFFFFF 12%, transparent);
  --glass: color-mix(in srgb, var(--bg) 72%, transparent);
  --line-soft: color-mix(in srgb, var(--line) 60%, transparent);
  --accent-2: color-mix(in oklab, var(--accent) 62%, #FF4D3D);
  --accent-film: color-mix(in srgb, var(--accent) 12%, transparent);
  --accent-line: color-mix(in srgb, var(--accent) 42%, transparent);

  /* Тіні. Перший рядок кожної — внутрішня світла грань: без неї темна картка
     на темному тлі читається як діра, а не як предмет. */
  --sh-card: inset 0 1px 0 var(--edge), 0 18px 40px -26px rgba(0, 0, 0, .85);
  --sh-lift: inset 0 1px 0 var(--edge-strong), 0 28px 60px -28px rgba(0, 0, 0, .95);
  --sh-hero: inset 0 1px 0 var(--edge-strong), 0 60px 120px -45px rgba(0, 0, 0, .9);

  /* Рух. Одна крива на весь сайт — різні криві в сусідніх елементах читаються
     як несправність, а не як багатство. */
  --ease: cubic-bezier(.22, .75, .24, 1);
  --dur: .2s;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.65 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Тло сторінки — не суцільна заливка: дві дуже слабкі плями кольору вгорі
     тримають вертикаль, коли людина прокручує повз межі секцій. */
  background-image:
    radial-gradient(900px 520px at 82% -8%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 70%),
    radial-gradient(760px 460px at 6% 4%, color-mix(in srgb, var(--info) 5%, transparent), transparent 70%);
  background-repeat: no-repeat;
  background-attachment: fixed;
}
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }

/* Фокус видно завжди і однаково. Клавіатурний обхід сторінки був єдиним
   станом, для якого тут не існувало жодного правила, окрім бургера. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}
::selection { background: color-mix(in srgb, var(--accent) 35%, transparent); color: var(--ink); }

/* --- Рух ------------------------------------------------------------------
   ПРАВИЛО, ЯКЕ ТУТ ГОЛОВНЕ: прокруткові анімації НЕ РУХАЮТЬ ГЕОМЕТРІЮ.
   Проявляємо через opacity і blur, ніколи через transform і ніколи через
   visibility. Дві незалежні причини, і обидві заміряні:
     1. `scripts/check-landing.mjs` рахує вертикальний ритм за
        getBoundingClientRect видимих нащадків. transform ЗМІНЮЄ цей
        прямокутник, тож картка, зсунута на 40px «до появи», зробила б стик
        секцій більшим на 40px — і сторож червонів би на правильній роботі;
     2. той самий сторож відкидає елементи з visibility:hidden, тобто ховання
        ним прибрало б блок із заміру взагалі.
   Виняток дозволено лише абсолютно спозиційованим прикрасам: сторож їх не
   бачить за побудовою (фільтр position === "static"), тож їм transform можна.

   Початкового стану «невидимо» НЕМАЄ в базових правилах — він живе ТІЛЬКИ
   всередині keyframes. Це навмисно: якщо браузер не підтримує прокруткові
   таймлайни, не застосує медіазапит або просто вимкне анімації, людина
   побачить сторінку цілою. Порядок «спершу сховати, потім показати» дає
   рівно протилежну відмову — порожню сторінку. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .sec-head,
    .card,
    .aud,
    .price,
    .store-badges,
    .cta-band .wrap,
    .dov-card,
    footer .col {
      animation: gl-reveal linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 62%;
    }
    /* Сходинка в межах ряду: у кожного елемента власний таймлайн, тож
       затримка тут задається зсувом ДІАПАЗОНУ, а не animation-delay —
       delay у прокруткових анімаціях не працює як у часових. */
    .grid > *:nth-child(3n + 2) { animation-range: entry 7% entry 69%; }
    .grid > *:nth-child(3n + 3) { animation-range: entry 14% entry 76%; }
    .grid-4 > *:nth-child(2) { animation-range: entry 6% entry 68%; }
    .grid-4 > *:nth-child(3) { animation-range: entry 12% entry 74%; }
    .grid-4 > *:nth-child(4) { animation-range: entry 18% entry 80%; }
  }

  /* Шапка «сідає» на тло, щойно сторінка зрушила: до першого пікселя вона
     майже прозора, далі — щільна з тінню. Прокрутковий таймлайн кореня, тож
     жодного JS. */
  @supports (animation-timeline: scroll()) {
    .top {
      animation: gl-top linear both;
      animation-timeline: scroll(root);
      animation-range: 0 90px;
    }
  }
}

@keyframes gl-reveal {
  from { opacity: 0; filter: blur(10px); }
  to { opacity: 1; filter: blur(0); }
}
@keyframes gl-top {
  from { background: color-mix(in srgb, var(--bg) 40%, transparent); box-shadow: none; }
  to { background: var(--glass); box-shadow: 0 12px 30px -22px rgba(0, 0, 0, 1); }
}
@keyframes gl-drift {
  from { transform: translate3d(-2%, -1%, 0) scale(1.04); }
  to { transform: translate3d(2%, 2%, 0) scale(1.12); }
}
@keyframes gl-pulse {
  0%, 100% { opacity: .55; }
  50% { opacity: 1; }
}
@keyframes gl-sheen {
  from { transform: translateX(-120%); }
  to { transform: translateX(220%); }
}

/* --- Шапка --- */
.top {
  position: sticky; top: 0; z-index: 50;
  background: var(--glass);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid var(--line-soft);
}
/* position:relative — щоб мобільна панель меню лягала рівно під шапку.
   Значення gap/font-size у шапці — стиснуті, і це не «на всяк випадок».
   .wrap має max-width: var(--maxw) і padding 20px, тож доступна ширина шапки
   СТАЛА — 1080px на будь-якому вікні від 1120 і ширше. Ширший монітор місця
   не додає. До 31.07.2026 ці значення були просторі (gap 40, 14.5px), а
   стиснення вмикав @media (max-width: 1120px) — тобто рівно навпаки:
   стискали там, де вміщалось, і не стискали там, де ні. Заміряно (Edge,
   Segoe UI): на 1440 шапці треба було 1175px проти 1080 доступних.

   РЕДИЗАЙН 08.08.2026 не змінив у цьому блоці ЖОДНОГО розміру — лише колір,
   розмиття й підкреслення. Причина не в обережності: висота, кеглі, проміжки
   й поля кнопок — це доданки того самого рахунку, з якого виведені межі 1099
   і 1023. Зміна кегля на пів пікселя посунула б межу, а межа тут — з
   пристрою власника, не з естетики. */
.top .wrap { position: relative; display: flex; align-items: center; gap: 24px; height: 72px; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 18px; letter-spacing: .2px; }
/* flex-shrink: 0 — бо інакше знак стискається ПЕРШИМ. Глобальне
   `img, svg { max-width: 100% }` дозволяє йому віддавати ширину, і при тиску
   на рядок (більший системний кегль, довший переклад, зайвий пункт) знак
   зникає повністю ще до того, як щось інше поворухнеться. Заміряно: при
   мінімальному кеглі браузера 18px іконка мала ширину 0, а «Спробувати»
   обрізалось краєм — тобто ламався бренд, а не те, що можна прибрати. */
.logo svg { width: 28px; height: 28px; flex-shrink: 0; }
.logo { margin-right: auto; flex-shrink: 0; }
.top .logo svg { transition: transform var(--dur) var(--ease), filter var(--dur) var(--ease); }
.top .logo:hover svg { transform: translateY(-1px); filter: drop-shadow(0 4px 10px var(--accent-line)); }

.nav { display: flex; align-items: center; gap: 16px; font-size: 13.5px; color: var(--muted); }
/* Без nowrap «Для автопарків» рветься всередині пункту і шапка стає двоярусною.
   Саме по собі це правило не лікує, а міняє симптом: якщо ширини не вистачає,
   пункти просто вилізуть за край. Тому воно йде В ПАРІ зі стисненням вище. */
.nav > a { white-space: nowrap; }
/* Підкреслення малюємо завжди, міняємо лише прозорість і масштаб — інакше
   hover зсував би сусідні пункти на висоту лінії. Масштаб іде від лівого
   краю: лінія «виїжджає» з початку слова, а не проявляється цілком. */
.nav a { position: relative; padding: 4px 0; transition: color var(--dur) var(--ease); }
.nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  opacity: 0; transform: scaleX(.3); transform-origin: left;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.nav a:hover { color: var(--ink); }
.nav a:hover::after { opacity: .6; transform: scaleX(1); }
.nav a.is-active { color: var(--ink); }
.nav a.is-active::after { opacity: 1; transform: scaleX(1); }
.nav-cta { display: flex; align-items: center; gap: 8px; margin-left: 8px; }
.nav-cta .btn { padding: 8px 13px; font-size: 13.5px; border-radius: 10px; white-space: nowrap; }

/* Бургер: чекбокс лишається у DOM видимим для клавіатури й скрінрідера,
   але прибраний з потоку — намальована лише мітка. */
.nav-toggle { display: none; position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; }
.burger {
  display: none; flex: none; width: 44px; height: 44px; margin-right: -10px;
  border-radius: 10px; cursor: pointer;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  transition: background var(--dur) var(--ease);
}
.burger:hover { background: color-mix(in srgb, var(--ink) 7%, transparent); }
.burger span {
  display: block; width: 22px; height: 2px; border-radius: 2px; background: var(--ink);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.nav-toggle:focus-visible + .burger { outline: 2px solid var(--accent); outline-offset: 2px; }
.nav-toggle:checked + .burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle:checked + .burger span:nth-child(2) { opacity: 0; }
.nav-toggle:checked + .burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Якорі не ховаються під липкою шапкою */
[id] { scroll-margin-top: 88px; }

/* --- Кнопки --- */
.btn {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 22px; border-radius: var(--r-md); font-weight: 700; font-size: 15px;
  border: 1px solid transparent; cursor: pointer;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease), background-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn-accent {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: var(--accent-ink);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #FFFFFF 30%, transparent),
              0 10px 26px -14px color-mix(in srgb, var(--accent) 85%, transparent);
}
/* Блік проходить по кнопці лише при наведенні — і лише один раз за наведення.
   Він абсолютний, тож у замір геометрії не входить. */
.btn-accent::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 35%, color-mix(in srgb, #FFFFFF 45%, transparent) 50%, transparent 65%);
  transform: translateX(-120%);
  pointer-events: none;
}
.btn-accent:hover {
  transform: translateY(-1px);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #FFFFFF 35%, transparent),
              0 16px 34px -14px color-mix(in srgb, var(--accent) 95%, transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .btn-accent:hover::after { animation: gl-sheen .65s var(--ease) 1; }
}
.btn-ghost {
  border-color: var(--line);
  color: var(--ink);
  background: color-mix(in srgb, var(--surface) 80%, transparent);
  box-shadow: inset 0 1px 0 var(--edge);
}
.btn-ghost:hover {
  border-color: var(--accent-line);
  background: color-mix(in srgb, var(--surface2) 90%, transparent);
  transform: translateY(-1px);
}
.btn-lg { padding: 15px 30px; font-size: 16.5px; border-radius: var(--r-md); }

/* --- Hero --- */
/* Нижній відступ героя. Головний змістовий розрив сторінки — герой→перша
   секція; ПРАВИЛО: він мусить бути помітно БІЛЬШИМ за рядовий стик
   секція→секція, інакше сторінка читається як однорідна стрічка без початку.
   Історія трьох спроб і чому арифметиці тут вірити не можна:
     144 (72+72) — пʼята частина екрана ноутбука порожня, скарга власника;
     88  (40+48) — рядовий стик став 96 проти головного 88: ієрархія перевернулась;
     72  (40+32) — за арифметикою на 7 px більше за рядовий, а ЗАМІРЯНО на живій
                   сторінці дало 66 проти 65. Різниця в 1 px — це не ієрархія.
   Розбіжність не помилка арифметики: правий стовпець героя нахилений і звисає
   нижче за падінг, тож око бачить стик меншим за розрахунковий. (Заміри вище
   зроблені ще на .mock; нахил 1.5deg успадкували .phone і .laptop, тож причина
   розбіжності та сама, а клас інший.)
   Тому числа тут перевіряються ТІЛЬКИ заміром відстані між видимим вмістом
   смуг (scripts/check-landing.mjs друкує обидва), а не додаванням падінгів:
   два з трьох попередніх варіантів були «правильні» на папері.
   Числа після редизайну 08.08.2026 — у коментарі до section нижче. */
.hero { padding: 104px 0 76px; position: relative; overflow: hidden; }
/* Дві плями кольору й тонка сітка. Сітка вимальовується маскою від центру
   назовні, тож на краях її не видно — інакше вона читається як міліметрівка,
   а не як фактура. */
.hero::before {
  content: ""; position: absolute; inset: -40% -20% auto;
  height: 130%; pointer-events: none;
  background:
    radial-gradient(600px 380px at 78% 30%, color-mix(in srgb, var(--accent) 15%, transparent), transparent 65%),
    radial-gradient(520px 320px at 15% 75%, color-mix(in srgb, var(--info) 10%, transparent), transparent 65%);
}
.hero::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--line-soft) 1px, transparent 1px),
    linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size: 56px 56px;
  opacity: .5;
  -webkit-mask-image: radial-gradient(680px 420px at 50% 30%, #000 0%, transparent 78%);
  mask-image: radial-gradient(680px 420px at 50% 30%, #000 0%, transparent 78%);
}
@media (prefers-reduced-motion: no-preference) {
  .hero::before { animation: gl-drift 26s ease-in-out infinite alternate; }
}
.hero .wrap { position: relative; z-index: 1; display: grid; grid-template-columns: 1.1fr .9fr; gap: 60px; align-items: center; }
.kicker {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 20px;
  padding: 6px 14px 6px 11px; border-radius: 99px;
  border: 1px solid var(--accent-line);
  background: var(--accent-film);
}
.kicker::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .kicker::before { animation: gl-pulse 2.6s var(--ease) infinite; }
}
h1 {
  font-size: clamp(36px, 5.6vw, 60px); line-height: 1.06; font-weight: 800;
  letter-spacing: -1.4px; text-wrap: balance;
}
/* Акцент у заголовку — градієнтом по тексту. Fallback явний: якщо
   background-clip:text не підтримується, лишиться суцільний акцентний колір,
   а не невидимий напис. */
h1 .em { color: var(--accent); }
@supports (-webkit-background-clip: text) or (background-clip: text) {
  h1 .em {
    background: linear-gradient(100deg, var(--accent), var(--accent-2) 55%, var(--accent));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}
.sub { margin: 24px 0 34px; font-size: 18.5px; color: var(--muted); max-width: 33em; text-wrap: pretty; }
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; }
.hero-note { margin-top: 18px; font-size: 13.5px; color: var(--muted); }

/* --- Мокапи героїв: КЛАСІВ БІЛЬШЕ НЕМАЄ ------------------------------------
   Тут стояли .mock (намальована картка авто в правому стовпці героя) та її
   нутрощі — .mock .plate (номерний знак), .mock h3, .mock .odo, рядок .mrow з
   .mrow .lbl і плашки .pill / .pill-ok / .pill-warn. Усі видалені 23.08.2026,
   коли останній мокап пішов зі сторінки.

   КУДИ ВОНИ ДІЛИСЬ. Мокапи по черзі замінені знімками СПРАВЖНІХ екранів:
     партія 2  — головна    → .phone  (клієнтський застосунок, mobile-first);
     партія 3  — /sto, /fleet, /avtomagazyn → .laptop (рамка вікна);
     партія 3в — /marketplace → .laptop зі знімком вітрини.
   Обидва замінники живуть нижче, у розділах партій 2 і 3, і успадкували від
   .mock рівно те, що тримало вигляд героя: нахил 1.5deg, світну грань
   псевдоелементом і ту саму заливку корпусу.

   ЧОМУ ВИДАЛЕНО, А НЕ ЛИШЕНО «ПРО ЗАПАС». Попередні дві партії лишали .mock
   свідомо і писали в коментарі, ХТО його ще вживає, — бо вживав. Тепер
   споживачів нуль: `class="mock"`, `mrow` і `pill` не трапляються в жодному з
   12 html лендінга (включно з /dovidnyk/**) і в scripts/gen-dovidnyk.mjs, який
   довідник генерує. Мертвий CSS без споживача не «запас», а пастка: наступний
   автор читає його як чинний і будує на ньому.

   ЩО ЗНИКЛО РАЗОМ ІЗ НИМИ. .pill-warn був мертвий ще до цієї партії (жодна
   сторінка його не вживала). Токен --success живий і потрібен далі — його
   вживає .aud li::before; шукати «звідки взявся --success, якщо .pill-ok
   немає» не доведеться. Заміряний контраст плашки (успіх на плівці успіху,
   4.56 при порозі 4.5) разом із причиною заливки 9% лишається в історії цього
   файла: якщо плашки колись повернуть, число вже здобуте. */


/* --- Секції --- */
/* Рядовий стик секція→секція проти головного розриву герой→перша секція.
   Правило те саме, що й раніше: головний розрив мусить читатись як більший,
   і сторож вимагає щонайменше ×1.15. Арифметика падінгів тут не працює —
   нахилений правий стовпець героя звисає нижче свого падінга, тож числа беруться ЗАМІРОМ
   (`node scripts/check-landing.mjs infra/landing`, секція «вертикальний ритм»).
   Заміряно 08.08.2026 — обидва боки тим самим сторожем, старий CSS з HEAD:
                було             стало
     1440    82 / 65  ×1.26    120 / 89  ×1.35
      375    72 / 57  ×1.26    105 / 69  ×1.52
   Проміжний варіант (нижній падінг героя 64) давав 108/89 = ×1.21. Формально
   він проходив поріг 1.15, і саме тому вартий згадки: секції отримали повітря,
   а разом з ним НЕЗАМІТНО з'їли половину запасу ієрархії. Зелений сторож цього
   не показує — він каже «так», а не «ледве». Тому нижній падінг піднято до 76:
   правило тут не «пройти поріг», а «тримати відстань від нього».
   Наслідок для наступного: додаєте повітря в section — додавайте ОДНОЧАСНО в
   нижній падінг героя, інакше зникне не ваша секція, а початок сторінки. */
section { padding: 44px 0; position: relative; }
section.alt {
  background: var(--surface);
  border-block: 1px solid var(--line-soft);
}
/* Тонка акцентна нитка на межі смуги: замість двох однакових ліній угорі й
   унизу межа отримує напрямок. */
section.alt::before {
  content: ""; position: absolute; inset: -1px 0 auto; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--accent-line) 22%, color-mix(in srgb, var(--info) 34%, transparent) 78%, transparent);
}
.sec-head { max-width: 740px; margin-bottom: 34px; }
h2 {
  font-size: clamp(27px, 3.6vw, 40px); font-weight: 800; letter-spacing: -.9px;
  line-height: 1.14; text-wrap: balance;
}
.sec-head p { margin-top: 15px; color: var(--muted); font-size: 17px; text-wrap: pretty; }

.grid { display: grid; gap: 18px; }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1100px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }

.card {
  position: relative;
  background: linear-gradient(180deg, color-mix(in srgb, var(--surface2) 96%, #FFFFFF) 0%, var(--surface2) 46%);
  border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 26px;
  box-shadow: var(--sh-card);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
section.alt .card {
  background: linear-gradient(180deg, color-mix(in srgb, var(--bg) 94%, #FFFFFF) 0%, var(--bg) 46%);
}
/* Тепле світло проступає з-під верхнього краю картки при наведенні. Малюємо
   псевдоелементом, а не тінню: тінь довелося б анімувати разом із підйомом,
   і на слабких машинах це помітно смикається. */
.card::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(420px 160px at 50% -30%, var(--accent-film), transparent 70%);
  opacity: 0; transition: opacity var(--dur) var(--ease);
}
.card:hover {
  transform: translateY(-3px);
  border-color: var(--accent-line);
  box-shadow: var(--sh-lift);
}
.card:hover::after { opacity: 1; }
.card .ico {
  position: relative;
  width: 46px; height: 46px; border-radius: var(--r-sm); display: grid; place-items: center;
  background: linear-gradient(160deg, var(--accent-film), transparent);
  border: 1px solid var(--accent-line);
  color: var(--accent); margin-bottom: 18px;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.card:hover .ico {
  transform: translateY(-1px) rotate(-3deg);
  box-shadow: 0 10px 22px -14px color-mix(in srgb, var(--accent) 90%, transparent);
}
.card .ico svg { width: 22px; height: 22px; }
.card h3 { font-size: 18px; margin-bottom: 9px; letter-spacing: -.2px; text-wrap: balance; }
.card p { color: var(--muted); font-size: 14.8px; text-wrap: pretty; }

/* --- Аудиторії --- */
/* Падінг 24, а не 34, і це не косметика. `1fr` — це `minmax(auto, 1fr)`, тобто
   трек не стискається нижче min-content картки, а min-content тут задає кнопка:
   вона `white-space: nowrap` і переноситись не вміє. При 34 px треки виходили
   272/261/261/261 (чотири картки РІЗНОЇ ширини, бо перша кнопка ширша), разом
   1142 проти 1080 доступних — і від 1130 сторінка починала їхати вбік.
   Заміряно в Edge: при 24 px треки рівні по 257, кнопка вміщається із запасом
   6-16 px, бічного скролу немає ніде.
   Не `minmax(0, 1fr)`: він теж вирівнює треки, але тоді кнопка вилазить із
   картки на 14 px — сторінка перестає їхати, а дефект переїжджає всередину.
   РЕДИЗАЙН 08.08.2026 падінг НЕ ЧІПАВ саме тому: 24 тут — не смак, а стеля,
   виведена з min-content кнопки. Усе, що додано, — рамка, підсвітка й смужка
   зверху, тобто нуль пікселів до внутрішньої ширини. */
.aud {
  position: relative; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--r-lg); padding: 24px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--surface2) 96%, #FFFFFF) 0%, var(--surface2) 50%);
  box-shadow: var(--sh-card);
  display: flex; flex-direction: column; gap: 0;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.aud::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  opacity: .55; transition: opacity var(--dur) var(--ease);
}
.aud:hover { transform: translateY(-3px); border-color: var(--accent-line); box-shadow: var(--sh-lift); }
.aud:hover::before { opacity: 1; }
.aud .tag { font-size: 12px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--accent); }
.aud h3 { font-size: 23px; margin: 10px 0 10px; letter-spacing: -.4px; }
.aud p { color: var(--muted); font-size: 15.5px; text-wrap: pretty; }
.aud ul { margin: 18px 0 26px; padding: 0; list-style: none; display: grid; gap: 10px; }
.aud li { display: flex; gap: 10px; font-size: 15px; }
.aud li::before { content: "✓"; color: var(--success); font-weight: 800; }
.aud .btn { margin-top: auto; align-self: start; }

/* --- Тарифи --- */
.price { text-align: center; }
.price .amount {
  font-size: 36px; font-weight: 800; margin: 8px 0 2px; letter-spacing: -1px;
  font-variant-numeric: tabular-nums;
}
.price .per { color: var(--muted); font-size: 13.5px; }
.price ul { list-style: none; margin: 20px 0 0; display: grid; gap: 9px; font-size: 14.5px; color: var(--muted); }
/* Виділений тариф читається як обраний через РАМКУ і ЗОВНІШНЄ світло, а не
   через тепле тло під текстом. Спершу тут стояв акцентний радіальний градієнт
   усередині картки — виглядав добре й ЗАВАЛИВ контраст: приглушений текст на
   плівці 12% дав 4.17 при порозі 4.5 (заміряно на /sto, де під ним стоять
   пункти тарифу). Зовнішня тінь дає той самий сигнал «цей», але лежить ПОЗА
   текстом, тож нічого не зменшує. Правило на майбутнє: акцент, що потрапляє
   ПІД текст, коштує контрасту; акцент навколо — ні. */
.price.hl {
  position: relative;
  border-color: var(--accent-line);
  box-shadow:
    inset 0 1px 0 var(--edge-strong),
    0 0 0 1px color-mix(in srgb, var(--accent) 16%, transparent),
    0 30px 70px -34px color-mix(in srgb, var(--accent) 55%, transparent);
}
.badge-top {
  position: absolute; top: -12px; left: 50%; transform: translateX(-50%);
  background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: var(--accent-ink);
  font-size: 11.5px; font-weight: 800; padding: 4px 13px; border-radius: 99px; letter-spacing: .04em;
  box-shadow: 0 8px 20px -10px color-mix(in srgb, var(--accent) 90%, transparent);
  white-space: nowrap;
}

/* --- CTA-стрічка --- */
.cta-band { text-align: center; padding: 68px 0; position: relative; overflow: hidden; }
.cta-band::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(620px 300px at 50% 118%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 70%),
    radial-gradient(520px 260px at 12% -20%, color-mix(in srgb, var(--info) 9%, transparent), transparent 70%);
}
.cta-band .wrap { position: relative; z-index: 1; }
.cta-band h2 { margin-bottom: 15px; }
.cta-band p { color: var(--muted); margin-bottom: 32px; font-size: 17px; }

/* --- Кроки --- */
.step .shead { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.step .shead h3 { margin: 0; }
.step .n {
  flex: none; width: 36px; height: 36px; border-radius: var(--r-sm);
  display: grid; place-items: center;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: var(--accent-ink); font-weight: 800;
  box-shadow: 0 8px 20px -12px color-mix(in srgb, var(--accent) 90%, transparent);
}

/* --- Футер --- */
footer {
  border-top: 1px solid var(--line-soft); padding: 52px 0 36px;
  background: var(--surface); position: relative;
}
footer::before {
  content: ""; position: absolute; inset: -1px 0 auto; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--accent-line) 30%, transparent 70%);
}
footer .wrap { display: flex; flex-wrap: wrap; gap: 36px; justify-content: space-between; align-items: start; }
footer .col h4 { font-size: 12.5px; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); margin-bottom: 14px; }
footer .col a { display: block; font-size: 14.5px; color: var(--muted); margin-bottom: 9px; transition: color var(--dur) var(--ease); }
footer .col a:hover { color: var(--accent); }
footer .fin { width: 100%; margin-top: 8px; padding-top: 18px; border-top: 1px solid var(--line-soft); color: var(--muted); font-size: 13px; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; }

/* --- Адаптив --- */
@media (max-width: 900px) {
  /* Вертикаль на мобільному. До 31.07.2026 цей медіазапит чіпав лише сітки й
     навігацію, тож усі відступи лишались десктопними: на 375 px самий лише
     .cta-band зі своїми 84+84 зʼїдав більше третини екрана. Пропорції ті самі,
     що на десктопі (герой→секція лишається найбільшим розривом), просто менші.
     Нижній відступ героя навмисно тримається помітно більшим за рядовий стик —
     те саме правило, що й на десктопі, і той самий сторож. */
  .hero { padding: 64px 0 48px; }
  section { padding: 34px 0; }
  .cta-band { padding: 48px 0; }
  .dl { padding: 28px 0 8px; }
  footer { padding: 36px 0 28px; }

  .hero .wrap { grid-template-columns: 1fr; gap: 40px; }
  /* Тут же стояв `.mock { transform: none; max-width: 420px }`. Правило пішло
     разом із самим класом; ті самі дві властивості на телефоні тепер ставлять
     .phone і .laptop — кожен у своєму @media (max-width: 900px) нижче, зі
     своєю стелею (420 і 480) і своїм поясненням, чому саме така. */
  .grid-3, .grid-2, .grid-4 { grid-template-columns: 1fr; }
  /* Сітка героя на телефоні тільки заважає: вона перебиває текст. */
  .hero::after { opacity: .25; }
}

/* Другорядний пункт ховається РАНІШЕ за всю шапку — і саме це дозволяє
   тримати горизонтальне меню до 1024px (див. наступний блок).

   Клас .nav-minor стоїть у розмітці на «Тарифах» з самого початку, але правила
   для нього не існувало: єдине згадування було в мобільному блоці
   (`display: block`), де воно й так перебивається сусіднім `.nav a` за
   специфічністю. Тобто задум «на вузькому десктопі другорядне ховаємо» був
   записаний у КЛАСІ, а не в CSS, і не працював ніде.

   Втрата тут менша, ніж здається: «Тарифи» — єдиний пункт, що веде на якір
   ЦІЄЇ Ж сторінки (#pricing на головній, #connect на продуктових), тож він
   лишається досяжним прокручуванням. Решта шести ведуть на інші сторінки, і
   сховати їх означало б відрізати розділ.

   У панелі бургера (≤1023) пункт повертається: `.nav a { display: flex }` там
   специфічніший за `.nav-minor` і перекриває це правило. Перевірено рендером,
   а не міркуванням про специфічність. */
@media (max-width: 1099px) {
  .nav-minor { display: none; }
  /* Проміжки тут теж тісніші — і це не «про запас». Сховати «Тарифи»
     достатньо чотирьом сторінкам із шести, але Маркетплейс цього пункту не
     має взагалі, а його друга кнопка — «Шукати запчастини» замість
     «Спробувати». Заміряно на 1024: без цих рядків його шапка виходила за
     контент на 8.3px, тобто впиралась у сам край вікна.

     Маркетплейс і лишається найтіснішою сторінкою — саме за ним тут міра, а
     не за рештою. Заміряно на 1024 (доступно 984):
       лише «Тарифи» сховано          треба 992.3   запас −8.3
       + проміжки 16→12, відступ 8→4  треба 964.3   запас  19.7
       + поля кнопок 13→11            треба 956.3   запас  27.7
     19.7px — це близько 2% ширини шапки, тобто рівно та величина, на яку
     розходяться системні шрифти різних платформ (Segoe UI / Roboto / SF).
     Тому останній рядок не зайвий: поля кнопок людина не зауважує, а
     зіткнення напису з краєм вікна зауважує одразу. */
  .nav { gap: 12px; }
  .nav-cta { margin-left: 4px; }
  .nav-cta .btn { padding-left: 11px; padding-right: 11px; }
}

/* Бургер вмикається на 1023px. Було 1119 — і ціна цієї межі виявилась значно
   вищою за очікувану: ноутбук 1366×768 із типовим для Windows масштабом 125%
   дає рівно 1092 CSS-px, тобто НАЙПОШИРЕНІША конфігурація отримувала мобільне
   меню на десктопі. Виглядає це так, що логотип лишається у смузі сам, а всі
   посилання стовпчиком їдуть униз — власне на це й прийшла скарга 02.08.2026.

   Попереднє міркування («горизонтальна шапка існує тільки тоді, коли
   контейнер розгорнутий на повну») було охайним, але спиралось на оцінку
   запасу, а не на замір: у коментарі стояло «запас тане і десь під 1085
   закінчується». Заміряно поіменно (Edge, Segoe UI, живий сайт): логотип 129.2
   + сім пунктів 546.0 + проміжки 112 + кнопки 177.2 + 8 = 1004.4, тобто шапці
   треба 1044px ВІКНА. Запас закінчувався на 1044, а не на 1085.

   Числа для нових меж (від 1099 «Тарифи» сховано і проміжки тісніші), /sto:
     1024 → доступно 984, треба 905.6, запас 78.4
     1099 → доступно 1059, треба 905.6, запас 153.4
     1100 → доступно 1060, треба 1004.4, запас 55.6
     1120 → доступно 1080, треба 1004.4, запас 75.6
   Найтісніша точка нової розкладки — 1100 із запасом 55.6px, тобто ширшим за
   сталі 35px, заради яких і ставили 1119. Найтісніша СТОРІНКА — не ця:
   Маркетплейс має власний набір кнопок, його рахунок — у блоці 1099 вище.

   ВАЖЛИВО: 1023 і 1099 вписані числами, бо медіазапити не вміють читати
   var(--maxw). Змінили --maxw — перерахуйте обидві.
   Ці правила НЕ можна тримати в блоці 900px разом з відступами: тоді мобільна
   вертикаль (герой, секції, сітки в одну колонку) поїхала б і на планшети. */
@media (max-width: 1023px) {
  /* Мобільна навігація: панель на всю ширину під шапкою.
     Ховаємо через max-height+visibility, а не display:none, щоб пункти
     не лишалися в табуляції у згорнутому стані, але анімація працювала. */
  .nav-toggle { display: block; }
  .burger { display: flex; }
  .nav {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--surface); border-bottom: 1px solid var(--line);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .5);
    max-height: 0; overflow: hidden; visibility: hidden;
    font-size: 16px;
    transition: max-height .22s var(--ease), visibility .22s;
  }
  .nav-toggle:checked ~ .nav { max-height: calc(100vh - 72px); overflow-y: auto; visibility: visible; }
  .nav-minor { display: block; }
  /* У панелі пункт займає всю ширину рядка, тож nowrap із базових правил тут
     нічого не тисне, але й не потрібен — лишаємо як є. */
  .nav a {
    display: flex; align-items: center; min-height: 52px; padding: 8px 20px;
    border-top: 1px solid var(--line-soft); color: var(--ink);
  }
  .nav a::after { left: 20px; right: auto; bottom: 8px; width: 28px; transform: none; }
  .nav a:hover::after { transform: none; }
  .nav-cta { flex-direction: column; align-items: stretch; gap: 10px; margin: 0; padding: 16px 20px 20px; border-top: 1px solid var(--line-soft); }
  .nav-cta .btn { min-height: 48px; padding: 12px 18px; font-size: 15.5px; }
}

/* ---------------------------------------------------------------------------
   Довідник (/dovidnyk/). Класи використовує генератор scripts/gen-dovidnyk.mjs.
   Ширина тексту обмежена 68 символами: довший рядок читається помітно гірше,
   а стаття на 1500+ слів у три чверті екрана — це стіна.
   --------------------------------------------------------------------------- */
.dov{padding:36px 0 64px}
.dov .wrap{max-width:760px}
.dov h1{font-size:clamp(28px,3.6vw,40px);line-height:1.16;margin:14px 0 6px;letter-spacing:-.9px;text-wrap:balance}
.dov h2{font-size:23px;line-height:1.28;margin:38px 0 10px;letter-spacing:-.4px;text-wrap:balance}
.dov h3{font-size:18px;margin:26px 0 8px}
.dov p{margin:0 0 14px;font-size:17px;line-height:1.68;color:var(--ink)}
.dov ul,.dov ol{margin:0 0 16px;padding-left:22px;display:grid;gap:7px}
.dov li{font-size:17px;line-height:1.6;color:var(--ink)}
/* Посилання в тілі статті підкреслюємо: у суцільній прозі один лише колір
   відрізняє їх недостатньо, і це вимога доступності, а не смак. */
.dov a{color:var(--accent);text-decoration:underline;text-decoration-color:var(--accent-line);text-underline-offset:3px;transition:text-decoration-color var(--dur) var(--ease)}
.dov a:hover{text-decoration-color:var(--accent)}
.dov strong{color:var(--ink)}

.crumbs{font-size:13.5px;color:var(--muted);margin-bottom:6px}
.crumbs a{color:var(--muted);text-decoration:none;transition:color var(--dur) var(--ease)}
.crumbs a:hover{color:var(--accent)}
.dov-date{font-size:13.5px;color:var(--muted);margin:0 0 22px}

.dov-hero{padding:72px 0 28px}
.dov-hero .wrap{display:block;max-width:760px}
.dov-card{display:block;text-decoration:none}
.dov-card h3{margin-bottom:8px;color:var(--ink)}
.dov-card p{color:var(--muted);font-size:15px;line-height:1.55;margin:0}

@media (max-width:900px){
  .dov{padding:24px 0 44px}
  .dov h1{margin-top:10px}
  .dov-hero{padding:44px 0 20px}
}

/* Кнопки сторів */
.dl{padding:36px 0 10px}
.store-badges{display:flex;gap:16px;justify-content:center;flex-wrap:wrap;margin-top:8px}
.sbadge{display:inline-flex;align-items:center;gap:13px;background:#000;border:1px solid #2a2f3a;border-radius:var(--r-md);padding:12px 22px;color:#fff;text-decoration:none;min-width:210px;box-shadow:var(--sh-card);transition:border-color var(--dur) var(--ease),transform var(--dur) var(--ease)}
.sbadge:hover{border-color:#555}
a.sbadge:hover{transform:translateY(-2px)}
.sbadge .ic{width:30px;height:30px;flex:none}
.sbadge span{display:flex;flex-direction:column;line-height:1.15;text-align:left}
.sbadge small{font-size:11.5px;color:#bfc5cf;letter-spacing:.3px}
.sbadge b{font-size:19px;font-weight:700}
@media(max-width:560px){.sbadge{min-width:0;flex:1}}

/* ---------------------------------------------------------------------------
   Партія 2: герой зі знімком, стрічка брендів, FAQ
   --------------------------------------------------------------------------- */

/* --- Рамка телефона в героєві --------------------------------------------
   Намальована картка .mock у героєві головної замінена справжнім знімком
   екрана застосунку. Тоді .mock ще лишався чинним — його вживали /sto, /fleet,
   /avtomagazyn і /marketplace, і прибрати його заради охайності на одній
   сторінці означало б зламати чотири. Партії 3 і 3в замінили й ті чотири, тож
   класу .mock у файлі більше немає взагалі (див. розділ вище).

   Нахил 1.5deg успадкований від .mock свідомо: він тримає звичний вигляд
   героя. Але предметом заміру ритму він більше не є — див. компенсацію нижче. */
.phone {
  position: relative;
  justify-self: center;
  width: 100%;
  max-width: 280px;
  /* min-width:0 тут ОБОВʼЯЗКОВЕ, і підстава лежить поза цим правилом, тож без
     коментаря його приберуть як зайве. Трек `1fr` — це `minmax(auto, 1fr)`, а
     `auto` для елемента сітки означає його МІНІМАЛЬНИЙ ВМІСТ. Для картинки
     мінімальний вміст — її ВЛАСНА ширина 390px (відсоткова width на це не
     впливає), тобто трек не може стати вужчим за 390+26 полів, і на телефоні
     колонка розпирається. Побачити це заміром сторожів не можна: .hero має
     overflow:hidden, тож бічного скролу немає, а ритм міряється по низу. */
  min-width: 0;
  padding: 14px 12px 12px;
  border: 1px solid var(--line);
  border-radius: calc(var(--r-xl) + 12px);
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--surface2) 92%, var(--accent)) 0%, var(--surface) 62%),
    var(--surface);
  box-shadow: var(--sh-hero);
  transform: rotate(1.5deg);
}
/* Світна грань корпусу — техніка, успадкована від .mock (видаленого, див.
   розділ на початку файла): абсолютна і без подій, тож ані в геометрію, ані в
   клікабельність не входить. */
.phone::before {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  padding: 1px;
  background: linear-gradient(160deg, var(--accent-line), transparent 42%, transparent 70%, color-mix(in srgb, var(--info) 30%, transparent));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}
/* Динамік. Абсолютний, тож сторож ритму його не бачить за побудовою. */
.phone::after {
  content: ""; position: absolute; top: 6px; left: 50%; width: 48px; height: 4px;
  transform: translateX(-50%); border-radius: 99px; pointer-events: none;
  background: color-mix(in srgb, var(--ink) 22%, transparent);
}
/* height:auto при заданих width/height у розмітці — знімок масштабується
   цілим. Ані object-fit, ані overflow тут немає навмисно: рамка НЕ ріже кадр,
   вона його обрамляє. Заокруглення екрана — те саме --r-xl, що й у карток. */
.phone img {
  width: 100%; height: auto;
  border-radius: var(--r-xl);
  border: 1px solid var(--line-soft);
}

/* --- Стрічка брендів ------------------------------------------------------
   Живе ВСЕРЕДИНІ .hero, а не окремою смугою body, і це не компонування, а
   вимога заміру. `scripts/check-landing.mjs` рахує вертикальний ритм за
   відстанню між сусідніми дітьми body: окрема смуга підмінила б сам предмет
   заміру — головним розривом став би стик «стрічка → перша секція», тобто
   сторож рахував би вже не те, про що його твердження. Кількість смуг body
   лишається десять. */
.marq {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; gap: 12px;
  /* Те саме, що й у .phone, але наслідок був дорожчий і повністю невидимий:
     доріжка стрічки має width:max-content (~1960px), і саме це число ставало
     мінімальним вмістом колонки. На ≤900 єдина колонка сітки виходила 1961.91px
     замість 350 — знімок телефона їхав на x=791, тобто ЦІЛКОМ ЗА ЕКРАН, і його
     мовчки зрізав overflow:hidden героя. Зелені були ВСІ сторожі: бічного
     скролу немає (зрізано), ритм по низу не змінився, контраст рахує кольори.
     Знайдено оком на знімку 390px. overflow:hidden на .marq-view від цього не
     рятує: він скорочує автоматичний мінімум лише для самого себе як елемента
     флексу, а не мінімальний вміст, що передається вгору. */
  min-width: 0;
}
.marq-lead {
  font-size: 12.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted);
  transition: color var(--dur) var(--ease);
}
.marq:hover .marq-lead { color: var(--ink); }
/* Згасання по краях — маскою, а не двома градієнтними накладками: накладка
   мусила б знати колір тла, а тло героя тут складене з трьох шарів. */
.marq-view {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 11%, #000 89%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 11%, #000 89%, transparent);
}
.marq-track { display: flex; width: max-content; }
.marq-set { display: flex; flex: none; }
.wm {
  position: relative;
  padding: 0 26px;
  font-size: 17px; font-weight: 800; letter-spacing: .06em;
  color: var(--muted);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
/* Роздільник — ПСЕВДОЕЛЕМЕНТ, а не символ у розмітці, і причина не в охайності.
   Кожен текстовий вузол сторінки потрапляє у звірку контрасту; приглушена
   крапка між назвами провалила б AA, лишаючись при цьому суто декоративною —
   тобто ми або зіпсували б звірку винятком, або підняли б яскравість
   роздільника до рівня самих назв. Крапка як тло текстом не є. */
.wm::after {
  content: ""; position: absolute; right: -3px; top: 50%; width: 5px; height: 5px;
  transform: translateY(-50%); border-radius: 50%;
  background: var(--accent-line);
}
.marq:hover .wm { color: var(--ink); }
@media (prefers-reduced-motion: no-preference) {
  /* Два ОДНАКОВІ набори підряд, зсув рівно на половину доріжки — тобто на
     ширину одного набору. Тому в мить перезапуску циклу картинка збігається
     сама з собою і стрибка не видно. */
  .marq-track { animation: gl-marquee 34s linear infinite; }
  .marq:hover .marq-track { animation-play-state: paused; }
}
@keyframes gl-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* --- FAQ на <details> -----------------------------------------------------
   Розкриття тримає браузер: ні JS, ні max-height-хаків. Висоту інтерполює сам
   рушій через interpolate-size і ::details-content; де їх немає — відповідь
   зʼявляється миттєво. Це запасний ВИГЛЯД, а не поломка: питання відкривається
   в будь-якому разі, різниця лише в плавності. */
#faq .grid { align-items: start; }
/* Без align-items:start згорнуте питання розтягується до висоти сусіда по
   ряду — заміряно 94px порожняви під однорядковим заголовком. */
#faq .card { padding: 0; }
#faq summary {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 18px;
  padding: 21px 26px; cursor: pointer;
  list-style: none;
  transition: color var(--dur) var(--ease);
}
#faq summary::-webkit-details-marker { display: none; }
#faq summary h3 { margin: 0; }
/* Маркер-стрілка: два бордери, повернуті на 45deg. Псевдоелемент, тож у замір
   ритму не входить; поворот тут — стан елемента керування, а не поява блока,
   і правило «прояв без transform» його не стосується. */
#faq summary::after {
  content: ""; flex: none;
  width: 9px; height: 9px; margin-top: 7px;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}
#faq details[open] > summary::after { transform: rotate(-135deg); }
#faq details > p { padding: 0 26px 24px; }
@supports selector(::details-content) and (interpolate-size: allow-keywords) {
  #faq details { interpolate-size: allow-keywords; }
  #faq details::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size var(--dur) var(--ease), content-visibility var(--dur);
    transition-behavior: allow-discrete;
  }
  #faq details[open]::details-content { block-size: auto; }
}

/* --- Компенсація вертикального ритму на телефоні --------------------------
   ЩО САМЕ ТУТ КОМПЕНСУЄТЬСЯ. Стик герой→секція міряється між ВИДИМИМ вмістом
   смуг, а не між їхніми краями. У старого .mock останнім видимим нащадком був
   рядок .mrow, і між ним та краєм картки лежали 22px ВЛАСНОГО падінга мокапа —
   тобто 22px «розриву», які насправді були нутрощами картки і до відступів
   сторінки не мали стосунку. Знімок у рамці й стрічка брендів стоять упритул
   до контентного боксу героя, тож ці 22px зникли разом із мокапом: заміряно на
   375 падіння 105px (×1.52) до 82px (×1.19) — формально ще вище порога 1.15,
   тобто зелений сторож цього не показав би.
   Повертаємо їх падінгом самої смуги, де вони й мають бути. */
@media (max-width: 900px) {
  .hero { padding-bottom: 60px; }
  /* Стеля така сама, як була в .mock: на 375 доступні 335px, тож обмеження
     працює лише на планшетах. Нахил на телефоні прибирається — на вузькому
     екрані він з'їдає бічні поля, а не додає обʼєму. */
  .phone { max-width: 420px; transform: none; }
}

/* ---------------------------------------------------------------------------
   Партія 3 (+3б, +3в): рамка вікна зі справжнім екраном у героях /sto, /fleet,
   /avtomagazyn і /marketplace
   --------------------------------------------------------------------------- */

/* --- Рамка вікна застосунку -----------------------------------------------
   Намальовані картки .mock у героях /sto, /fleet, /avtomagazyn і /marketplace
   замінені знімками справжніх екранів. Партія 3 лишала клас .mock чинним, бо
   його ще вживав /marketplace: екран вітрини можна було знімати лише ПІСЛЯ її
   редизайну (вона стала світлою, і кадр до редизайну застарів би одразу).
   Редизайн вітрини закінчено, кадр знято — тож .mock видалений (розділ «Мокапи
   героїв: класів більше немає» на початку файла).

   ЧОМУ ВІКНО, А НЕ ТЕЛЕФОН. CRM, Автопарк і Склад — desktop-first (у
   клієнтського застосунку навпаки, тому там .phone). Маркетплейс сам по собі
   адаптивний, але обіцянка сторінки — «видно, у кого деталь Є, за скільки і де»,
   а це сітка карток: на телефоні в кадр влізла б одна картка з двох колонок.
   Смуга з трьома крапками — єдине, що відрізняє рамку вікна від просто картки,
   і вона намальована ПСЕВДОЕЛЕМЕНТОМ: три кружечки як текст провалили б звірку
   контрасту, лишаючись декорацією.

   ЧОТИРИ ЗНІМКИ РІЗНИХ ПРОПОРЦІЙ у одній рамці, і це навмисно. /sto показує
   ПРАВУ панель картки замовлення (1120x1520, вертикальна) — ліва половина того
   екрана зайнята демонстраційним сміттям бази й у кадр не йде. /fleet показує
   сторінку витрат цілком (2560x1420, горизонтальна), /avtomagazyn — історію
   продажів із прибутком по чеках (2560x1492 → 900x525), /marketplace — головну
   вітрини від шапки до першого ряду карток (2304x1852 → 900x723). Рамка не
   задає пропорцій і не ріже кадр: висоту дає сам знімок через height:auto.

   ЄДИНИЙ СВІТЛИЙ ЕКРАН У ТЕМНОМУ ГЕРОЄВІ — це /marketplace, і рамка тут не
   оздоба, а те, що тримає кадр. Три інші знімки темні й зливаються з корпусом;
   світлий прямокутник без корпусу читався б як провал у верстці. Працює на
   ньому саме темна рамка: 30px смуги вікна з крапками згори, 10px полів по
   боках, власна тінь --sh-hero і світна грань ::before. Тобто прибрати падінг
   «бо знімок і так має рамку» на цій сторінці НЕ МОЖНА — на трьох інших це
   коштувало б вигляду, тут коштувало б сенсу. */
.laptop {
  position: relative;
  justify-self: center;
  width: 100%;
  /* min-width:0 тут ОБОВʼЯЗКОВЕ — та сама пастка, що в .phone і .marq, і
     підстава так само лежить поза цим правилом. Трек `1fr` — це
     `minmax(auto, 1fr)`, а `auto` для елемента сітки означає його МІНІМАЛЬНИЙ
     ВМІСТ; для картинки це її ВЛАСНА ширина (800 і 874 px), тобто на телефоні
     колонка розпиралась би до знімка. Заміром сторожів це НЕ ловиться: .hero
     має overflow:hidden, тож бічного скролу немає — знімок просто мовчки
     їде за екран. */
  min-width: 0;
  /* Верхнє поле більше за решту — це смуга вікна, у якій лежать крапки. */
  padding: 30px 10px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--surface2) 92%, var(--accent)) 0%, var(--surface) 62%),
    var(--surface);
  box-shadow: var(--sh-hero);
  /* Нахил той самий, що був у .mock: герой мусить лишитись упізнаваним. */
  transform: rotate(1.5deg);
}
/* Світна грань корпусу — та сама техніка, що в .phone (обидва успадкували її
   від видаленого .mock): абсолютна й без подій, тож ані в геометрію, ані в
   клікабельність не входить. */
.laptop::before {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  padding: 1px;
  background: linear-gradient(160deg, var(--accent-line), transparent 42%, transparent 70%, color-mix(in srgb, var(--info) 30%, transparent));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}
/* Три крапки в смузі вікна. Абсолютний псевдоелемент, тож сторож ритму його не
   бачить за побудовою (фільтр position === "static"). */
.laptop::after {
  content: ""; position: absolute; top: 12px; left: 16px;
  width: 44px; height: 8px; pointer-events: none;
  background:
    radial-gradient(circle 4px at 4px 4px, color-mix(in srgb, var(--ink) 24%, transparent) 96%, transparent 100%),
    radial-gradient(circle 4px at 22px 4px, color-mix(in srgb, var(--ink) 24%, transparent) 96%, transparent 100%),
    radial-gradient(circle 4px at 40px 4px, color-mix(in srgb, var(--ink) 24%, transparent) 96%, transparent 100%);
}
/* height:auto при заданих width/height у розмітці — знімок масштабується цілим.
   Ані object-fit, ані overflow тут немає навмисно: рамка НЕ ріже кадр. */
.laptop img {
  width: 100%; height: auto;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-soft);
}

@media (max-width: 900px) {
  /* Стеля 480, а не 420 як у .phone (і як було в .mock), і це компроміс уже
     ЧОТИРЬОХ пропорцій під одним класом: на 480 вертикальний знімок /sto
     виходить 651px заввишки, горизонтальний /fleet — 265px, /marketplace —
     проміжні 386px. Взяти 420 означало б зробити екран Автопарку завширшки з
     візитівку заради того, щоб панель СТО була на 100px нижчою.
     Працює це обмеження лише в смузі 741…900: від 740 і вниз колонка й так
     вужча за 480 (на 390 доступні 350). Нахил на телефоні прибирається — на
     вузькому екрані він зʼїдає бічні поля, а не додає обʼєму. */
  .laptop { max-width: 480px; transform: none; }
}
