/* =========================================================================
   GLNZ detailing — design tokens & base
   Signature: "sheen sweep" — diagonal glossy highlight, echoes light moving
   across freshly ceramic-coated paint. Used on hero load + interactive hover.
   ========================================================================= */

:root {
  /* ФАЗА 3A (финальная схема): единый множитель масштаба для hero/шапки.
     Эталон одобрялся при просмотре на 1536px (Windows-масштаб 125%), т.е.
     --glnz-s там равнялся 1536/1920 = 0.80 — это и есть верный базис, а не
     1280. Формула: 100vw/1920 (чистое отношение к нативному канвасу,
     то же, что делал --glnz-s), floor 0.80 держит его от 1536 и ниже
     (дальше — только перекомпоновка, Фаза 3B), потолок 1.0 выше 1920.
     Между 1536 и 1920 — пропорционально, БЕЗ отклонения от эталона.
     Все нативные размеры (типографика/паддинги/gap/высоты/гутеры) —
     calc(native * var(--u)) — один множитель на весь макет. */
  --u: clamp(0.80, calc(100vw / 1920px), 1);

  /* Color — graphite/black base, glossy blue accent, copper in small doses */
  --bg-page: #0d0d0f;
  --bg-panel: #16171a;
  --bg-panel-raised: #1f2024;
  --bg-input: #1b1c20;
  --border-hairline: #2a2b30;
  --border-copper: rgba(184, 115, 51, .38);

  --text-primary: #f4f5f7;
  --text-secondary: #9aa0ab;
  --text-tertiary: #6b7178;

  --blue: #1d6fe0;          /* buttons, icons, large numerals, borders */
  --blue-on-dark: #5b96ea;  /* inline text links on dark surfaces (AA-safe) */
  --blue-dim: rgba(29, 111, 224, .16);
  --copper: #b87333;        /* dividers, icon accents, hover trim — sparing */
  --success: #2fae66;
  --danger: #e0645c;

  /* Type */
  --font-display: 'Unbounded', system-ui, sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
  --font-mono: 'JetBrains Mono', 'Consolas', monospace;

  --fs-h1: clamp(2.05rem, 5.4vw + 1rem, 4.1rem);
  --fs-h2: clamp(1.6rem, 3vw + 1rem, 2.5rem);
  --fs-h3: clamp(1.1rem, 1vw + 1rem, 1.3rem);
  --fs-lead: clamp(1rem, 0.5vw + 0.9rem, 1.15rem);
  --fs-stat: clamp(1.5rem, 2.6vw + 1rem, 2.2rem);
  --fs-small: 0.875rem;

  /* Spacing / layout */
  --container-w: 1200px;
  --container-pad: 1.25rem;
  --section-pad: clamp(3rem, 6vw, 6rem);
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 14px;

  /* Header geometry — scroll-margin-top depends on this (uncompressed height).
     76px native @1920, scaled by --u like everything else in the hero/header
     system (Фаза 3A) — keeps the negative-margin overlay trick (see HEADER
     block) and anchor scroll-offset in sync with the header's real height. */
  --header-h: calc(76px * var(--u));
  --header-h-compact: 60px;
  --stickybar-h: 64px;

  /* Z-index — explicit scale, do not improvise numbers elsewhere */
  --z-dropdown: 200;   /* panels nested inside the header's own stacking context */
  --z-float: 400;      /* floating WhatsApp / Telegram buttons */
  --z-stickybar: 450;  /* mobile sticky bottom CTA bar */
  --z-header: 500;     /* sticky header, isolation: isolate */
  --z-cookie: 600;     /* cookie notice — above everything, dismissible */

  --ease: cubic-bezier(.22, .68, 0, 1);

  /* -----------------------------------------------------------------------
     GLNZ finalized hero tokens (source of truth: this block — the former
     glnz-design-tokens.md was removed from the repo as a duplicate).
     Kept separate from the tokens above — those still drive the
     not-yet-rebuilt sections (services/gallery/why/etc.). New sections
     should build from --glnz-* below; old vars retire once every section
     is rebuilt on the finalized hero system.
     ----------------------------------------------------------------------- */

  /* Base */
  --glnz-bg: #0A0A0A;

  /* Accent — warm copper (interactive) */
  --glnz-accent: #63400f;               /* primary button fill, "ЗАПИСАТЬСЯ" hover fill */
  --glnz-accent-border: #874805;        /* центральная кнопка "ЗАПИСАТЬСЯ" — обводка */
  --glnz-accent-border-soft: #e89338c9; /* кнопка "ЗАПИСАТЬСЯ" в шапке — обводка (полупрозрачная) */

  /* "Glossy" steel gradient — large logo/heading only */
  --glnz-gradient-steel: linear-gradient(90deg, #6E6E6E 0%, #FDFDFD 50%, #7A7A7A 100%);

  /* Text */
  --glnz-text-onbtn: #f4f7fb;       /* текст на кнопках, телефон */
  --glnz-text-white: #FFFFFF;       /* текст кнопки "ЗАПИСАТЬСЯ" (центр) */
  --glnz-eyebrow: #E8E8E8;          /* надстрочная строка (DETAILING · ЕКАТЕРИНБУРГ) */
  --glnz-subtitle: #9aa7b5;
  --glnz-nav-link: #9aa7b6;
  --glnz-nav-logo-small: #cfcfcf;
  --glnz-stat-value: #a3a3a3;       /* значения статистики — серые, не акцентные */
  --glnz-stat-label: #8A8F98;
  --glnz-border-secondary: #232a32;
  --glnz-shadow-color: rgba(0, 0, 0, .25); /* button drop-shadow / box-shadow ink, both same alpha */

  /* Background overlays/gradients */
  --glnz-overlay-hero: linear-gradient(90deg, #0A0A0AB3 0%, #0A0A0A40 35%, #0A0A0A66 70%, #0A0A0AF2 100%);
  --glnz-overlay-header: linear-gradient(90deg, #0A0A0AC0 0%, #0A0A0A00 100%); /* фон шапки ВНЕ hero (services.html и т.п.) — не трогать */

  /* Полупрозрачные плоские полосы hero (верх/низ) — сквозь них просвечивает
     фон. Один тон #0F0F0F = rgb(15,15,15), плотность крутится этими двумя
     числами, без градиентов. bottombar временно поднят до 0.80 (тестовое
     значение) — фото под нижней полосой заметно светлее, чем под шапкой,
     0.45 давало одинаковый % затемнения, но разный видимый результат
     (см. отчёт коммита c6d74bb). topbar не тронут. */
  --glnz-overlay-topbar: rgba(15, 15, 15, 0.45);
  --glnz-overlay-bottombar: rgba(15, 15, 15, 0.80);

  /* Вертикальная позиция фонового фото hero (.hero__bg, background-size:
     cover) — крутить одним числом, не трогая background-size. 50% = центр
     кадра (было). Поднято, чтобы колесо автомобиля не уходило под нижнюю
     полосу — см. блок HERO. */
  --glnz-hero-bg-pos-y: 55%;

  /* Вертикальная позиция видео-фона hero (.hero__video, object-fit: cover).
     Источник видео (1920×1080) кадрирован иначе, чем фото-эталон .hero__bg
     (2400×1600) — то же object-position-число НЕ даёт то же положение
     машины на экране. Подобрано расчётом по точке контакта переднего
     колеса с асфальтом (совмещено с эталоном .hero__bg при
     --glnz-hero-bg-pos-y: 55%), крутить одним числом. */
  --glnz-hero-video-pos-y: 61%;

  /* Type — Oswald (display) + Inter (body) */
  --glnz-font-display: 'Oswald', sans-serif;
  --glnz-font-body: 'Inter', sans-serif;

  /* Type scale — ФАЗА 3A (финал): КАЖДЫЙ размер = native@1920 × var(--u).
     Один множитель на всё — пропорции внутри макета сохраняются, H1 больше
     не отдельный случай (он и раньше был по факту той же формулой). */
  --glnz-fs-h1: calc(150px * var(--u));         /* Oswald 700, стальной градиент */
  --glnz-fs-eyebrow: calc(20px * var(--u));     /* Oswald 500, letter-spacing 3px, uppercase */
  --glnz-fs-subtitle: calc(30px * var(--u));    /* Oswald 400 */
  --glnz-fs-stat-value: calc(31.2px * var(--u)); /* Oswald 700, line-height 31px */
  --glnz-fs-stat-accent: calc(38px * var(--u)); /* Oswald 700, letter-spacing 5px */
  --glnz-fs-btn-center: calc(18px * var(--u));  /* Oswald 700, letter-spacing 2px */
  --glnz-fs-nav: calc(14px * var(--u));         /* Inter 500, letter-spacing 1.5px, uppercase */
  --glnz-fs-phone: calc(15px * var(--u));       /* Inter 600 */
  --glnz-fs-cta: calc(16px * var(--u));         /* Inter 600 / 500 */
  --glnz-fs-stat-label: calc(16px * var(--u));  /* Inter 400 */
  --glnz-fs-nav-logo: calc(22px * var(--u));    /* Inter 700, letter-spacing -1px — small nav logo + stats highlight text */

  /* Services section (Pencil: uslgi(main-page)3_2.pen, артборды "Услуги / покой" и "Услуги / ховер").
     Подзаголовок переиспользует --glnz-stat-label (#8A8F98) — значение
     совпадает, отдельного токена не заводим. Нижняя линия ПЛИТКИ при
     наведении по-прежнему на общем --glnz-accent-border (медь, см. ниже) —
     а вот разделитель под самой СЕКЦИЕЙ — отдельный приглушённый токен
     --glnz-section-divider, чтобы не трогать общий accent-border. */
  --glnz-services-bg: #0F0F0F;
  --glnz-services-heading: #D8D8D8;
  --glnz-services-name-color: #EBE1D6; /* тёплый айвори — название услуги на плитке, во всех состояниях */
  --glnz-services-desc: #C9CDD3;    /* описание услуги на фото плитки */
  --glnz-services-accent: #E89338;  /* сплошная медь — "→ подробнее", нижняя линия плитки */
  --glnz-section-divider: rgba(138, 143, 152, 0.30); /* приглушённый разделитель под секцией «Услуги» — тон подзаголовков hero, глуше меди */
  --glnz-services-scrim:
    linear-gradient(to bottom, #000000B3 0%, transparent 30%),
    linear-gradient(to bottom, transparent 55%, #000000A0 78%, #000000E6 100%);
  --glnz-services-scrim-hover: /* усиленный верхний край — читаемость имени на светлых кадрах (ceramic) */
    linear-gradient(to bottom, #000000CC 0%, transparent 35%),
    linear-gradient(to bottom, transparent 55%, #000000A0 78%, #000000E6 100%);

  --glnz-fs-services-h2: calc(64px * var(--u));    /* Oswald 700 */
  --glnz-fs-services-lead: calc(20px * var(--u));  /* Inter 400 */
  --glnz-fs-services-name: calc(21px * var(--u));  /* Oswald 500, uppercase, letter-spacing .04em */
  --glnz-fs-services-price: calc(22px * var(--u)); /* Oswald 500 */
  --glnz-fs-services-desc: calc(16px * var(--u));  /* Inter 400 */
  --glnz-fs-services-more: calc(15px * var(--u));  /* Inter 500 */
  --glnz-fs-services-promo-title: calc(38px * var(--u)); /* Oswald 600 — промо-блок в пустоте 2 ряда, N=5 */
  --glnz-fs-services-promo-text: calc(22px * var(--u));  /* Inter 400 */

  /* Process section («Как проходит запись», Pencil, montazh.md Секция 6).
     Orbitron — ТОЛЬКО для цифр шага (см. CLAUDE.md, исключение из общей
     пары шрифтов), сабсет из 4 глифов (1234) подключён в index.html.
     Цвет декора (линии/ромбы) — отдельный токен, --glnz-accent-border
     не трогаем (используется в других местах). */
  --glnz-font-process-num: 'Orbitron', sans-serif;
  --glnz-process-line: rgba(232, 147, 56, 0.40);
  --glnz-process-diamond: #6A4926;
  --glnz-process-num-gradient: linear-gradient(to bottom, #c8d3de 0%, #5e6e7c 100%);
  --glnz-fs-process-num: calc(110px * var(--u));   /* Orbitron 700 */
  --glnz-fs-process-title: calc(25px * var(--u));  /* Oswald 600 */
  --glnz-fs-process-desc: calc(19px * var(--u));   /* Inter 400 */
  --glnz-fs-why-title: calc(25px * var(--u));      /* Oswald 600 */
  --glnz-fs-why-desc: calc(19px * var(--u));       /* Inter 400 */

  /* Works section («Наши работы», Pencil: works2.pen).
     ВАЖНО: works2.pen нарисован при канвасе 1440 (фрейм секции 1438), а не
     1920 — все размеры оттуда пересчитаны в базис проекта множителем
     1920/1440 = 4/3. Плитка 400x280 → пропорция 10:7 (от базиса не зависит,
     идёт в aspect-ratio), зазор между плитками 54 → 72 нативных px.
     Боковой гутер макета (59) игнорируем: по решению владельца секция
     выравнивается по гутеру шапки, как «Услуги» и «Процесс».
     Рамка плитки — stroke 1px #79828c из макета; в палитре проекта такого
     серо-синего нет, поэтому отдельный токен, а не --glnz-accent-border.
     Ручка шторки — общая медь --glnz-services-accent. */
  --glnz-works-bg: #0F0F0F;
  --glnz-works-frame: #79828C;
  --glnz-works-gap: calc(72px * var(--u));
  --glnz-works-ratio: 10 / 7;
  --glnz-works-handle-w: calc(2px * var(--u));   /* линия среза */
  --glnz-works-grip: calc(44px * var(--u));      /* круглый захват на линии */
  --glnz-works-grip-bg: rgba(15, 15, 15, 0.55);

  /* Reviews section («Что говорят клиенты», montazh.md Секция 7).
     Макета нет — величины подобраны на взгляд от ритма соседних секций.
     Размеры шрифтов новых не заводим: текст отзыва — на общем
     --glnz-fs-services-lead (Inter 400 20px, тот же кегль, что подзаголовки
     секций), имя — на --glnz-fs-why-title слишком крупно, поэтому один
     собственный кегль на подпись.
     Рамка карточки — НЕ --glnz-works-frame (#79828C): та рисует обводку
     фотоплиток и по соседству спорила бы с ними по силе; здесь тот же
     серо-синий, но приглушённый до 45%, чтобы карточка читалась как текст,
     а не как ещё одна плитка. Фон карточки чуть светлее фона секции —
     подъём на 4 единицы яркости, ровно чтобы поймать край без рамки-ступеньки. */
  --glnz-reviews-bg: #0F0F0F;
  --glnz-reviews-card-bg: #131313;
  --glnz-reviews-border: rgba(121, 130, 140, 0.45);
  --glnz-reviews-gap: calc(40px * var(--u));
  --glnz-reviews-card-pad: calc(40px * var(--u));
  --glnz-fs-reviews-author: calc(17px * var(--u)); /* Oswald 500, letter-spacing .04em */
  /* Фоновый кадр секции появился позже, макетом-референсом
     (5 - Отзывы\images\backimage_var.pen): там фрейм секции залит
     #0b0b0bd6 ПОВЕРХ фото — то есть сплошное затемнение 84%, а не градиент.
     Значение перенесено из макета один в один. Под ним карточки остаются
     непрозрачными (--glnz-reviews-card-bg), поэтому текст отзывов от кадра
     не зависит вовсе; на просвет работает только заголовок секции,
     а он стоит в тёмной верхней части кадра. */
  --glnz-reviews-scrim: rgba(11, 11, 11, 0.84);

  /* Booking / CTA-запись («Записаться на детейлинг», montazh.md Секция 9).
     Макета нет — величины подобраны на взгляд от ритма соседних секций.
     Поле светлее фона секции ровно настолько, чтобы читаться как углубление
     и без рамки; рамка при этом та же приглушённая серо-синяя, что у карточек
     отзывов, — форма и отзывы стоят рядом и должны звучать одинаково.
     Красный и зелёный — единственные не-медные цвета в проекте, значения
     унаследованы от легаси --danger / --success, чтобы состояния формы
     не поехали при выводе старой палитры. */
  --glnz-booking-bg: #0F0F0F;
  --glnz-booking-field-bg: #151515;
  --glnz-booking-field-border: rgba(121, 130, 140, 0.45);
  --glnz-booking-field-h: calc(64px * var(--u));
  --glnz-booking-gap: calc(60px * var(--u));   /* между колонкой формы и заметками */
  --glnz-booking-row-gap: calc(28px * var(--u)); /* между полями формы */
  --glnz-booking-error: #E0645C;
  --glnz-booking-ok: #6FDBA0;
  --glnz-booking-ok-bg: rgba(47, 174, 102, 0.12);
  --glnz-booking-ok-border: rgba(47, 174, 102, 0.40);
  --glnz-fs-booking-label: calc(15px * var(--u)); /* Inter 500, uppercase, letter-spacing .06em */
  --glnz-fs-booking-input: calc(17px * var(--u)); /* Inter 400 — вводимый текст и плейсхолдер */
  --glnz-fs-booking-note: calc(15px * var(--u)); /* Inter 400 — ошибки, согласие, статус */

  /* Contacts + Footer («Как нас найти» + подвал, montazh.md Секция 8 и Подвал).
     Макета нет — величины подобраны на взгляд от ритма соседних секций.
     Квадратная кнопка мессенджера повторяет .why-item__icon (квадрат, рамка
     --glnz-accent-border-soft, медный значок), только мельче: это тот же
     элемент языка, второй его вариант заводить незачем.
     Фон подвала темнее полотна (#0A0A0A = --glnz-bg, тон hero) — подвал
     должен читаться как край страницы, а не как ещё одна секция. */
  --glnz-contacts-bg: #0F0F0F;
  --glnz-contacts-gap: calc(60px * var(--u));   /* между списком и картой */
  --glnz-contacts-row-gap: calc(36px * var(--u)); /* между строками контактов */
  --glnz-contacts-icon: calc(56px * var(--u));  /* квадрат иконки строки и мессенджера */
  --glnz-contacts-map-h: calc(440px * var(--u));
  --glnz-contacts-map-border: rgba(121, 130, 140, 0.45); /* та же рамка, что у карточек отзывов и полей формы */
  --glnz-fs-contacts-label: calc(15px * var(--u)); /* Inter 500, uppercase, letter-spacing .06em */
  --glnz-fs-contacts-value: calc(20px * var(--u)); /* Inter 400 */

  --glnz-footer-bg: #0A0A0A;
  --glnz-footer-gap: calc(60px * var(--u));
  --glnz-footer-link-gap: calc(18px * var(--u));  /* было 14 литералом — подросло вслед за кеглем ссылок */
  /* Логотип подвала — пара строк в духе hero, снята с референса
     6 - Подвал\footer-left.jpg (скрин в базисе 1920): надстрочная строка
     11px по высоте прописных → Oswald ≈15px, «GLNZ» 61px по высоте
     прописных → Oswald ≈84px. Трекинг надстрочной подобран так, чтобы её
     ширина совпала с шириной слова (в референсе 141 против 144px) —
     это и есть главная пропорция пары. Буквально hero (150px) в подвале
     не нужен: там строка — заголовок страницы, здесь — подпись. */
  --glnz-fs-footer-eyebrow: calc(15px * var(--u)); /* Oswald 500, uppercase */
  --glnz-footer-eyebrow-tracking: calc(2.25px * var(--u));
  --glnz-fs-footer-word: calc(84px * var(--u));   /* Oswald 700, стальной градиент */
  /* Кегли колонок подняты: на ширине 1920 прежние 15/17 читались мелко
     относительно поля. Ориентир — типографика «Контактов» по соседству
     (label 15 / value 20); подвал берёт на ступень крупнее по ссылкам,
     потому что здесь это единственный текст в колонке. */
  --glnz-fs-footer-title: calc(18px * var(--u));  /* Oswald 500, uppercase, letter-spacing .1em (было 15) */
  --glnz-fs-footer-link: calc(21px * var(--u));   /* Inter 400 (было 17) */
  --glnz-fs-footer-slogan: calc(21px * var(--u)); /* Inter 400 — раньше делил токен со ссылками */
  --glnz-fs-footer-copy: calc(16px * var(--u));   /* Inter 400 (было 15) */

  /* ---------------------------------------------------------------------
     SERVICES PAGE — страница услуг (эталон: services_hero5_3.html, холст
     1920). Все значения ниже сняты с эталона один в один; там, где цвет
     уже есть в палитре, отдельный токен НЕ заводился, а переиспользован
     существующий:
       #f4f7fb  заголовки и значения  -> --glnz-text-onbtn
       #9aa7b6  основной абзац        -> --glnz-nav-link
       #a3a3a3  statement в hero      -> --glnz-stat-value
       #E89338  номер секции, цена    -> --glnz-services-accent
       #63400F  заливка кнопки        -> --glnz-accent
       #232a32  рамка второй кнопки   -> --glnz-border-secondary
       #0A0A0A / #0F0F0F фоны секций  -> --glnz-bg / --glnz-services-bg
     --------------------------------------------------------------------- */
  /* Волосяная линия эталона #FFFFFF14 — верхняя черта секции, разделители
     характеристик и строк списка услуг в hero. Одна на все три места. */
  --glnz-svc-hairline: rgba(255, 255, 255, 0.08);
  --glnz-svc-label: #77818C;   /* надзаголовок, ключи характеристик, подпись под фото */
  --glnz-svc-lead: #C3CCD8;    /* вводный абзац секции и название услуги в списке hero */
  --glnz-svc-tick: rgba(232, 147, 56, 0.35);  /* короткое тире у номера секции (#E8933859) */
  --glnz-svc-index: rgba(232, 147, 56, 0.60); /* номер в списке услуг hero (#E8933899) */
  /* Нижняя полоса hero услуг: прозрачная слева, глухая справа — под
     statement. У hero главной полоса ровная (--glnz-overlay-bottombar),
     это другой приём, поэтому отдельный токен. */
  --glnz-svc-hero-bottombar: linear-gradient(90deg, #0A0A0A00 0%, #0A0A0AF5 40%, #0A0A0A 100%);
  /* Подъём кадра hero. В эталоне слой 1920×860 стоит на top:-90px внутри
     секции той же высоты: верхние 90 обрезаются, нижние 90 секции остаются
     фоном, и машина за счёт этого стоит выше. Через background-position
     то же не делается: кадр 1584×672 шире бокса 1920×860, cover масштабирует
     его ПО ВЫСОТЕ, вертикальной обрезки нет — и позиция по Y ни на что
     не влияет. Поэтому подъём отдельным числом, крутится одним токеном. */
  --glnz-svc-hero-bg-shift: calc(-90px * var(--u));
  /* Высота hero и слоя кадра — 860 нативных из холста. Одно число на три
     места (.svc-hero, .svc-hero__bg и слои hover-подсветки), потому что
     геометрия световых накладок считается ОТ этого слоя: разъедутся
     высоты — уедут метки. */
  --glnz-svc-hero-h: calc(860px * var(--u));
  /* Геометрия списков услуг в hero. Вынесена в токены не ради порядка:
     от неё считается начало выноски hover-подсветки, и разъехаться эти
     два места не должны — правка числа здесь двигает и список, и линию.
     Черта строки ровно 1px и НЕ масштабируется на --u (волосяная линия),
     поэтому шаг строки = высота + 1px, а не 53px * --u: к четвёртой строке
     разница набегает в 4 нативных px. */
  --glnz-svc-nav-gutter: calc(110px * var(--u)); /* гутер списков = общий гутер контента */
  --glnz-svc-nav-w: calc(240px * var(--u));      /* ширина колонки списка */
  --glnz-svc-nav-top: calc(150px * var(--u));    /* от верха hero до верхней черты списка */
  --glnz-svc-nav-link-h: calc(52px * var(--u));  /* высота строки без черты */
  --glnz-svc-nav-rule: 1px;                      /* черта над списком и под каждой строкой */
  /* Два слоя поверх кадра секции: краевая растяжка в фон секции (95%)
     и ровная вуаль (30%). Тон берётся от фона своей секции, поэтому
     пар две — тёмная и светлая. */
  --glnz-svc-fade-dark: #0A0A0AF2;
  --glnz-svc-veil-dark: #0A0A0A4D;
  --glnz-svc-fade-light: #0F0F0FF2;
  --glnz-svc-veil-light: #0F0F0F4D;

  /* === HERO-HOVER: токены ================================================
     Подсветка списка услуг в hero страницы услуг. Эталон services_hero7.html,
     вариант A («свет и метка», кадр 1). Цвета сняты с эталона один в один.
     Кольцо-маркер выноски — #E8933859, то же значение, что у --glnz-svc-tick,
     отдельный токен не заводился (политика блока SERVICES PAGE выше).
     ===================================================================== */
  --glnz-svc-fx-dim: #04060A59;                /* затемнение сцены под светом */
  --glnz-svc-fx-lead: #5A6472;                 /* название НЕактивной услуги во время наведения */
  --glnz-svc-fx-index: rgba(232, 147, 56, 0.22);  /* её номер (#E8933838) */
  --glnz-svc-fx-sub: #8A939E;                  /* расшифровка детали под подписью выноски */
  --glnz-svc-fx-leader-start: linear-gradient(90deg, #E8933800 0%, #E89338CC 100%);
  --glnz-svc-fx-leader-end: linear-gradient(-90deg, #E8933800 0%, #E89338CC 100%);
  --glnz-svc-fx-leader-drop: linear-gradient(180deg, #E8933866 0%, #E89338 100%);
  --glnz-svc-fx-dur: 320ms;                    /* переход всех состояний подсветки */
  --glnz-svc-fx-shift: calc(14px * var(--u));  /* сдвиг активной строки вправо */
  /* Зазор между краем колонки списка и ближним концом линии выноски.
     В эталоне он симметричен с обеих сторон (слева линия начинается
     на 26 правее края колонки, справа — на 26 левее), значит намеренный. */
  --glnz-svc-fx-callout-gap: calc(26px * var(--u));
  /* Порог гашения выноски: минимальная длина горизонтальной линии.
     Линия короче — выноска гаснет целиком, свет и подсветка списка
     остаются. Нужен потому, что концы линии живут в разных системах:
     ближний стоит на гутере, дальний едет вместе с кадром, и при сужении
     окна линия схлопывается, а подпись наползает на пункт меню.
     Порог общий, но срабатывает у каждой услуги на своей ширине — длина
     линии у всех разная. При 1920 самая короткая линия у 07 (94 нативных
     px), поэтому 72 — потолок, выше ставить нельзя: погаснет там, где
     всё ещё хорошо. Величина стартовая, подбирается владельцем. */
  --glnz-svc-fx-callout-min: calc(72px * var(--u));
  /* Подложка под подписью выноски: подписи теряются на светлых участках
     кузова. Приём тот же, что у --glnz-services-scrim, — градиент,
     растворяющийся в прозрачность, только по двум осям: подпись это
     короткая строка, а не полоса во всю плитку. Ни рамки, ни плашки:
     видимого края у пятна нет. Цвет готовый, --glnz-svc-fade-dark,
     новых цветовых токенов не заводим.
     Три величины ниже — СТАРТОВЫЕ, подбираются владельцем в DevTools. */
  --glnz-svc-fx-plate: radial-gradient(ellipse closest-side,
    var(--glnz-svc-fade-dark) 0%, transparent 100%);
  --glnz-svc-fx-plate-x: calc(48px * var(--u));  /* вылет пятна за текст по бокам */
  --glnz-svc-fx-plate-y: calc(16px * var(--u));  /* вылет сверху и снизу */
  --glnz-svc-fx-plate-alpha: .55;                /* глубина затемнения в центре */

  /* Inter Tight — третье семейство, только на странице услуг: заголовки
     секций (700) и значения характеристик (600). См. CLAUDE.md. */
  --glnz-font-tight: 'Inter Tight', sans-serif;

  --glnz-fs-svc-h2: calc(92px * var(--u));    /* Inter Tight 700, трекинг -2px, интерлиньяж 97/92 */
  --glnz-fs-svc-lead: calc(19px * var(--u));  /* Inter 400, интерлиньяж 30/19; тот же кегль у значения характеристики (Inter Tight 600) */
  --glnz-fs-svc-body: calc(15px * var(--u));  /* Inter 400, интерлиньяж 26/15 */
  --glnz-fs-svc-meta: calc(12px * var(--u));  /* Inter 500 разрядкой 2px — надзаголовок и ключи; и 400 разрядкой 0.6px — подпись под фото */
  --glnz-fs-svc-num: calc(10px * var(--u));   /* Inter 500, разрядка 1.5px — номера 01–07 */
  --glnz-fs-svc-callout: calc(11px * var(--u)); /* Inter 500/400 — подпись детали в выноске hero */
  --glnz-fs-svc-price: calc(27px * var(--u)); /* Inter 700, разрядка .3px, медь */

  /* about.html — страница «О студии». Язык типографики общий со страницей
     услуг (Inter Tight на заголовках, токены --glnz-fs-svc-* и цветовые
     --glnz-svc-*/--glnz-services-accent переиспользуются один в один —
     см. about.html). Ниже только величины, которых в этом языке ещё не
     было: сняты с эталона about_as.html, холст 1920. */
  --glnz-fs-about-h2: calc(60px * var(--u)); /* Inter Tight 700, трекинг -0.0233em (≈ -1.4px при 60px, см. .about__heading — em, не px, чтобы не разъезжаться на порогах), интерлиньяж 66/60 — заголовки секций и CTA */
  --glnz-fs-about-stat: calc(44px * var(--u));       /* Inter Tight 700, трекинг -1.6px — показатели «В цифрах» */
  --glnz-fs-about-brand: calc(22px * var(--u));      /* Inter Tight 600, трекинг -0.4px — названия партнёров «Материалов» */
  --glnz-fs-about-item-title: calc(21px * var(--u)); /* Inter Tight 600, трекинг -0.3px — заголовок принципа в «Подходе» */
  --glnz-fs-about-body-lg: calc(17px * var(--u));    /* Inter 400, интерлиньяж 29/17 — вводный абзац «В цифрах» (в эталоне у CTA свой кегль 18, см. --glnz-fs-about-cta-lead) */
  /* Сверка с эталоном (второй заход): часть переиспользованных классов
     services.html (.svc__num/.svc__label/.svc__caption/.svc__spec-key/
     .svc__spec-value) на about.html обслуживает СВОИ и ЧУЖИЕ по кеглю
     тексты одновременно — там, где эталон about_as.html даёт другую
     величину для конкретного вхождения, класс не трогаем (он верен для
     остальных мест), а добавляем точечный селектор с одним из токенов
     ниже. Разрядка (letter-spacing) у этих же вхождений — inline calc(),
     как везде в файле, отдельных токенов под неё не заводим. */
  --glnz-fs-about-note-key: calc(11px * var(--u));   /* Inter 500, трекинг 2px — «ПЕРВЫЙ ШАГ» (интро и CTA); .svc__num в остальных местах (индексы 01–05) — 10px, эталон совпадает, не трогаем */
  --glnz-fs-about-item-index: calc(11px * var(--u)); /* Inter 500, трекинг 1.5px — индекс принципа в «Подходе» (01–04); отдельный от индекса эйбрау (10px) */
  --glnz-fs-about-caption-lg: calc(13px * var(--u)); /* Inter 400 — подпись галереи «Пространство», заметка «Материалов», адрес CTA (трекинг у каждой свой, эталон) */
  --glnz-fs-about-kind: calc(11px * var(--u));       /* Inter 500, трекинг 1.6px — вид материала у партнёра («Материалы») */
  --glnz-fs-about-stat-key: calc(11px * var(--u));   /* Inter 500, трекинг 2px (как у .svc__spec-key) — ключ показателя «В цифрах»; .svc__spec-key в «Команде» — 12px, эталон совпадает, не трогаем */
  --glnz-fs-about-role-value: calc(18px * var(--u)); /* Inter Tight 600, трекинг -0.2px (как у .svc__spec-value) — значение роли «Команды» */
  --glnz-fs-about-cta-lead: calc(18px * var(--u));   /* Inter 400, интерлиньяж 30/18 — лид CTA, отдельно от --glnz-fs-about-body-lg (17, «В цифрах») */

  /* contacts.html — страница «Контакты» (эталон: Pencil «Страница —
     Контакты», холст 1920). Язык типографики общий с about.html: заголовок
     страницы на .svc__title, заголовки секций на .about__heading, тексты —
     .svc__lead/.svc__body/.svc__caption. Кегли, которые уже есть, НЕ
     дублируются: ключ строки 11px — --glnz-fs-about-note-key, заголовок
     способа 21px — --glnz-fs-about-item-title, индекс способа 11px —
     --glnz-fs-about-item-index, meta способа 11px — --glnz-fs-about-kind.
     Префикс --glnz-cts-* (не --glnz-contacts-*): вторая группа занята
     секцией «Как нас найти» на главной, это разные блоки.
     Медь 70% и 50% — в палитре таких ступеней ещё не было
     (--glnz-svc-tick 35%, --glnz-svc-index 60%). */
  --glnz-cts-key: rgba(232, 147, 56, 0.70);     /* ключи строк контактов и meta способов (#E89338B3) */
  --glnz-cts-caption: rgba(232, 147, 56, 0.50); /* подпись под картой (#E8933880) */
  --glnz-cts-pin-bg: rgba(10, 10, 10, 0.85);    /* плашка бейджа поверх карты (#0A0A0AD9) */
  --glnz-cts-list-w: calc(520px * var(--u));    /* колонка контактов в Split */
  --glnz-cts-gap: calc(120px * var(--u));       /* Split: между контактами и картой */
  --glnz-cts-icon: calc(52px * var(--u));       /* квадрат иконки строки контактов */
  --glnz-cts-map-h: calc(700px * var(--u));     /* бокс карты — 1040x700 на канвасе 1920 */
  --glnz-fs-cts-btn: calc(14px * var(--u));     /* Inter 500, трекинг .3px — подпись мессенджера и бейдж карты */

  /* Появление секций при прокрутке — длительность/easing/величина сдвига
     сняты с готовой анимации входа hero (.hero__cta-col, translateX 70px
     и .hero__stats-col, translateX 70px: обе .9s cubic-bezier(.22,1,.36,1);
     вертикальный сдвиг — с .hero__book-wrap, translateY 60px, та же пара
     duration/ease), чтобы появление секций двигалось так же, как hero. */
  --glnz-reveal-shift-x: 70px;
  --glnz-reveal-shift-y: 60px;
  --glnz-reveal-duration: .9s;
  --glnz-reveal-ease: cubic-bezier(.22, 1, .36, 1);
  --glnz-reveal-delay-step: 250ms;
}

/* Gradient-clipped text — steel "glossy" effect on large logo/headings only */
.glnz-text-steel {
  background-image: var(--glnz-gradient-steel);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg-page);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
ul { list-style: none; margin: 0; padding: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, select, textarea { font: inherit; color: inherit; }
h1, h2, h3, p, figure { margin: 0; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

:focus-visible {
  outline: 2px solid var(--blue-on-dark);
  outline-offset: 3px;
  border-radius: 2px;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0; margin: -1px;
}
a.visually-hidden:focus {
  position: fixed;
  top: .75rem; left: .75rem;
  width: auto; height: auto;
  clip: auto; white-space: normal;
  z-index: var(--z-cookie);
  background: var(--blue);
  color: #fff;
  padding: .7rem 1.1rem;
  border-radius: var(--radius-sm);
  font-weight: 600;
  font-size: .9rem;
}

.icon-sprite { display: none; }

/* Легаси-лого. Осталось РОВНО ОДНО место — шапка policy.html; в подвале
   его сменил .footer__logo. Переехало сюда из удалённого блока FOOTER,
   чтобы не висеть в чужой секции. Умрёт вместе с перевёрсткой policy.html. */
.logo {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: .01em;
  white-space: nowrap;
}
.logo-sub {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: .68rem;
  color: var(--text-secondary);
  letter-spacing: .04em;
  margin-left: .3rem;
}

/* ---------- Layout helpers ---------- */
.container {
  width: 100%;
  max-width: var(--container-w);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

.section { padding-block: var(--section-pad); }
.section--panel { background: var(--bg-panel); }

.section-head { max-width: 640px; margin-bottom: clamp(1.75rem, 4vw, 2.75rem); }
.section-head--center { margin-inline: auto; text-align: center; }
h2 {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.12;
}
.section-lead {
  margin-top: .85rem;
  color: var(--text-secondary);
  font-size: var(--fs-lead);
  max-width: 52ch;
}

/* ---------- Buttons ---------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .85rem 1.5rem;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: .95rem;
  letter-spacing: .01em;
  overflow: hidden;
  white-space: nowrap;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), background-color .18s var(--ease);
}
.btn:active { transform: translateY(1px); }

.btn--accent {
  background: var(--blue);
  color: #fff;
  box-shadow: 0 1px 0 rgba(255,255,255,.16) inset, 0 8px 20px -10px rgba(29,111,224,.65);
}
.btn--accent:hover { background: #2a7ce8; }
.btn--accent::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,.35) 45%, transparent 60%);
  transform: translateX(-120%);
}
.btn--accent:hover::after { transform: translateX(120%); transition: transform .7s var(--ease); }

.btn--lg { padding: 1rem 1.9rem; font-size: 1rem; }
.btn--sm { padding: .6rem 1.1rem; font-size: .85rem; }
.btn--block { width: 100%; }

/* ---------- Placeholder photo blocks ---------- */
.placeholder-photo {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    repeating-linear-gradient(135deg, #1c1d21 0 14px, #19191d 14px 28px);
  border: 1px dashed var(--border-hairline);
  border-radius: var(--radius-md);
  overflow: hidden;
  color: var(--text-tertiary);
}
.placeholder-photo__label {
  font-family: var(--font-mono);
  font-size: .72rem;
  line-height: 1.5;
  letter-spacing: .02em;
  text-align: center;
  max-width: 26ch;
  padding: 1rem;
  background: rgba(13,13,15,.55);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-sm);
}
.ratio-1x1  { aspect-ratio: 1 / 1; }

.photo-cover { width: 100%; height: 100%; object-fit: cover; }

/* ---------- Real photo frame (replaces .placeholder-photo once a photo lands) ---------- */
.photo-frame {
  position: relative;
  overflow: hidden;
  background: var(--bg-panel-raised);
  border: 1px solid var(--border-hairline);
  border-radius: var(--radius-md);
}

/* =========================================================================
   HEADER (ФАЗА 3A) — sticky, живёт ВНЕ hero и визуально «наплывает» на его
   фото: header не занимает своё место в потоке (margin-bottom утягивает
   hero под себя), поэтому по умолчанию фон — прозрачный градиент
   Pencil-эталона (видно фото hero сквозь шапку), а сплошной тёмный —
   только после скролла (.is-scrolled). hero компенсирует утяжку через
   padding-top на .hero__body (см. блок HERO), фоновые слои hero остаются
   полноблидными (inset:0), сдвиг их не касается.
   ВАЖНО: утяжка — на РЕАЛЬНОЙ высоте шапки calc(72px*var(--u)) (нативная
   высота Top Nav), а не на общем сайтовом --header-h (76px, старое site-wide
   значение для scroll-margin-top других секций — не совпадает с
   Pencil-высотой). Раньше здесь стоял var(--header-h) — расхождение в 4px
   давало на hero__body лишний (неточный) отступ сверху. */
.site-header {
  position: sticky;
  top: 0;
  isolation: isolate;
  z-index: var(--z-header);
  margin-bottom: calc(-72px * var(--u));
  background-image: var(--glnz-overlay-header);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  border-bottom: 1px solid transparent;
  transition: background-color .2s var(--ease), border-color .2s var(--ease), padding-block .2s var(--ease), box-shadow .2s var(--ease);
}
/* .site-header общая (см. services.html/policy.html) — плоскую
   полупрозрачную полосу даём ТОЛЬКО там, где шапка реально наплывает на
   hero (#hero в разметке страницы: index.html). На остальных страницах
   фон шапки остаётся прежним градиентом выше.
   Страница услуг вернулась в эту же категорию: её hero (.svc-hero,
   эталон services_hero5_3.html) рисует шапку именно градиентом
   --glnz-overlay-header — в эталоне Top Nav залит ровно им. */
body:has(#hero) .site-header {
  background-image: none;
  background-color: var(--glnz-overlay-topbar);
}
/* Разделитель по нижнему краю шапки — на ВСЕХ страницах, а не только в
   контексте hero главной, как было раньше: без линии шапка сливалась с
   полотном страницы в самом верху (видно на contacts.html и about.html,
   где вверху ровный тёмный фон, а не фото hero). Толщина и цвет — те же
   1px и --glnz-section-divider, что у линии над подвалом (.footer::before);
   концы растворяются, как у разделителя под секцией «Услуги»
   (.services::after) — border градиентом не заливается, поэтому ::after,
   а не border-bottom. Линия статична и от прокрутки не зависит: собственный
   border-bottom шапки по-прежнему включается только в .is-scrolled. */
.site-header::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent 0%,
    var(--glnz-section-divider) 14%,
    var(--glnz-section-divider) 86%,
    transparent 100%
  );
}
.site-header.is-scrolled {
  background-image: none;
  background-color: rgba(10, 10, 10, .88);
  backdrop-filter: blur(10px);
  border-bottom-color: var(--glnz-border-secondary);
  box-shadow: 0 12px 24px -18px rgba(0,0,0,.6);
}
.header-inner {
  max-width: var(--container-w);
  margin-inline: auto;
  padding: 1rem var(--container-pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--header-h);
  transition: min-height .2s var(--ease);
}
.site-header.is-scrolled .header-inner { min-height: var(--header-h-compact); }

/* Pencil nav-logo: hexagon mark + wordmark (small companion to the hero's giant steel "GLNZ") */
.glnz-logo {
  display: inline-flex;
  align-items: center;
  gap: 0; /* эталон: "Left" (иконка+GLNZ) объявлен с gap:0px — раньше стояло 8px, лишний зазор */
  font-family: var(--glnz-font-body);
  font-weight: 700;
  font-size: var(--glnz-fs-nav-logo);
  letter-spacing: calc(-1px * var(--u));
  color: var(--glnz-nav-logo-small);
  white-space: nowrap;
}
.glnz-logo__mark {
  width: calc(33px * var(--u));
  height: calc(30px * var(--u));
  flex-shrink: 0;
  /* эталон: 2 стэкнутых drop-shadow(0px 4px 2px #00000040) — раньше был
     один произвольный drop-shadow(2px 1px), y-offset native 4px давал >1px
     расхождение на 1536 */
  filter:
    drop-shadow(0 calc(4px * var(--u)) calc(2px * var(--u)) var(--glnz-shadow-color))
    drop-shadow(0 calc(4px * var(--u)) calc(2px * var(--u)) var(--glnz-shadow-color));
}

.main-nav__links {
  display: flex;
  gap: calc(36px * var(--u)); /* см. @media(min-width:1025px) ниже — mobile-default gap:0 иначе побеждает в каскаде для десктопа, там тоже нужен × var(--u) */
}
.main-nav__links a {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-nav);
  font-weight: 500;
  letter-spacing: calc(1.5px * var(--u));
  text-transform: uppercase;
  color: var(--glnz-nav-link);
  padding-block: .3rem;
  border-bottom: 1px solid transparent;
  white-space: nowrap;
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.main-nav__links a:hover,
.main-nav__links a:focus-visible { color: var(--glnz-text-onbtn); border-color: var(--copper); }

.header-actions { display: flex; align-items: center; gap: calc(24px * var(--u)); }
.header-phone {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-phone);
  font-weight: 600;
  letter-spacing: calc(.5px * var(--u));
  color: var(--glnz-text-onbtn);
  white-space: nowrap;
}
.header-phone:hover { color: var(--glnz-accent-border-soft); }

/* Pencil "ЗАПИСАТЬСЯ" — copper-outlined ghost button, fill sweeps in on hover */
.glnz-header__cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  isolation: isolate;
  padding: calc(10px * var(--u)) calc(22px * var(--u));
  border: 1px solid var(--glnz-accent-border-soft);
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-nav);
  font-weight: 600;
  letter-spacing: calc(1px * var(--u));
  text-transform: uppercase;
  color: var(--glnz-text-white);
  white-space: nowrap;
  transition: border-color .45s ease;
}
.glnz-header__cta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--glnz-accent);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform .45s cubic-bezier(.4, 0, .2, 1);
}
.glnz-header__cta:hover::before { transform: scaleX(1); }
.glnz-header__cta:hover { border-color: var(--glnz-accent); }
.glnz-header__cta--block { width: 100%; }
@media (prefers-reduced-motion: reduce) {
  .glnz-header__cta::before { transition-duration: .01ms !important; }
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem; height: 2.4rem;
  border-radius: 999px;
  border: 1px solid var(--border-hairline);
}
.icon-btn svg { width: 1.05rem; height: 1.05rem; }

/* Pencil-стиль для мобильной круглой кнопки звонка в шапке: тонкая рамка
   --glnz-accent-border-soft (сверено — тот же токен, что реально стоит в
   border у .glnz-header__cta, см. правило ниже; никакого gradient/filter/
   box-shadow тут нет и не было — если кайма читается «мягкой», это сам
   токен полупрозрачный (#e89338c9), одинаково у обеих кнопок намеренно).
   Цвет иконки — --glnz-nav-link (как у пунктов меню рядом), фон прозрачный
   (наследуется от .icon-btn, заливки нет). Круг и штрих иконки — одна
   толщина (1.5px), значок увеличен относительно круга (был мелковат). */
.glnz-icon-btn {
  border-width: 1.5px;
  border-color: var(--glnz-accent-border-soft);
  color: var(--glnz-nav-link);
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.glnz-icon-btn:hover { color: var(--glnz-text-onbtn); border-color: var(--glnz-accent); }
.glnz-icon-btn svg { width: 1.5rem; height: 1.5rem; }

.burger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 2.4rem; height: 2.4rem;
  border-radius: var(--radius-sm);
}
.burger span {
  display: block; width: 1.3rem; height: 2px;
  background: var(--text-primary);
  transition: transform .2s var(--ease), opacity .2s var(--ease);
}
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Mobile nav panel — separate stacking layer within the isolated header */
.main-nav {
  position: absolute;
  inset: 100% 0 auto 0;
  z-index: var(--z-dropdown);
  background: var(--bg-panel);
  border-bottom: 1px solid var(--border-hairline);
  padding: 1.25rem var(--container-pad) 1.75rem;
  transform: translateY(-8px);
  opacity: 0;
  visibility: hidden;
  transition: transform .2s var(--ease), opacity .2s var(--ease), visibility .2s;
}
.main-nav.is-open { transform: translateY(0); opacity: 1; visibility: visible; }
.main-nav__links { flex-direction: column; gap: 0; }
.main-nav__links a { display: block; padding-block: .85rem; border-bottom: 1px solid var(--border-hairline); }
.main-nav__foot {
  display: flex; flex-direction: column; gap: .85rem;
  margin-top: 1.25rem;
}
.main-nav__foot .header-phone { font-size: 1.05rem; }

@media (min-width: 1025px) {
  .burger, .main-nav__mobile-only { display: none; }
  .main-nav {
    position: static;
    background: none; border: 0; padding: 0;
    transform: none; opacity: 1; visibility: visible;
    display: flex; flex: 1 1 0; justify-content: center;
  }
  .main-nav__links { flex-direction: row; gap: calc(36px * var(--u)); } /* mobile-default gap:0 (строка выше) иначе побеждает в каскаде */
  .main-nav__links a { padding-block: .3rem; border-bottom: 1px solid transparent; }
  .main-nav__foot { display: none; }
  .header-actions .header-phone { display: inline; }

  /* Pencil Top-Nav geometry — 72px bar @1920, три равные flex-колонки
     (лого start / меню center / actions end). Всё × var(--u): высота бара
     и боковые гутеры так же, как остальной hero/header. */
  .header-inner {
    height: calc(72px * var(--u));
    min-height: 0;
    padding: 0 calc(110px * var(--u));
    max-width: none;
    margin-inline: 0;
    gap: 0;
  }
  .site-header.is-scrolled .header-inner { height: calc(72px * var(--u)); min-height: 0; }
  .glnz-logo { flex: 1 1 0; justify-content: flex-start; }
  .header-actions { flex: 1 1 0; justify-content: flex-end; }
}
@media (max-width: 1024px) {
  .header-actions .header-phone,
  .header-actions .glnz-header__cta { display: none; }
}


/* Scroll offset for every anchor target so the sticky header never
   overlaps the top of a section (measured against the uncompressed header). */
#services, #gallery, #why, #process, #reviews, #contacts, #booking,
/* Якоря услуг на services.html — те же семь id, что в ссылках плиток
   главной. Величина одна и та же для всех страниц: шапка sticky и на
   services.html, высота у неё та же. */
#ceramic, #film, #polish, #liquid-glass, #interior, #tint, #presale,
/* Якоря секций about.html — та же логика, шапка sticky и там. */
#intro, #approach, #space, #numbers, #team, #materials, #cta,
/* Секции contacts.html: #intro/#cta уже выше, добираем оставшиеся две. */
#place, #route,
/* Секции policy.html. #consent — цель ссылки «Согласие на обработку ПДн»
   из подвалов ВСЕХ страниц и подписи чекбокса формы записи на index.html:
   без отступа заголовок раздела уезжал под шапку, и было непонятно,
   куда попал. */
#doc, #consent,
/* Цель скип-ссылки «Перейти к содержимому» на всех страницах: у клавиатурного
   пользователя ровно та же поломка, что была у #consent, — первый экран
   содержимого прятался под шапкой. */
#main-content,
/* #top — сама шапка, стоит в начале документа: вычисленная позиция скролла
   уходит в минус и всё равно упирается в 0, так что правило здесь ничего
   не меняет. Стоит в списке только чтобы он покрывал все якорные цели
   без исключений и не приходилось выяснять это заново. */
#top {
  scroll-margin-top: calc(var(--header-h) + 24px);
}

/* =========================================================================
   HERO
   ========================================================================= */
.hero {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background-color: var(--glnz-bg);
  /* Высота — нативная высота канваса (860px) × var(--u), как и весь
     остальной hero. НАЙДЕННЫЙ БАГ (см. STOP): раньше здесь стоял
     clamp(560px,62vw,860px), который на 1536 (и выше ~1387px) клампился к
     максимуму 860 БЕЗ учёта var(--u) — hero рендерился в полную нативную
     высоту вместо 860×0.80=688px. min(...,100svh) остаётся только
     потолком-страховкой от переполнения на низких окнах.
     860 → 770.6: canvas укорочен ровно на срезанную пустую полосу низа
     bottombar (см. .hero__bottombar min-height ниже) — hero__body (0-615
     native) не трогается, меняется только высота нижней панели. */
  min-height: min(calc(770.6px * var(--u)), 100svh);
}

/* =========================================================================
   GLNZ finalized hero (Pencil export — 13detailing_reference5_6.html,
   вынесен из репозитория в ../_hub/reference/, в проекте его нет)
   ФАЗА 3A (финальная схема): канвас 1920×860 + --glnz-s-скейлер сняты,
   вёрстка на обычном flex/grid-flow. КАЖДЫЙ нативный размер эталона
   (типографика/паддинги/gap/высоты/гутеры) — calc(native × var(--u)),
   --u определён в :root (0.85 на 1280 → 1.0 на 1920, заморожен за
   границами). Ниже 1280 — только перекомпоновка (Фаза 3B), не ужимание.
   Верхний nav внутри канваса удалён — его роль у постоянной sticky-шапки.
   ========================================================================= */

/* 1. Background layers — full-bleed photo + dark gradient wash */
.hero__bg {
  position: absolute; inset: 0;
  /* Приём тот же, что у .reviews__bg: WebP вперёд, JPEG последним звеном,
     выбор размера — медиазапросом по ширине окна, а не дескрипторами
     плотности. Дескрипторы 1x/2x выбирают по DPR: на мониторе 1920 с DPR 1
     отдавался файл 1280 с растяжением. Кадр не перекадрирован, только
     даунскейл (tools/build-hero-images.py).
     hero-glnz.jpg НЕ удалять и НЕ пережимать: он одновременно фолбэк для
     браузеров без WebP и донор og:image — часть парсеров превью WebP
     не читает (см. «Отложено до появления домена» в CLAUDE.md). */
  background-image: image-set(
    url("../img/hero-glnz-1920.webp") type("image/webp"),
    url("../img/hero-glnz.jpg") type("image/jpeg")
  );
  background-position: center var(--glnz-hero-bg-pos-y);
  background-repeat: no-repeat;
  background-size: cover;
  z-index: 0;
}
/* Ниже 1024 кадр всё равно режется по ширине — 1920 там лишний вес */
@media (max-width: 1024px) {
  .hero__bg {
    background-image: image-set(
      url("../img/hero-glnz-1280.webp") type("image/webp"),
      url("../img/hero-glnz.jpg") type("image/jpeg")
    );
  }
}

/* 1а. Видео-фон hero — прогрессивное улучшение поверх .hero__bg (main.js,
   секция HERO VIDEO). Элемент создаётся и добавляется в DOM только когда
   JS решает, что видео уместно (не prefers-reduced-motion, не мобильный
   брейкпоинт) — в остальных случаях .hero__bg (фото) остаётся видимым
   как есть, дополнительной CSS-ветки для фолбэка не требуется.
   object-position задан через --glnz-hero-video-pos-y (рядом с
   --glnz-hero-bg-pos-y выше) — рассчитан так, чтобы колесо автомобиля
   встало на ту же высоту, что на фото-эталоне .hero__bg. Тот же тир
   z-index:0, что и .hero__bg — видео добавляется в DOM ПОСЛЕ него
   (main.js), поэтому перекрывает фото при своём наличии, ниже
   .hero__overlay (z:1). */
.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center var(--glnz-hero-video-pos-y);
  z-index: 0;
}

.hero__overlay {
  position: absolute; inset: 0;
  background-image: var(--glnz-overlay-hero);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  z-index: 1;
}

/* === SHEEN ВРЕМЕННО ОТКЛЮЧЁН — вернуться к настройке ===
1c. Sheen — надстройка поверх фото/градиента И поверх фона тёмной
   панели bottombar (см. .hero__bottombar::before ниже), но ниже текста/
   кнопок/статистики (те — z-index:4). НАЙДЕННЫЙ БАГ: раньше вспышка
   (z:1) обрезалась на правой части кадра фоном .hero__bottombar
   (z:2, background-image: var(--glnz-overlay-bottombar)) — панель и
   контент бара были одним элементом, вспышка не могла оказаться между
   ними. Фон панели вынесен в ::before-псевдоэлемент, у самого
   .hero__bottombar z-index снят, поэтому его дети (cta-col/book-wrap/
   stats-col) получили z-index явно. Тиры: bg=0, overlay=1, панель
   bottombar=2, sheen=3, body/контент bottombar=4.
   Выключатель: .hero--no-sheen на .hero скрывает слой целиком, вид
   идентичен исходному. Настройки — через переменные на .hero__sheen,
   крутить в DevTools без правки файлов. * /
.hero__sheen {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  pointer-events: none;
  --sheen-opacity: 0.30; /* ПИК прозрачности в центре прохода, не постоянный уровень — по пути к центру и от него ниже (см. keyframes) * /
  --sheen-duration: 14s; /* ПОЛНЫЙ цикл туда-обратно: проход 1.2s + пауза 5.8s + обратный проход 1.2s + пауза 5.8s = вспышка каждые 7s * /
  --sheen-angle: 105deg;
  --sheen-width: 18vw;
  --sheen-tint: 255, 238, 214;
}
.hero--no-sheen .hero__sheen { display: none; }

.hero__sheen-band {
  position: absolute;
  top: -50%;
  left: 0;
  width: var(--sheen-width);
  height: 200%;
  background: linear-gradient(
    to right,
    rgba(var(--sheen-tint), 0)    0%,
    rgba(var(--sheen-tint), 0.06) 38%,
    rgba(var(--sheen-tint), 0.55) 46%,
    rgba(var(--sheen-tint), 1)    50%,
    rgba(var(--sheen-tint), 0.55) 54%,
    rgba(var(--sheen-tint), 0.06) 62%,
    rgba(var(--sheen-tint), 0)    100%
  );
  opacity: 0;
  mix-blend-mode: screen;
  will-change: transform, opacity;
  animation: hero-sheen var(--sheen-duration) linear infinite;
}

/* Короткая вспышка каждые 7s (при 14s это полный цикл туда-обратно):
   0-8.57% проход слева направо (1.2s), 8.57-50% пауза за правым краем
   (5.8s), 50-58.57% проход справа налево (1.2s), 58.57-100% пауза за
   левым краем (5.8s). Пик прозрачности — в середине каждого прохода
   (4.29%/54.29%), т.е. на кузове в центре кадра.
   LEFT/RIGHT: ПЕРЕСЧИТАНЫ на -750%/1080% (было -340%/500% под ширину
   38vw) — translateX в % от ширины САМОЙ полосы, а --sheen-width в этой
   же правке сузили до 18vw, старые проценты перестали хватать. Проверено
   geometry-тестом (getBoundingClientRect в момент keyframe, с учётом
   поворота) на 1536 и 375, плюс запасом на 320×1000. MID=165% — среднее
   LEFT/RIGHT (по формуле задачи); центр полосы в этой точке не строго
   по центру вьюпорта (сдвиг ~12% из-за разной геометрии на 1536/375 —
   один и тот же процент не может идеально центрироваться на обеих
   ширинах), в проверке это не требовалось.
   Анимируются только transform/opacity — без left/top/background-position. * /
@keyframes hero-sheen {
  0%     { transform: rotate(calc(var(--sheen-angle) - 90deg)) translateX(-750%); opacity: 0; }
  1%     { opacity: 0.12; }
  4.29%  { transform: rotate(calc(var(--sheen-angle) - 90deg)) translateX(165%); opacity: var(--sheen-opacity); }
  7.5%   { opacity: 0.12; }
  8.57%  { transform: rotate(calc(var(--sheen-angle) - 90deg)) translateX(1080%); opacity: 0; }
  50%    { transform: rotate(calc(var(--sheen-angle) - 90deg)) translateX(1080%); opacity: 0; }
  51%    { opacity: 0.12; }
  54.29% { transform: rotate(calc(var(--sheen-angle) - 90deg)) translateX(165%); opacity: var(--sheen-opacity); }
  57.5%  { opacity: 0.12; }
  58.57% { transform: rotate(calc(var(--sheen-angle) - 90deg)) translateX(-750%); opacity: 0; }
  100%   { transform: rotate(calc(var(--sheen-angle) - 90deg)) translateX(-750%); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__sheen { display: none; }
}
=== /SHEEN === */

/* 1b. Ken Burns on the background — DISABLED by owner's decision.
   To bring back: uncomment the block below.
.hero__bg {
  will-change: transform;
  animation: glnz-kenburns 13s ease-in-out infinite alternate both;
}
@keyframes glnz-kenburns {
  from { transform: scale(1.05) translate3d( 2.6%,  1.6%, 0); }
  to   { transform: scale(1.22) translate3d(-2.6%, -2.0%, 0); }
}
*/

/* 2. Content column — eyebrow / title / subtitle, centered in the flexible
   zone between the (external, sticky) header and the bottom bar.
   padding-top clears the header, which visually overlaps the hero's top
   edge (see HEADER block, margin-bottom: calc(-1 * var(--header-h))). */
/* Вертикальный/горизонтальный ритм — из нативных координат канваса
   13detailing_reference5_6.html (вынесен из репозитория в
   ../_hub/reference/, в проекте его нет), каждое число × var(--u):
   Nav bottom(72) → Eyebrow top(118): gap 46 (оба конца — задекларированные
     значения, надёжно).
   Eyebrow top(118) → Title top(133): raw-дельта 15 — Pencil НЕ даёт Eyebrow
     явной height (line-height:normal, однострочный текст), так что точную
     "высоту" вычесть не из чего; margin-top Title оставлен 0 (Title идёт
     сразу за строкой Eyebrow во flow) — единственное место в этой раскладке,
     где вместо вычисленного числа стоит приближение, см. STOP.
   Title top(133)+height(181)=314 → Subtitle top(496): gap 182 (оба конца
     задекларированы — надёжно).
   Subtitle top(496)+height(107)=603 → Bottom Bar top(615): gap 12 (надёжно).
   Bottom Bar bottom(615+245=860) = высота канваса — вплотную, без зазора.
   Left: Eyebrow/Subtitle = 48, Title = 36 (на 12 левее) — раскладка ниже
   берёт 36 как базовый padding-left, Eyebrow/Subtitle получают +12
   margin-left. */
.hero__body {
  position: relative;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding-top: calc(118px * var(--u));   /* Eyebrow top, канвас = 0 у верхнего края hero */
  padding-left: calc(36px * var(--u));   /* Title left (самый левый элемент блока) */
  padding-right: calc(110px * var(--u)); /* общий гутер — контент сюда не доходит, для симметрии с bottom-bar */
  padding-bottom: calc(12px * var(--u)); /* Subtitle bottom → Bottom Bar top */
}
.hero__eyebrow {
  margin: 0 0 0 calc(12px * var(--u)); /* +12 к padding-left блока = нативные 48 */
  color: var(--glnz-eyebrow);
  font-family: var(--glnz-font-display);
  font-size: var(--glnz-fs-eyebrow);
  font-weight: 500;
  letter-spacing: calc(3px * var(--u));
  line-height: normal;
  white-space: nowrap;
}
.hero__title {
  /* было margin:0 (приближение — Eyebrow без явной height). Реальным
     замером (getBoundingClientRect на 1536) нашли: Eyebrow фактически
     рендерится в 30px (native) высотой, а не 15px, — значит Title должен
     подняться на (133 - 118 - 30) = -15px (native), чтобы точно попасть в
     top:133 эталона. Проверено скриншотом — Eyebrow/Title не перекрываются. */
  margin: calc(-15px * var(--u)) 0 0 0;
  /* эталон резервирует ФИКСИРОВАННУЮ высоту-бокс (height:181px), а не
     высоту от line-height — реальный рендер текста короче зоны, которую
     Pencil-дизайн резервирует под неё (это и было причиной "полосы" под
     bottom-bar, см. STOP). height + line-height:normal — как в эталоне. */
  height: calc(181px * var(--u));
  font-family: var(--glnz-font-display);
  font-size: var(--glnz-fs-h1);
  font-weight: 700;
  line-height: normal;
}
.hero__subtitle {
  margin: calc(182px * var(--u)) 0 0 calc(12px * var(--u)); /* top: Title-bottom→Subtitle-top; left: +12 = нативные 48 */
  /* та же логика, что у Title — эталон резервирует height:107px фиксированно */
  height: calc(107px * var(--u));
  max-width: calc(786px * var(--u));
  color: var(--glnz-subtitle);
  font-family: var(--glnz-font-display);
  font-size: var(--glnz-fs-subtitle);
  font-weight: 400;
  line-height: normal;
}

/* 3. Bottom bar — 3-column grid: CTA buttons (left) / book button (true
   center, regardless of side content width) / stats (right). Всё × var(--u).
   На ≤1439px (см. брейкпоинт ниже) НЕ помещается в одну строку без
   перекомпоновки — статистика уходит на отдельную строку (Вариант 1). */
.hero__bottombar {
  /* z-index на самом баре НЕ ставим — иначе он создаёт свой стэкинг-
     контекст и панель (::before) с контентом (cta-col/book-wrap/
     stats-col) всегда красятся одним куском, вспышку между ними не
     просунуть. Фон панели — ::before ниже, z:2; контент — z:4
     явно на каждой колонке. */
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: calc(24px * var(--u));
  /* 245 → 155.6: под самой нижней строкой контента (hero__stats-col с
     hero__highlight) оставалась пустая полоса ниже панели ~51px (замер
     getBoundingClientRect на 1536), вдвое больше зазора шапки над её
     контентом (~15px, тот же замер) — hero не был симметричен сверху и
     снизу. align-items:center не трогаем (кнопки/статистика/книга
     остаются центрированы друг относительно друга тем же способом), меняем
     только саму высоту рамки — центрирование внутри неё сдвигает все три
     колонки СИНХРОННО (на одну и ту же дельту), их взаимное расположение и
     внутренние отступы между ними не меняются. 155.6 = высота контента
     (117.7 native) + 2× зазор шапки (18.9 native каждый), т.е. нижний
     зазор становится равным замеренному верхнему зазору шапки. */
  min-height: calc(155.6px * var(--u));
  padding-inline: calc(110px * var(--u));
}
.hero__bottombar::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-color: var(--glnz-overlay-bottombar); /* плоская полупрозрачная заливка, без градиента — см. токен в :root */
}
/* Разделитель по верхнему краю панели — тот же токен/градиент, что под
   секцией «Услуги» (.services::after) и под шапкой выше. ::before уже
   занят заливкой панели, поэтому линия — на ::after. */
.hero__bottombar::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 3;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(
    to right,
    transparent 0%,
    var(--glnz-section-divider) 14%,
    var(--glnz-section-divider) 86%,
    transparent 100%
  );
}
.hero__cta-col { position: relative; z-index: 4; justify-self: start; min-width: 0; }
.hero__cta-row {
  display: flex;
  align-items: center;
  gap: calc(16px * var(--u));
}
/* .svc-btn-* добавлены в группы, а не скопированы отдельным блоком —
   тем же приёмом, что .works__book-btn выше. Эталон страницы услуг
   (services_hero5_3.html) рисует ровно эти три кнопки один в один
   с hero главной: заливка #63400F и паддинг 20/34 у главной,
   рамка #232a32 + радиус 8 у второй, 260×95 с медной рамкой у
   «ЗАПИСАТЬСЯ». Поэтому не копируем значения, а расширяем селекторы. */
.hero__btn-primary,
.svc-btn--primary {
  align-items: center;
  background-color: var(--glnz-accent);
  box-shadow: 0 4px 4px 0 var(--glnz-shadow-color), 0 4px 4px 0 var(--glnz-shadow-color);
  display: flex;
  flex-shrink: 0;
  gap: calc(12px * var(--u));
  justify-content: center;
  padding: calc(20px * var(--u)) calc(34px * var(--u));
  text-decoration: none;
  white-space: nowrap;
}
.hero__btn-primary-label,
.svc-btn--primary .svc-btn__label {
  color: var(--glnz-text-onbtn);
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-cta);
  font-weight: 600;
  letter-spacing: calc(.3px * var(--u));
  line-height: normal;
  white-space: nowrap;
}
/* Иконки кнопок hero — набор lucide (arrow-right здесь, play в
   .hero__btn-secondary-icon, chevron-down в .hero__book-btn-icon ниже).
   SVG инлайнятся в разметке (data-icon-set="lucide"), тут только размер. */
.hero__btn-primary-icon { flex-shrink: 0; height: calc(18px * var(--u)); width: calc(18px * var(--u)); }
/* .svc-btn--ghost — «Смотреть работы» в hero услуг и рамка блока цены
   в секциях. В эталоне это тот же бокс: outline 1px #232a32 + радиус 8. */
.hero__btn-secondary,
.svc-btn--ghost,
.svc__price {
  align-items: center;
  background-color: transparent;
  border: 1px solid var(--glnz-border-secondary);
  border-radius: var(--radius-md);
  display: flex;
  flex-shrink: 0;
  gap: calc(10px * var(--u));
  justify-content: center;
  padding: calc(20px * var(--u)) calc(30px * var(--u));
  text-decoration: none;
  white-space: nowrap;
}
.hero__btn-secondary-icon { flex-shrink: 0; height: calc(16px * var(--u)); width: calc(16px * var(--u)); }
.hero__btn-secondary-label,
.svc-btn--ghost .svc-btn__label {
  color: var(--glnz-text-onbtn);
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-cta);
  font-weight: 500;
  letter-spacing: calc(.3px * var(--u));
  line-height: normal;
  white-space: nowrap;
}

.hero__book-wrap { position: relative; z-index: 4; justify-self: center; }
/* .works__book-* добавлены в группы ниже, а не скопированы отдельным блоком:
   кнопка «Хочу так же» в «Наших работах» должна остаться один в один с
   hero-кнопкой «ЗАПИСАТЬСЯ» при любой будущей правке. Разметка hero при
   этом не тронута (она утверждена, см. CLAUDE.md). */
.hero__book-btn,
.works__book-btn,
.svc-hero__book-btn {
  align-items: center;
  background-color: transparent;
  border: 1px solid var(--glnz-accent-border);
  display: flex;
  flex-shrink: 0;
  gap: calc(12px * var(--u));
  height: calc(95px * var(--u));
  justify-content: center;
  text-decoration: none;
  width: calc(260px * var(--u));
}
.hero__book-btn-text,
.works__book-btn-text,
.svc-hero__book-btn-text {
  color: var(--glnz-text-white);
  font-family: var(--glnz-font-display);
  font-size: var(--glnz-fs-btn-center);
  font-weight: 700;
  letter-spacing: calc(2px * var(--u));
  line-height: normal;
  white-space: nowrap;
}
.hero__book-btn-icon,
.works__book-btn-icon,
.svc-hero__book-btn-icon { flex-shrink: 0; height: calc(18px * var(--u)); width: calc(18px * var(--u)); }

.hero__stats-col {
  position: relative;
  z-index: 4;
  justify-self: end;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* эталон, ЗАМЕРЕНО живым рендером reference-файла (не по declared-боксам —
     это и есть та же ловушка, что раньше на Title/Subtitle): реальный
     center-x строки статистики (по крайним текстовым узлам, не контейнеру)
     = (1311.97+1827.03)/2 = 1569.5; center-x highlight-строки =
     (1391.28+1747.70)/2 = 1569.49 — совпадает. align-items:center верен. */
  align-items: center;
  /* ЗАМЕРЕНО: нижняя граница подписей статистики (label.bottom, одинаково
     у всех трёх) = 742px; верхняя граница highlight-строки (по "+", он
     выше по тексту из-за font-size 38 и line-height:38) = 768px.
     Реальный визуальный разрыв = 768 − 742 = 26px — НЕ 0 (то было
     расстояние между declared-боксами контейнеров, слишком оптимистично) и
     НЕ мои прежние произвольные 8px. */
  gap: calc(26px * var(--u));
}
.hero__stats {
  display: flex;
  justify-content: center; /* эталон: justify-content:center у обеих Stats Column */
  gap: calc(21px * var(--u)); /* эталон, не менялось */
}
.hero__stat { display: flex; flex-direction: column; gap: calc(4px * var(--u)); }
.hero__stat-value {
  color: var(--glnz-stat-value);
  font-family: var(--glnz-font-display);
  font-size: var(--glnz-fs-stat-value);
  font-weight: 700;
  /* 31/31.2 из эталона, записано отношением, а не длиной: кегль на узких
     ширинах переопределяется токеном, и интерлиньяж-длина осталась бы от
     десктопа — строка висела бы в завышенном боксе. Отношение едет за
     кеглем само, отдельного токена на каждый брейкпоинт не нужно. */
  line-height: 0.994;
  white-space: nowrap;
}
.hero__stat-label {
  color: var(--glnz-stat-label);
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-stat-label);
  font-weight: 400;
  line-height: normal;
}
.hero__stat-label--wrap { max-width: calc(163px * var(--u)); }

.hero__highlight { display: flex; align-items: center; gap: 0; } /* ЗАМЕРЕНО: "+".right(1413.34)==текст.left(1413.34) вплотную, было произвольных 8px */
.hero__highlight-plus {
  color: var(--glnz-stat-value);
  font-family: var(--glnz-font-display);
  font-size: var(--glnz-fs-stat-accent);
  font-weight: 700;
  letter-spacing: calc(5px * var(--u));
  line-height: 1; /* 38/38 из эталона — отношением, по той же причине, что у .hero__stat-value */
}
.hero__highlight-text {
  color: var(--glnz-stat-value);
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-nav-logo);
  font-weight: 700;
  letter-spacing: calc(-1px * var(--u));
  line-height: normal;
  white-space: nowrap;
}

/* 4. "ЗАПИСАТЬСЯ" button — fill sweeps in from center to edges on hover */
.hero__book-btn,
.works__book-btn,
.svc-hero__book-btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  cursor: pointer;
  transition: border-color .45s ease;
}
.hero__book-btn::before,
.works__book-btn::before,
.svc-hero__book-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--glnz-accent);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform .45s cubic-bezier(.4, 0, .2, 1);
}
.hero__book-btn:hover::before,
.works__book-btn:hover::before,
.svc-hero__book-btn:hover::before { transform: scaleX(1); }
.hero__book-btn:hover,
.works__book-btn:hover,
.svc-hero__book-btn:hover { border-color: var(--glnz-accent); }

/* 5. Bottom-panel entrance: left / bottom / right, staggered */
.hero__cta-col { animation: glnz-in-left  .9s cubic-bezier(.22, 1, .36, 1) 1.20s both; }
.hero__book-wrap { animation: glnz-in-up    .9s cubic-bezier(.22, 1, .36, 1) 1.35s both; }
.hero__stats-col { animation: glnz-in-right .9s cubic-bezier(.22, 1, .36, 1) 1.50s both; }

@keyframes glnz-in-left  { from { opacity: 0; transform: translateX(-70px); } to { opacity: 1; transform: none; } }
@keyframes glnz-in-right { from { opacity: 0; transform: translateX( 70px); } to { opacity: 1; transform: none; } }
@keyframes glnz-in-up    { from { opacity: 0; transform: translateY( 60px); } to { opacity: 1; transform: none; } }

/* Accessibility: kill motion per system setting (also covers the nav-link
   underline transition via the global *, *::before, *::after rule above) */
@media (prefers-reduced-motion: reduce) {
  .hero__cta-col,
  .hero__book-wrap,
  .hero__stats-col,
  .about-intro__head .svc__eyebrow,
  .about-intro__title,
  .about-intro__lead,
  .about-intro__note,
  .about-intro__media { animation: none !important; }
  .hero__book-btn::before,
  .works__book-btn::before,
  .svc-hero__book-btn::before { transition-duration: .01ms !important; }
}

/* 6. Bottom-bar restructure (ФАЗА 3A, Вариант 1 — статистика уходит под
   кнопки). Расчёт по метрикам шрифта (без живого рендера — см. STOP), базис
   --u=0.80 заморожен с 1536 (не с 1280 — эталон одобрялся на 1536/125%
   масштабе Windows): однострочному бару нужно ~1259px контента при
   --u=0.80 (константа на всём диапазоне ≤1536). На 1440 запас ~181px, на
   1536 (основная проверочная ширина) — ~277px. 1440 оставлен как граница
   (раньше запас был лишь ~44px при старом полу 0.85 — теперь коэффициент
   ниже, значит контент меньше и запас больше; понижать порог дальше не
   стал — метрика уже один раз занизила реальную тесноту на ~150-200px в
   шапке, см. историю STOP). */
@media (max-width: 1439px) {
  .hero__bottombar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    row-gap: calc(16px * var(--u));
  }
  .hero__cta-col { order: 1; }
  .hero__book-wrap { order: 2; }
  .hero__stats-col {
    order: 3;
    flex-basis: 100%;
    align-items: center;
  }
  .hero__stats { justify-content: center; }
}

/* =========================================================================
   MOBILE / ПЛАНШЕТ (ФАЗА 3B) — ниже 1024px. --u заморожен на 0.80 (см.
   :root) — здесь НЕ масштабируем дальше, адаптив только перекомпоновкой:
   перенос строк, столбик вместо ряда, явные размеры в самом медиа-запросе.
   Референса для мобильного макета не существует (эталон — Pencil-канвас,
   который просто ужимается) — критерий: читаемость, без горизонтального
   скролла, ничего не наезжает, все CTA доступны.
   ========================================================================= */
@media (max-width: 1024px) {
  /* Hero растёт по содержимому — БЕЗ calc(860px*var(--u)) потолка (тот был
     нужен только чтобы совпасть с эталоном на десктопе). 100svh — теперь
     только МИНИМУМ (короткий контент не даст hero схлопнуться), никогда не
     обрезает: min-height не может обрезать контент по определению, но
     раньше здесь стоял calc(860px*var(--u)), который на некоторых
     сочетаниях высоты экрана визуально "тянул" макет к устаревшей цифре —
     убираем совсем, оставляем только защитный минимум. */
  .hero { min-height: 100svh; }

  /* === КЕГЛИ HERO НА УЗКИХ ШИРИНАХ ======================================
     Почему вообще нужны ступени: --u = clamp(0.80, 100vw/1920, 1) заморожен
     на 0.80 ниже 1536px, то есть от 1536 и до 360 кегли одинаковые. На 1024
     и уже тексты hero съедали первый экран.

     Переопределения объявлены НА .hero, а не в :root: часть токенов общая —
     --glnz-fs-nav-logo несёт ещё и лого в шапке (styles.css:566), а
     --glnz-fs-btn-center — кнопку «ОТПРАВИТЬ ЗАЯВКУ» и «Хочу так же»
     в «Наших работах». Наследование переменных отдаёт им корневое значение,
     hero живёт своим.

     Значения записаны итоговыми px, без calc(N * var(--u)): --u здесь
     константа 0.80, и в такой записи число в токене = число на экране —
     иначе, чтобы получить 15px, владельцу пришлось бы вписывать 18.75.

     Коэффициент ступени — 0.72 от десктопного кегля. Раскладка тут уже
     перестроена в одну колонку (кнопки во всю ширину), поэтому шаг
     умеренный: главная задача — снять доминирование лого GLNZ.

     ПОРОГИ ЧИТАЕМОСТИ (основной текст 15px, вспомогательный 12px) бьют
     раньше пропорции — где они сработали, помечено «порог».
     ====================================================================== */
  .hero {
    --glnz-fs-h1: 86px;             /* 120 × 0.72 */
    --glnz-fs-eyebrow: 12px;        /* порог: 16 × 0.72 = 11.5 */
    --glnz-fs-subtitle: 17px;       /* 24 × 0.72 */
    --glnz-fs-stat-value: 18px;     /* 24.96 × 0.72 */
    --glnz-fs-stat-label: 12px;     /* порог: 12.8 × 0.72 = 9.2 */
    --glnz-fs-stat-accent: 22px;    /* 30.4 × 0.72 — «+» перед highlight */
    --glnz-fs-nav-logo: 13px;       /* 17.6 × 0.72 — строка «самые чистые машины» */
    /* --glnz-fs-btn-center (14.4) и --glnz-fs-cta (12.8) НЕ трогаем: они уже
       ниже порога 15px до всякой правки, уменьшать их нельзя (см. отчёт). */
  }
  /* === /КЕГЛИ HERO НА УЗКИХ ШИРИНАХ === */

  /* Текстовый блок: правое поле (110px×u = 88px на морозе) убираем — оно
     не несёт контента (выравнивание по левому краю) и просто съедало
     ширину под перенос eyebrow/subtitle. Левое поле — чуть уже.
     ВЕРТИКАЛЬНЫЙ РИТМ (найдено живой проверкой): отступ до Eyebrow
     (calc(118px*var(--u))≈94px) и разрыв Title→Subtitle
     (calc(182px*var(--u))≈146px, ниже) — оба взяты из десктопного
     эталона, где считались от нативных координат канваса 1920×860.
     На мобильном такого эталона нет, а место в вертикали — самый дефицит
     первого экрана (360×640/414×736). Заменяем на типографские отступы. */
  .hero__body {
    padding-top: 2.25rem;
    padding-left: calc(20px * var(--u));
    padding-right: calc(20px * var(--u));
    padding-bottom: 1rem;
  }
  .hero__eyebrow { margin-left: 0; }
  .hero__title { margin-top: .35rem; }
  .hero__subtitle {
    margin-left: 0;
    margin-top: 1.1rem; /* было calc(182px*var(--u))≈146px */
    /* НАШЁЛ СКРИНШОТОМ (не отловилось замером rect — там проверялся БОКС,
       не реальный текст): height:107px×u — фиксированная, нужна для
       точного совпадения с эталоном на десктопе. На мобильном при более
       узких полях текст переносится на большее число строк, чем эта
       высота вмещает, — переполнение визуально уходит ПОД bottom-bar
       (следующий элемент в потоке рисуется поверх). Авто-высота решает. */
    height: auto;
  }

  /* Bottom-bar — полностью в столбик, в нормальном потоке, порядок как в
     согласованной композиции: CTA-кнопки → книга-кнопка → статистика.
     order уже расставлен в блоке ≤1439 выше, здесь просто меняем row→column
     и растягиваем каждый блок на всю ширину. НАШЁЛ ЗАМЕРОМ: padding-inline
     тут был всё ещё десктопный calc(110px*var(--u))=88px — кнопки реально
     вылезали за экран на 360/414 и обрезались overflow:hidden у .hero
     (не скроллбар — контент молча пропадал). Приводим к тем же полям, что
     у .hero__body. */
  .hero__bottombar {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    row-gap: calc(24px * var(--u));
    padding-top: calc(28px * var(--u));
    /* + --stickybar-h: резерв под ПОСТОЯННУЮ .mobile-cta-bar (fixed,
       перекрывает низ вьюпорта) — иначе последний элемент (highlight)
       долистывается ровно ПОД неё, без запаса. Cookie-баннер — временный,
       под него отдельно не резервируем (once accepted — держать вечный
       зазор под исчезнувшую панель не имеет смысла). */
    padding-bottom: calc(28px * var(--u) + var(--stickybar-h));
    padding-inline: calc(20px * var(--u));
  }
  /* Правило-близнец для нижней полосы hero страницы услуг — в блоке
     SERVICES PAGE ниже: там .mobile-cta-bar в разметке нет и резерв
     под неё не нужен. */
  .hero__cta-col,
  .hero__book-wrap,
  .hero__stats-col { flex-basis: auto; }

  /* Две CTA-кнопки — в столбик, на всю ширину (было: в ряд, nowrap). */
  .hero__cta-row {
    flex-direction: column;
    align-items: stretch;
  }
  .hero__btn-primary,
  .hero__btn-secondary { justify-content: center; width: 100%; }

  /* Книга-кнопка — тоже на всю ширину (была фиксированных 260px×u). */
  .hero__book-wrap { display: flex; justify-content: center; }
  .hero__book-btn { width: 100%; }

  .hero__stats-col { align-items: center; }
}

/* Статистика: 3 в ряд держим до 768px (тот же ряд, что на десктопе —
   отдельных правил не нужно). Ниже 768 — в столбик (выбрал столбик, а не
   2+1: при самом длинном значении «Ceramic Pro» + подписи 2-в-ряд уже
   тесно на 360-414, столбик гарантированно не наедет ни при какой ширине
   текста). Если визуально покажется, что до 560 ещё можно было держать
   ряд — могу вернуть 2+1 отдельным подтиром, не пересобирая остальное. */
@media (max-width: 767px) {
  .hero__stats {
    flex-direction: column;
    align-items: center;
    gap: calc(10px * var(--u));
  }
  .hero__stat { align-items: center; }

  /* === КЕГЛИ HERO НА УЗКИХ ШИРИНАХ (768) ===============================
     Коэффициент 0.60 — шаг глубже, чем на 1024: статистика тут разворачивается
     в столбик и добавляет три строки высоты, вертикали становится меньше при
     той же ширине. Порядок величин и причина записи в px — см. блок на 1024.
     ====================================================================== */
  .hero {
    --glnz-fs-h1: 72px;             /* 120 × 0.60 */
    --glnz-fs-eyebrow: 12px;        /* порог: 16 × 0.60 = 9.6 */
    --glnz-fs-subtitle: 15px;       /* порог: 24 × 0.60 = 14.4 */
    --glnz-fs-stat-value: 15px;     /* порог: 24.96 × 0.60 = 15.0 — ровно на грани */
    --glnz-fs-stat-label: 12px;     /* порог: 12.8 × 0.60 = 7.7 */
    --glnz-fs-stat-accent: 18px;    /* 30.4 × 0.60 */
    --glnz-fs-nav-logo: 12px;       /* порог: 17.6 × 0.60 = 10.6 */
  }
  /* === /КЕГЛИ HERO НА УЗКИХ ШИРИНАХ (768) === */
}

/* Самые узкие телефоны: H1 «GLNZ» пропорционально меньше — 150px×var(--u)
   (120px на заморозке 0.80) визуально доминирует над 360-414px экраном.
   Слово одно, без пробелов — технически не перенеслось бы в любом случае,
   но так пропорциональнее. Eyebrow/subtitle не трогаю — не жаловались.
   height:auto — иначе жёсткая height:181px×u (нужна для точного совпадения
   с эталоном на десктопе) оставляет пустой зазор под уменьшенным текстом. */
@media (max-width: 419px) {
  /* === КЕГЛИ HERO НА УЗКИХ ШИРИНАХ (420) ===============================
     Коэффициент 0.52. Здесь почти всё, кроме лого и «+», уже стоит на
     порогах читаемости с предыдущей ступени — реально уменьшается только
     графика. Пороговые токены повторены явно, а не унаследованы: иначе
     непонятно, почему на самой узкой ступени часть величин «не изменилась».
     Кегль лого раньше стоял литералом прямо в правиле (calc(90px*var(--u))
     = 72px) — переехал в токен, height:auto остался на месте: без него
     жёсткая height:181px×u оставляет пустой зазор под уменьшенным словом.
     ====================================================================== */
  .hero {
    --glnz-fs-h1: 62px;             /* 120 × 0.52, было 72 */
    --glnz-fs-eyebrow: 12px;        /* порог */
    --glnz-fs-subtitle: 15px;       /* порог */
    --glnz-fs-stat-value: 15px;     /* порог: 24.96 × 0.52 = 13.0 */
    --glnz-fs-stat-label: 12px;     /* порог */
    --glnz-fs-stat-accent: 16px;    /* 30.4 × 0.52 */
    --glnz-fs-nav-logo: 12px;       /* порог */
  }
  .hero__title { height: auto; }
  /* === /КЕГЛИ HERO НА УЗКИХ ШИРИНАХ (420) === */
}

/* =========================================================================
   SERVICES (rebuilt, Pencil: uslgi(main-page)3_2.pen — "Услуги / покой" и
   "Услуги / ховер"). Боковой гутер секции = боковой гутер шапки
   (.header-inner, min-width:1025px ниже), это же выравнивает лого/заголовок/
   первую плитку по вертикали. Лестница колонок — отдельные пороги
   1440/1024/768/420 (см. .services__grid ниже), это разные вещи: гутер
   и число колонок переключаются не в одной точке, и это ок (см. STOP
   про 1023/1024 в задаче — на этом пороге не сверяем).
   ========================================================================= */
.services {
  position: relative;
  background: var(--glnz-services-bg);
  padding-top: calc(60px * var(--u));
  padding-bottom: calc(120px * var(--u));
  padding-inline: var(--container-pad);
}
/* Разделитель — градиент, не border (border гradientом не заливается):
   гаснет к обоим краям окна, тоньше и глуше меди тайлов. */
.services::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent 0%,
    var(--glnz-section-divider) 14%,
    var(--glnz-section-divider) 86%,
    transparent 100%
  );
}
@media (min-width: 1025px) {
  .services { padding-inline: calc(110px * var(--u)); }
}

.services__title {
  margin: 0 0 calc(24px * var(--u)) 0;
  color: var(--glnz-services-heading);
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-services-h2);
  line-height: normal;
}
.services__lead {
  margin: 0 0 calc(80px * var(--u)) 0;
  color: var(--glnz-stat-label);
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-services-lead);
  line-height: normal;
}

/* Лестница перестройки — меняется только N колонок (см. задачу, п.4) */
.services__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  column-gap: calc(10px * var(--u));
  row-gap: calc(80px * var(--u));
}
@media (min-width: 420px)  { .services__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 768px)  { .services__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .services__grid { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1440px) { .services__grid { grid-template-columns: repeat(5, 1fr); } }

/* min-width:0 — без этого длинный текст внутри aspect-ratio-плитки
   (напр. "Предпродажная подготовка" + длинное описание) через
   auto-минимум грид-айтема раздувает именно ЭТУ колонку сильнее других,
   1fr перестаёт быть равным и секция вылезает за вьюпорт (поймано на
   границе 420px). */
.services__item { list-style: none; min-width: 0; }

/* Плитка: фото (слой) + градиент (слой) + текст (слой), пропорция 332:466.
   Ширина не задаётся числом — следует из грида. */
.services__link {
  position: relative;
  display: block;
  aspect-ratio: 332 / 466;
  overflow: hidden;
  text-decoration: none;
}
.services__photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  line-height: 0;
}
.services__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: filter 420ms cubic-bezier(.2, .7, .2, 1), transform 420ms cubic-bezier(.2, .7, .2, 1);
}
.services__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: var(--glnz-services-scrim);
}
.services__scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--glnz-services-scrim-hover);
  opacity: 0;
  transition: opacity 420ms cubic-bezier(.2, .7, .2, 1);
}
.services__content {
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: calc(28px * var(--u));
}
.services__name {
  margin: 0;
  font-family: var(--glnz-font-display);
  font-weight: 500;
  font-size: var(--glnz-fs-services-name);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--glnz-services-name-color);
}
.services__details {
  display: flex;
  flex-direction: column;
  gap: calc(10px * var(--u));
  opacity: 1;
  transform: none;
  pointer-events: auto;
  transition: opacity .3s ease-out, transform .3s ease-out;
}
.services__price {
  margin: 0;
  font-family: var(--glnz-font-display);
  font-weight: 500;
  font-size: var(--glnz-fs-services-price);
  color: var(--glnz-services-heading);
}
.services__desc {
  margin: 0;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-services-desc);
  line-height: 1.45;
  color: var(--glnz-services-desc);
}
.services__more {
  font-family: var(--glnz-font-body);
  font-weight: 500;
  font-size: var(--glnz-fs-services-more);
  color: var(--glnz-services-accent);
}
.services__line {
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--glnz-accent-border);
  opacity: 1;
}

/* Промо-текст в пустоте второго ряда — только при N=5 (лестница п.4 в
   предыдущей задаче даёт ровно 3 пустые ячейки в этой раскладке).
   Ниже 1440 — display:none, в поток не переносится (решение владельца). */
.services__promo {
  display: none;
  grid-column: span 3;
  min-width: 0;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}
.services__promo-title {
  margin: 0 0 calc(16px * var(--u)) 0;
  font-family: var(--glnz-font-display);
  font-weight: 600;
  font-size: var(--glnz-fs-services-promo-title);
  color: var(--glnz-stat-value);
}
.services__promo-text {
  margin: 0;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-services-promo-text);
  line-height: 1.5;
  color: var(--glnz-stat-label);
}
@media (min-width: 1440px) {
  .services__promo { display: flex; }
}

/* ≥1024: "покой" — фото затемнено фильтром, детали скрыты; ховер/фокус
   оживляет. Ниже 1024 (тач) — вышестоящие базовые правила уже дают
   всегда-видимое состояние, ховера физически нет. */
@media (min-width: 1024px) {
  .services__photo img { filter: brightness(.45) saturate(.75); }
  .services__details {
    opacity: 0;
    transform: translateY(calc(16px * var(--u)));
    pointer-events: none;
  }
  .services__line { opacity: 0; }

  .services__link:hover .services__photo img,
  .services__link:focus-within .services__photo img {
    filter: none;
    transform: scale(1.06);
  }
  .services__link:hover .services__scrim::after,
  .services__link:focus-within .services__scrim::after { opacity: 1; }
  .services__link:hover .services__details,
  .services__link:focus-within .services__details {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    transition-delay: 80ms;
  }
  .services__link:hover .services__line,
  .services__link:focus-within .services__line { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .services__photo img,
  .services__details,
  .services__scrim::after,
  .services__line {
    transition-duration: 0s !important;
    transition-delay: 0s !important;
  }
  .services__details { transform: none; }
  .services__link:hover .services__photo img,
  .services__link:focus-within .services__photo img { transform: none; }
}

/* =========================================================================
   WORKS — «Наши работы», три плитки до/после со шторкой
   (Pencil: works2.pen; пересчёт базиса и происхождение величин — в блоке
   токенов --glnz-works-* выше). Гутер и заголовочная пара повторяют
   SERVICES: секция выравнивается по гутеру шапки.

   Устройство плитки. Кадр «после» лежит в потоке и задаёт высоту бокса,
   кадр «до» — в .works__clip, растянутом на весь бокс (inset:0) и
   обрезанном clip-path. Обрезка нужна именно clip-path'ом, а не шириной:
   ширина обёртки должна оставаться равной ширине плитки, иначе картинка
   «до» сжималась бы вместе со срезом и объекты в кадре разъезжались бы.
   Линия среза и ручка сидят на одной переменной --pos — разойтись не могут.
   ========================================================================= */
.works {
  position: relative;
  background: var(--glnz-works-bg);
  padding-top: calc(60px * var(--u));
  padding-bottom: calc(120px * var(--u));
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  .works { padding-inline: calc(110px * var(--u)); }
}

.works__title {
  margin: 0 0 calc(24px * var(--u)) 0;
  color: var(--glnz-services-heading);
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-services-h2);
  line-height: normal;
}
.works__lead {
  margin: 0 0 calc(80px * var(--u)) 0;
  color: var(--glnz-stat-label);
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-services-lead);
  line-height: normal;
}

/* Лестница 3 / 2 / 1 на общих порогах проекта (1024 / 768) */
.works__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: var(--glnz-works-gap);
}
@media (min-width: 768px)  { .works__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .works__grid { grid-template-columns: repeat(3, 1fr); } }

/* min-width:0 — тот же приём, что в .services__item: не давать содержимому
   плитки раздувать колонку и выносить сетку за вьюпорт. */
.works__item { list-style: none; min-width: 0; }

.works__ba {
  --pos: 50%;
  position: relative;
  aspect-ratio: var(--glnz-works-ratio);
  overflow: hidden;
  /* pan-y, а не none: горизонтальный жест забираем себе под шторку,
     вертикальный оставляем странице. С touch-action:none плитка в
     одноколоночном режиме занимала бы почти весь экран и палец не смог бы
     проскроллить страницу, начав движение с неё. */
  touch-action: pan-y;
  cursor: ew-resize;
  /* stroke:outer из макета — box-shadow рисует рамку снаружи и не влияет
     на геометрию бокса (border съел бы 2px внутренней ширины). */
  box-shadow: 0 0 0 1px var(--glnz-works-frame);
}

.works__photo,
.works__photo img {
  display: block;
  width: 100%;
  height: 100%;
}
.works__photo img { object-fit: cover; }

.works__clip {
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--pos)) 0 0);
}

.works__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--pos);
  width: var(--glnz-works-handle-w);
  margin-left: calc(var(--glnz-works-handle-w) / -2);
  background: var(--glnz-services-accent);
  pointer-events: none;
}
/* Круглый захват по центру линии: медный контур, стрелки — CSS-шевроны */
.works__handle::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--glnz-works-grip);
  height: var(--glnz-works-grip);
  margin: calc(var(--glnz-works-grip) / -2) 0 0 calc(var(--glnz-works-grip) / -2);
  border: 1px solid var(--glnz-services-accent);
  border-radius: 50%;
  background: var(--glnz-works-grip-bg);
  backdrop-filter: blur(2px);
}
/* Две вертикальные риски внутри захвата — привычный знак «тяни вбок» */
.works__handle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(var(--glnz-works-grip) * 0.26);
  height: calc(var(--glnz-works-grip) * 0.34);
  margin: calc(var(--glnz-works-grip) * -0.17) 0 0 calc(var(--glnz-works-grip) * -0.13);
  border-left: 2px solid var(--glnz-services-accent);
  border-right: 2px solid var(--glnz-services-accent);
}

/* Клавиатурный дублёр: физически лежит на плитке (иначе фокус уезжает
   в невидимую точку страницы), но не виден и не перехватывает указатель —
   мышью шторку двигает сам бокс. */
.works__range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  pointer-events: none;
}
/* Сам input прозрачен, поэтому кольцо фокуса рисуем на плитке */
.works__ba:has(.works__range:focus-visible) {
  outline: 2px solid var(--glnz-services-accent);
  outline-offset: 2px;
}

/* Обёртка задаёт только положение — сама кнопка целиком на правилах
   hero-кнопки (см. .hero__book-btn, туда добавлен .works__book-btn).
   Мобильное правило hero «width:100%» сюда НЕ подключено: оно относится
   к раскладке нижней панели hero, а не к виду кнопки. */
.works__cta {
  margin-top: calc(80px * var(--u));
  display: flex;
  justify-content: center;
}

@media (prefers-reduced-motion: reduce) {
  .works__handle { transition: none; }
}

/* =========================================================================
   PROCESS — «Как проходит запись», 4 шага (Pencil, montazh.md Секция 6).
   Гутер и точка перестройки колонок повторяют SERVICES выше (общий гутер
   шапки, 110 нативных px от 1025px). Декор (линии/ромбы) держится на
   рассчитанной высоте цифры (130px×u) — см. .process-step__num ниже —
   и полностью выключен ниже 1024px вместе с самой сеткой-таймлайном
   (см. медиазапросы в конце блока).
   ========================================================================= */
.process {
  position: relative;
  background: var(--bg-panel);
  padding-top: calc(60px * var(--u));
  padding-bottom: calc(82px * var(--u));
  padding-inline: var(--container-pad);
  overflow: hidden;
}
@media (min-width: 1025px) {
  .process { padding-inline: calc(110px * var(--u)); }
}

.process__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .12;
  background-image: image-set(
    url("../img/process-bg-1280.webp") type("image/webp"),
    url("../img/process-bg.jpg") type("image/jpeg")
  );
  background-size: cover;
  background-position: center;
}

.process__title {
  position: relative;
  z-index: 1;
  margin: 0 0 calc(80px * var(--u)) 0;
  color: var(--glnz-services-heading);
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-services-h2);
  line-height: normal;
}

.process__grid-wrap { position: relative; z-index: 1; }

/* Декор — выключен по умолчанию (мобильный/планшетный диапазон без
   таймлайна), включается только на десктопной 4-колоночной сетке. */
.process__decor { position: absolute; inset: 0; z-index: 0; display: none; }
.process__decor-line { position: absolute; background: var(--glnz-process-line); }
.process__decor-line--h {
  left: 0;
  right: 0;
  top: calc(130px * var(--u));
  height: 1px;
  background: linear-gradient(to right,
    transparent 0%, var(--glnz-process-line) 15%,
    var(--glnz-process-line) 85%, transparent 100%);
}
.process__decor-line--v {
  top: calc((130px - 52px) * var(--u));
  width: 1px;
  height: calc(271px * var(--u));
  transform: translateX(-50%);
}
.process__decor-line--v-1 { left: 25%; }
.process__decor-line--v-2 { left: 50%; }
.process__decor-line--v-3 { left: 75%; }
.process__decor-diamond {
  position: absolute;
  top: calc(130px * var(--u));
  width: calc(14px * var(--u));
  height: calc(14px * var(--u));
  background: var(--glnz-process-diamond);
  transform: translate(-50%, -50%) rotate(45deg);
  z-index: 1;
}
.process__decor-diamond--1 { left: 25%; }
.process__decor-diamond--2 { left: 50%; }
.process__decor-diamond--3 { left: 75%; }

.process__grid {
  position: relative;
  z-index: 1;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  row-gap: calc(60px * var(--u));
}
@media (min-width: 768px) {
  .process__grid {
    grid-template-columns: repeat(2, 1fr);
    column-gap: calc(40px * var(--u));
  }
}
@media (min-width: 1024px) {
  .process__grid { grid-template-columns: repeat(4, 1fr); gap: 0; }
  .process__decor { display: block; }
}

.process-step { position: relative; text-align: center; padding-inline: calc(20px * var(--u)); }

.process-step__num {
  display: block;
  margin: 0 0 calc(20px * var(--u)) 0;
  font-family: var(--glnz-font-process-num);
  font-weight: 700;
  font-size: var(--glnz-fs-services-h2); /* уменьшенный размер ниже 1024 — декоративная линия под цифрой отключена, точная 130px-коробка не нужна */
  line-height: normal;
  color: transparent;
  background-image: var(--glnz-process-num-gradient);
  -webkit-background-clip: text;
  background-clip: text;
}
.process-step__title {
  margin: 0 0 calc(12px * var(--u)) 0;
  font-family: var(--glnz-font-display);
  font-weight: 600;
  font-size: var(--glnz-fs-process-title);
  color: var(--glnz-text-white);
  letter-spacing: .04em;
}
.process-step__desc {
  margin: 0;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-process-desc);
  color: var(--glnz-stat-value);
  line-height: 1.6;
}

@media (min-width: 1024px) {
  .process-step__num {
    height: calc(130px * var(--u));
    line-height: calc(130px * var(--u));
    font-size: var(--glnz-fs-process-num);
    margin-bottom: 0;
  }
  .process-step__title { margin: calc(60px * var(--u)) 0 0 0; }
  .process-step__desc { margin: calc(50px * var(--u)) 0 0 0; }
}

/* =========================================================================
   WHY US
   ========================================================================= */
#why {
  position: relative;
  overflow: hidden;
  background: var(--glnz-services-bg);
  padding-top: calc(60px * var(--u));
  padding-bottom: calc(100px * var(--u));
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  #why { padding-inline: calc(110px * var(--u)); }
}
.why-media { position: absolute; inset: 0; z-index: 0; }
.why-media img { width: 100%; height: 100%; }
.why-media::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(13,13,15,.55) 0%, rgba(13,13,15,.9) 55%, var(--glnz-services-bg) 100%);
}
.why__inner { position: relative; z-index: 1; }

.why__title {
  margin: 0 0 calc(80px * var(--u)) 0;
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-services-h2);
  line-height: normal;
  color: var(--glnz-services-heading);
}

.why-grid {
  display: grid;
  grid-template-columns: 1fr;
  column-gap: calc(40px * var(--u));
  row-gap: calc(60px * var(--u));
}
@media (min-width: 768px) {
  .why-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .why-grid { grid-template-columns: repeat(3, 1fr); }
}

.why-item {
  display: flex;
  gap: calc(20px * var(--u));
  min-width: 0;
}
.why-item__icon {
  flex: none;
  width: calc(72px * var(--u));
  height: calc(72px * var(--u));
  border: 1px solid var(--glnz-accent-border-soft);
  border-radius: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--glnz-services-accent);
}
.why-item__icon svg { width: calc(32px * var(--u)); height: calc(32px * var(--u)); }
.why-item h3 {
  margin: 0 0 calc(12px * var(--u)) 0;
  font-family: var(--glnz-font-display);
  font-weight: 600;
  font-size: var(--glnz-fs-why-title);
  letter-spacing: .04em;
  color: var(--glnz-text-white);
}
.why-item p {
  margin: 0;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-why-desc);
  line-height: 1.6;
  color: var(--glnz-stat-value);
}

/* =========================================================================
   REVIEWS — «Что говорят клиенты», три карточки-цитаты на фоновом кадре.
   Макета сетки нет (есть только макет фона, backimage_var.pen — см. ниже):
   гутер, вертикальный ритм (60/120) и заголовок повторяют
   SERVICES/WORKS, лестница колонок 3/2/1 — та же, что у WORKS, на общих
   порогах 1024/768. Легаси-порог 761px старого .reviews-grid не переносим,
   он умер вместе с блоком.
   Подзаголовка у секции нет (в montazh.md только заголовок), поэтому
   отступ 80px до сетки несёт сам заголовок — расстояние «шапка → сетка»
   остаётся тем же, что у соседей (24 + 80 у пары title+lead читается как
   один интервал, здесь он собран в одно число).
   Карточки — на однотонной подложке с рамкой: единственная в секции
   графика, поэтому вся её сила в кегле и воздухе, а не в декоре.
   ========================================================================= */
.reviews {
  position: relative;
  background: var(--glnz-reviews-bg);
  padding-top: calc(60px * var(--u));
  padding-bottom: calc(120px * var(--u));
  padding-inline: var(--container-pad);
  overflow: hidden;
}
@media (min-width: 1025px) {
  .reviews { padding-inline: calc(110px * var(--u)); }
}

/* Фон и затемнение — двумя слоями, как в PROCESS: кадр отдельно, скрим
   отдельно. Раздельно потому, что степень затемнения владелец подбирает
   в DevTools, и она не должна требовать пересборки фона.
   Кадр посажен по центру (background-position: center) — так он стоит
   в макете backimage_var.pen: image-fill "fill" ровно по фрейму секции,
   без сдвига. Файл нарезан с запасом по высоте (1920x700 ≈ 2.74:1 против
   ~2.9:1 у реального бокса), лишнее срезает cover. */
.reviews__bg,
.reviews__scrim {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.reviews__bg {
  background-image: image-set(
    url("../img/reviews-bg-1920.webp") type("image/webp"),
    url("../img/reviews-bg.jpg") type("image/jpeg")
  );
  background-size: cover;
  background-position: center;
}
/* Ниже 1024 секция уже, кадр всё равно режется по ширине — 1920 там лишний вес */
@media (max-width: 1024px) {
  .reviews__bg {
    background-image: image-set(
      url("../img/reviews-bg-1280.webp") type("image/webp"),
      url("../img/reviews-bg.jpg") type("image/jpeg")
    );
  }
}
.reviews__scrim { background: var(--glnz-reviews-scrim); }

.reviews__title {
  position: relative;
  z-index: 1;
  margin: 0 0 calc(80px * var(--u)) 0;
  color: var(--glnz-services-heading);
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-services-h2);
  line-height: normal;
}

/* Лестница 3 / 2 / 1 на общих порогах проекта (1024 / 768) */
.reviews__grid {
  position: relative;
  z-index: 1;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: var(--glnz-reviews-gap);
}
@media (min-width: 768px)  { .reviews__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .reviews__grid { grid-template-columns: repeat(3, 1fr); } }

/* min-width:0 — тот же приём, что в .works__item / .services__item */
.reviews__item { list-style: none; min-width: 0; display: flex; }

/* stretch по высоте: три отзыва разной длины, но нижние края карточек
   в ряду должны стоять на одной линии — подпись прижимается к низу
   через margin-top:auto, а не подгонкой длины текста. */
.reviews__card {
  margin: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  background: var(--glnz-reviews-card-bg);
  border: 1px solid var(--glnz-reviews-border);
  padding: var(--glnz-reviews-card-pad);
  transition: border-color .25s var(--ease);
}
/* Тот же жест, что у плиток услуг: медь появляется по наведению */
.reviews__card:hover { border-color: var(--glnz-accent-border-soft); }

.reviews__text {
  margin: 0 0 calc(32px * var(--u)) 0;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-services-lead);
  line-height: 1.6;
  color: var(--glnz-stat-value);
}

.reviews__author {
  margin-top: auto;
  font-style: normal;
  display: flex;
  flex-direction: column;
  gap: calc(6px * var(--u));
}
.reviews__name {
  font-family: var(--glnz-font-display);
  font-weight: 500;
  font-size: var(--glnz-fs-reviews-author);
  letter-spacing: .04em;
  color: var(--glnz-services-accent);
}
.reviews__car {
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-services-desc);
  color: var(--glnz-stat-label);
}

@media (prefers-reduced-motion: reduce) {
  .reviews__card { transition: none; }
}

/* =========================================================================
   BOOKING — CTA-запись «Записаться на детейлинг».
   Макета нет: гутер, вертикальный ритм (60/120) и заголовочная пара
   повторяют SERVICES/WORKS. Раскладка ломается на общих порогах проекта:
   1024 — форма и заметки встают в две колонки, 768 — «Имя» и «Телефон»
   встают в ряд. Легаси-пороги 941/901 старого блока не переносим.

   Контракт с js/main.js (менять только вместе со скриптом): состояние
   ошибки — класс is-invalid НА ОБЁРТКЕ поля, скрипт ищет внутри неё
   `input, select`; показ статуса — класс is-visible; ошибка согласия
   переключается инлайновым display, поэтому её базовое состояние обязано
   быть display:none в CSS, иначе она видна до отправки.
   ========================================================================= */
.booking {
  position: relative;
  background: var(--glnz-booking-bg);
  padding-top: calc(60px * var(--u));
  padding-bottom: calc(120px * var(--u));
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  .booking { padding-inline: calc(110px * var(--u)); }
}

.booking__title {
  margin: 0 0 calc(24px * var(--u)) 0;
  color: var(--glnz-services-heading);
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-services-h2);
  line-height: normal;
}
.booking__lead {
  margin: 0 0 calc(80px * var(--u)) 0;
  color: var(--glnz-stat-label);
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-services-lead);
  line-height: normal;
}

.booking__layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--glnz-booking-gap);
}
/* Форма шире заметок: заметки — сопровождение, а не вторая колонка контента */
@media (min-width: 1024px) {
  .booking__layout { grid-template-columns: 1.35fr 1fr; align-items: start; }
}

/* Сетка полей: «Имя» и «Телефон» в ряд от 768, остальные — во всю ширину */
.booking__form {
  display: grid;
  grid-template-columns: 1fr;
  column-gap: calc(24px * var(--u));
  row-gap: var(--glnz-booking-row-gap);
  min-width: 0;
}
@media (min-width: 768px) {
  .booking__form { grid-template-columns: repeat(2, 1fr); }
}

.booking__field {
  display: flex;
  flex-direction: column;
  gap: calc(10px * var(--u));
  min-width: 0;
}
.booking__field--wide,
.booking__consent,
.booking__submit,
.booking__status { grid-column: 1 / -1; }

.booking__label {
  font-family: var(--glnz-font-body);
  font-weight: 500;
  font-size: var(--glnz-fs-booking-label);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--glnz-stat-label);
}
/* «(необязательно)» — тот же цвет, что подпись, приглушён прозрачностью:
   отдельный токен на один оттенок серого заводить не за чем. */
.booking__label-note {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  opacity: .7;
}

/* Радиуса нет нигде в новых секциях — поле тоже прямоугольное */
.booking__input {
  width: 100%;
  height: var(--glnz-booking-field-h);
  padding-inline: calc(20px * var(--u));
  background: var(--glnz-booking-field-bg);
  border: 1px solid var(--glnz-booking-field-border);
  border-radius: 0;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-booking-input);
  color: var(--glnz-text-onbtn);
  transition: border-color .25s var(--ease);
}
.booking__input::placeholder { color: var(--glnz-stat-label); }
.booking__input:focus {
  border-color: var(--glnz-services-accent);
  outline: none;
}
/* Стрелка селекта — свой chevron: нативная рисуется системой и на тёмном
   фоне выглядит инородно. SVG инлайном, потому что это часть оформления
   поля, а не самостоятельный ресурс. */
.booking__input--select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: calc(52px * var(--u));
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' fill='none' stroke='%23E89338' stroke-width='1.4'%3E%3Cpath d='M3.2 5.2 7 9l3.8-3.8'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right calc(20px * var(--u)) center;
  background-size: calc(14px * var(--u));
}
.booking__input--area {
  height: auto;
  min-height: calc(150px * var(--u));
  padding-block: calc(18px * var(--u));
  line-height: 1.6;
  resize: vertical;
}

.booking__error {
  display: none;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-booking-note);
  color: var(--glnz-booking-error);
}
.booking__field.is-invalid .booking__input { border-color: var(--glnz-booking-error); }
.booking__field.is-invalid .booking__error { display: block; }

/* Согласие: чекбокс и подпись в одну строку, ошибка — третьей ячейкой
   под подписью, чтобы не сдвигать чекбокс. */
.booking__consent {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
  column-gap: calc(14px * var(--u));
  row-gap: calc(8px * var(--u));
  margin-top: calc(4px * var(--u));
}
.booking__checkbox {
  width: calc(20px * var(--u));
  height: calc(20px * var(--u));
  margin: 0;
  accent-color: var(--glnz-services-accent);
}
.booking__consent-label {
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-booking-note);
  line-height: 1.5;
  color: var(--glnz-stat-label);
}
.booking__consent-label a {
  color: var(--glnz-services-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.booking__error--consent { grid-column: 2; }

/* Не близнец hero-кнопки намеренно: тот же жест (медь выезжает из центра),
   но геометрия своя — во всю ширину формы и ниже, потому что кнопка стоит
   в потоке формы, а не в композиции hero. Ширина hero-кнопки (260) здесь
   выглядела бы обрубком под полем в 950. */
.booking__submit {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  height: calc(72px * var(--u));
  margin-top: calc(12px * var(--u));
  background-color: transparent;
  border: 1px solid var(--glnz-accent-border);
  border-radius: 0;
  cursor: pointer;
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-btn-center);
  letter-spacing: calc(2px * var(--u));
  text-transform: uppercase;
  color: var(--glnz-text-white);
  transition: border-color .45s ease;
}
.booking__submit::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--glnz-accent);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform .45s cubic-bezier(.4, 0, .2, 1);
}
.booking__submit:hover::before { transform: scaleX(1); }
.booking__submit:hover { border-color: var(--glnz-accent); }

.booking__status {
  display: none;
  padding: calc(18px * var(--u)) calc(24px * var(--u));
  background: var(--glnz-booking-ok-bg);
  border: 1px solid var(--glnz-booking-ok-border);
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-booking-note);
  color: var(--glnz-booking-ok);
}
.booking__status.is-visible { display: block; }

/* Заметки — без подложки и рамки: рядом с формой из четырёх рамок ещё одна
   коробка дала бы «два бланка», поэтому список держится на медных галочках. */
.booking__aside { min-width: 0; }
.booking__notes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: calc(24px * var(--u));
}
.booking__note {
  display: flex;
  gap: calc(16px * var(--u));
  align-items: flex-start;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-services-desc);
  line-height: 1.6;
  color: var(--glnz-stat-value);
}
.booking__note-icon {
  flex: none;
  width: calc(20px * var(--u));
  height: calc(20px * var(--u));
  margin-top: calc(4px * var(--u));
  color: var(--glnz-services-accent);
}

@media (prefers-reduced-motion: reduce) {
  .booking__submit,
  .booking__submit::before,
  .booking__input { transition: none; }
}

/* =========================================================================
   CONTACTS — «Как нас найти», список + карта.
   Блок стоит после BOOKING, потому что после него секция идёт и в вёрстке
   (порядок блоков в файле = порядок секций на странице).
   Макета нет: гутер и ритм 60/120 как у соседей, лестница 1024/768.
   Легаси-порог 901px старого .contacts-layout не переносим.
   Подзаголовка у секции нет — весь отступ до содержимого несёт заголовок.
   ========================================================================= */
.contacts {
  position: relative;
  background: var(--glnz-contacts-bg);
  padding-top: calc(60px * var(--u));
  padding-bottom: calc(120px * var(--u));
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  .contacts { padding-inline: calc(110px * var(--u)); }
}

.contacts__title {
  margin: 0 0 calc(80px * var(--u)) 0;
  color: var(--glnz-services-heading);
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-services-h2);
  line-height: normal;
}

/* Карта шире списка: список — четыре короткие строки, карта — предмет,
   ради которого секция существует. align-items:stretch, чтобы карта
   тянулась на высоту списка, а не висела своим min-height. */
.contacts__layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--glnz-contacts-gap);
  align-items: stretch;
}
@media (min-width: 1024px) {
  .contacts__layout { grid-template-columns: 1fr 1.35fr; }
}

.contacts__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--glnz-contacts-row-gap);
  min-width: 0;
}
.contacts__row {
  display: flex;
  gap: calc(20px * var(--u));
  align-items: flex-start;
  min-width: 0;
}
/* Квадрат иконки — тот же элемент, что .why-item__icon, только 56 вместо 72 */
.contacts__icon {
  flex: none;
  width: var(--glnz-contacts-icon);
  height: var(--glnz-contacts-icon);
  border: 1px solid var(--glnz-accent-border-soft);
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--glnz-services-accent);
}
.contacts__icon svg { width: calc(24px * var(--u)); height: calc(24px * var(--u)); }

/* У строки мессенджеров своей иконки нет — её ячейка встаёт на то же
   место по горизонтали за счёт отступа шириной иконки и зазора. */
.contacts__row--msg { padding-left: calc(var(--glnz-contacts-icon) + 20px * var(--u)); }

.contacts__cell {
  display: flex;
  flex-direction: column;
  gap: calc(8px * var(--u));
  min-width: 0;
}
.contacts__label {
  font-family: var(--glnz-font-body);
  font-weight: 500;
  font-size: var(--glnz-fs-contacts-label);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--glnz-stat-label);
}
.contacts__value {
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-contacts-value);
  line-height: 1.4;
  color: var(--glnz-text-onbtn);
}
.contacts__value--link { transition: color .15s var(--ease); }
.contacts__value--link:hover { color: var(--glnz-services-accent); }

.contacts__msgs { display: flex; gap: calc(16px * var(--u)); }
.contacts__msg {
  width: var(--glnz-contacts-icon);
  height: var(--glnz-contacts-icon);
  border: 1px solid var(--glnz-accent-border-soft);
  border-radius: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--glnz-services-accent);
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.contacts__msg svg { width: calc(24px * var(--u)); height: calc(24px * var(--u)); }
.contacts__msg:hover { color: var(--glnz-text-onbtn); border-color: var(--glnz-accent); }

.contacts__map {
  min-height: var(--glnz-contacts-map-h);
  border: 1px solid var(--glnz-contacts-map-border);
  overflow: hidden;
  min-width: 0;
}
.contacts__map iframe {
  display: block;
  width: 100%;
  height: 100%;
  min-height: var(--glnz-contacts-map-h);
  border: 0;
}

/* =========================================================================
   FOOTER — подвал. Разметка общая для index/services/policy, на policy
   работает укороченный вариант .footer--slim (одна строка копирайта).
   Фон темнее полотна секций, но перепада тона на границе оказалось мало —
   подвал сливался с предыдущей секцией, поэтому сверху добавлена линия
   (.footer::before, см. ниже).
   ВАЖНО: ниже 1025 внизу висит фиксированная мобильная CTA-панель
   (.mobile-cta-bar, высота --stickybar-h) — она перекрыла бы копирайт,
   поэтому на этих ширинах подвалу добавляется её высота. Считать от того
   же токена, а не литералом: разъедется при первой правке панели.
   ========================================================================= */
.footer {
  position: relative; /* система координат для линии-::before, геометрию не меняет */
  background: var(--glnz-footer-bg);
  padding-top: calc(80px * var(--u));
  padding-bottom: calc(60px * var(--u));
  padding-inline: var(--container-pad);
}
/* Отделительная линия по верхнему краю подвала. Толщина и цвет взяты один
   в один с разделителя над нижней полосой hero (.hero__bottombar::after:
   height 1px, --glnz-section-divider) — это и есть отбивка между блоками
   в языке проекта, тем же токеном отбиты секция «Услуги» (.services::after)
   и низ шапки. Первая версия повторяла рамку иконок мессенджеров
   (.footer__msg, --glnz-accent-border-soft) — медь оказалась слишком
   толстой и яркой для разделителя.
   ::before, а не border-top: border лёг бы по всей ширине окна, а линия
   должна стоять на том же гутере, что и содержимое подвала. Отсюда же
   inset-inline, повторяющий padding-inline .footer (обе величины —
   в этом же блоке, правятся парой). Градиентного затухания к краям, как
   у hero, здесь нет намеренно: та линия идёт во всю ширину окна и гасится
   по краям, эта и так обрезана гутером. */
.footer::before {
  content: "";
  position: absolute;
  top: 0;
  inset-inline: var(--container-pad);
  height: 1px;
  background: var(--glnz-section-divider);
}
@media (min-width: 1025px) {
  .footer { padding-inline: calc(110px * var(--u)); }
  .footer::before { inset-inline: calc(110px * var(--u)); }
}
@media (max-width: 1024px) {
  .footer { padding-bottom: calc(60px * var(--u) + var(--stickybar-h)); }
}

/* Колонки распределены равными долями от гутера до гутера — прежние
   1.6fr/1.4fr на бренде стягивали три правые колонки к середине и оставляли
   у правого края пустое поле. Бренду лишняя ширина не нужна: слоган
   и так ограничен 32ch. */
.footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--glnz-footer-gap);
}
@media (min-width: 768px)  { .footer__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .footer__grid { grid-template-columns: repeat(4, 1fr); } }

.footer__brand { min-width: 0; }

/* Логотип подвала — две строки в духе hero: надстрочная строка и слово.
   Величины — см. блок токенов --glnz-fs-footer-eyebrow / -word. */
.footer__logo {
  display: block;
  margin-bottom: calc(26px * var(--u)); /* до слогана; в референсе 35 нативных от базовой линии слова, минус подслойный просвет строки */
  color: var(--glnz-text-white);
}
.footer__logo-eyebrow {
  display: block;
  font-family: var(--glnz-font-display);
  font-weight: 500;
  font-size: var(--glnz-fs-footer-eyebrow);
  letter-spacing: var(--glnz-footer-eyebrow-tracking);
  line-height: 1;
  color: var(--glnz-eyebrow);
  white-space: nowrap;
}
.footer__logo-word {
  display: block;
  margin-top: calc(10px * var(--u)); /* в референсе 18 нативных от базовой линии надстрочной до верха прописных «GLNZ»; между боксами строк это 10 */
  font-family: var(--glnz-font-display);
  font-weight: 700;
  font-size: var(--glnz-fs-footer-word);
  line-height: 1;
}
.footer__slogan {
  margin: 0 0 calc(28px * var(--u)) 0;
  max-width: 32ch;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-footer-slogan);
  line-height: 1.6;
  color: var(--glnz-stat-value);
}

.footer__msgs { display: flex; gap: calc(16px * var(--u)); }
.footer__msg {
  width: calc(48px * var(--u));
  height: calc(48px * var(--u));
  border: 1px solid var(--glnz-accent-border-soft);
  border-radius: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--glnz-services-accent);
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.footer__msg svg { width: calc(20px * var(--u)); height: calc(20px * var(--u)); }
.footer__msg:hover { color: var(--glnz-text-onbtn); border-color: var(--glnz-accent); }

.footer__col { min-width: 0; }
.footer__col-title {
  margin: 0 0 calc(24px * var(--u)) 0;
  font-family: var(--glnz-font-display);
  font-weight: 500;
  font-size: var(--glnz-fs-footer-title);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--glnz-services-heading);
}
.footer__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--glnz-footer-link-gap);
}
.footer__links a,
.footer__links span {
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-footer-link);
  line-height: 1.4;
  color: var(--glnz-stat-label);
}
.footer__links a { transition: color .15s var(--ease); }
.footer__links a:hover { color: var(--glnz-services-accent); }

/* Телефон — единственная ссылка подвала, набранная медью: тот же
   --glnz-services-accent, что у ссылки в согласии формы записи
   (.booking__consent-label a). Подчёркивания нет: там оно нужно, потому что
   ссылка сидит внутри строки текста, здесь строка своя.
   Наведение уводит НЕ в медь (она уже базовая), а в белый текст кнопок —
   так же, как у .footer__msg:hover. */
.footer__links a.footer__phone { color: var(--glnz-services-accent); }
.footer__links a.footer__phone:hover { color: var(--glnz-text-onbtn); }

/* Копирайт отделён не линией, а воздухом — линий на странице и так хватает */
.footer__copy {
  margin: calc(72px * var(--u)) 0 0 0;
  font-family: var(--glnz-font-body);
  font-weight: 400;
  font-size: var(--glnz-fs-footer-copy);
  color: var(--glnz-stat-label);
}

/* policy.html: сетки нет, копирайт стоит сам по себе */
.footer--slim { padding-block: calc(60px * var(--u)); }
.footer--slim .footer__copy { margin-top: 0; }

@media (prefers-reduced-motion: reduce) {
  .contacts__msg,
  .contacts__value--link,
  .footer__msg,
  .footer__links a { transition: none; }
}

/* =========================================================================
   SERVICES PAGE — hero и семь секций услуг (services.html).
   Эталон: services_hero5_3.html, канвасный экспорт Pencil, холст 1920.
   Из эталона взяты композиция, пропорции, кегли, цвета и тексты; разметка
   не переносилась — она собрана заново на flex/grid и токенах --glnz-*.

   Расхождения эталона с правилами проекта разрешены в пользу правил:
   боковой гутер в эталоне 120px, здесь общий проектный 110px (гутер шапки).
   Пороги перестройки — проектные 1440/1024/768/420, своих не заводим.

   Ключ ко всей странице — модификатор .svc--even (секции 02/04/06):
   он переставляет кадр вправо, даёт светлый фон и разворачивает краевую
   растяжку кадра. Три вещи чередуются по одной и той же чётности,
   поэтому класс один.
   ========================================================================= */

/* ---------- HERO страницы услуг (эталон 1920×860) ---------------------- */
.svc-hero {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background-color: var(--glnz-bg);
  /* 860 нативных из холста — низкий hero, не во весь экран.
     100svh только потолком-страховкой от переполнения на низких окнах. */
  min-height: min(var(--glnz-svc-hero-h), 100svh);
}
/* Кадр во всю ширину секции. Исходник 1584×672 — уже холста, поэтому
   единственный размер; приём выбора звена тот же, что у .hero__bg
   и .reviews__bg.
   Геометрия слоя перенесена из эталона буквально: высота равна высоте
   секции, а сам слой поднят на --glnz-svc-hero-bg-shift. Верх кадра
   срезается overflow'ом секции, снизу остаётся полоса чистого фона —
   именно так машина встаёт выше нижней полосы, а не заезжает в неё
   колёсами. */
.svc-hero__bg {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--glnz-svc-hero-bg-shift);
  height: var(--glnz-svc-hero-h);
  z-index: 0;
  background-image: image-set(
    url("../img/services/services-hero.webp") type("image/webp"),
    url("../img/services/services-hero.jpg") type("image/jpeg")
  );
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

/* Два списка услуг у левого и правого гутера. В эталоне это два
   абсолютных блока по 240px от y=150; здесь — обычный flex-ряд
   с распором, вертикаль задана padding-top. */
.svc-hero__lists {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: calc(40px * var(--u));
  padding-top: var(--glnz-svc-nav-top);
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  .svc-hero__lists { padding-inline: var(--glnz-svc-nav-gutter); }
}

.svc-nav {
  list-style: none;
  margin: 0;
  padding: 0;
  width: var(--glnz-svc-nav-w);
  min-width: 0;
  border-top: var(--glnz-svc-nav-rule) solid var(--glnz-svc-hairline);
}
/* Пункт списка — отдельный элемент со своими вложенными названием
   и номером. Так задумано под будущую анимацию появления: каждой
   строке можно дать свою задержку, не трогая разметку. Номера
   псевдоэлементами НЕ рисуются намеренно — их надо будет анимировать. */
.svc-nav__item { border-bottom: var(--glnz-svc-nav-rule) solid var(--glnz-svc-hairline); }
.svc-nav__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(12px * var(--u));
  height: var(--glnz-svc-nav-link-h);
  text-decoration: none;
  transition: color .15s var(--ease);
}
.svc-nav__name {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-nav);
  font-weight: 500;
  letter-spacing: calc(2px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-lead);
  transition: color .15s var(--ease);
}
.svc-nav__index {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-num);
  font-weight: 500;
  letter-spacing: calc(1.5px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-index);
  transition: color .15s var(--ease);
}
.svc-nav__link:hover .svc-nav__name,
.svc-nav__link:focus-visible .svc-nav__name { color: var(--glnz-text-onbtn); }
.svc-nav__link:hover .svc-nav__index,
.svc-nav__link:focus-visible .svc-nav__index { color: var(--glnz-services-accent); }

/* Нижняя полоса: кнопки слева, «ЗАПИСАТЬСЯ» строго по центру окна,
   statement справа — та же тройка колонок, что у hero главной. */
.svc-hero__bottom {
  position: relative;
  z-index: 3;
  display: grid;
  /* minmax(0, …) вместо голого 1fr: у 1fr минимум равен содержимому,
     поэтому крайние колонки отказывались сжиматься и выдавливали
     «ЗАПИСАТЬСЯ» из середины — кнопки наезжали друг на друга. Ширины
     на 1920 от этого не меняются: места там хватает, колонки равны. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: calc(24px * var(--u));
  min-height: calc(245px * var(--u));
  padding-inline: var(--container-pad);
  background-image: var(--glnz-svc-hero-bottombar);
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
@media (min-width: 1025px) {
  .svc-hero__bottom { padding-inline: calc(110px * var(--u)); }
}
/* Ступень 1440. Ниже неё три кнопки и абзац в одну строку не встают:
   --u уже упёрся в свой минимум 0.80 и перестал уменьшать содержимое,
   а окно продолжает сужаться. Абзац уходит на вторую строку целиком,
   первая остаётся кнопкам. Пустая третья ячейка первой строки сохранена
   намеренно — без неё «ЗАПИСАТЬСЯ» перестал бы стоять по центру окна.
   Порог из проектного набора (1440 / 1024 / 768 / 420), нового не заводим. */
@media (max-width: 1440px) {
  .svc-hero__bottom {
    grid-template-areas:
      "cta  book  ."
      "text text  text";
    row-gap: calc(28px * var(--u));
    padding-block: calc(32px * var(--u));
  }
  .svc-hero__cta { grid-area: cta; }
  .svc-hero__book { grid-area: book; }
  .svc-hero__statement { grid-area: text; }
}
.svc-hero__cta {
  display: flex;
  align-items: center;
  /* Перенос — последняя страховка на самых узких окнах выше 1024:
     обрезать кнопку хуже, чем поставить её на вторую строку. */
  flex-wrap: wrap;
  gap: calc(16px * var(--u));
  justify-self: start;
  min-width: 0;
}
.svc-hero__book { justify-self: center; }
.svc-hero__statement {
  justify-self: end;
  max-width: calc(607px * var(--u));
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-cta);
  font-weight: 400;
  line-height: calc(24 / 16);
  color: var(--glnz-stat-value);
}
/* h1 страницы. Визуально не выделен: течёт в том же абзаце тем же
   кеглем и цветом — ровно как в эталоне. */
.svc-hero__lede {
  display: inline;
  margin: 0;
  font: inherit;
  color: inherit;
}

/* === HERO-HOVER === НАЧАЛО =================================================
   Подсветка списка услуг в hero страницы услуг.
   Эталон: services_hero7.html, вариант A — кадр «1. Hover «Керамика» —
   свет и метка». Кадр 2 («технический маркер») намеренно не реализован.

   ВЫКЛЮЧАТЕЛЬ. Весь блок висит на селекторе body[data-hero-hover].
   Снять атрибут с <body> services.html — не сработает ни одно правило
   ниже, слои останутся пустыми коробками без фона, список статичен.
   JS (js/hero-hover.js) проверяет тот же атрибут и без него не вешает
   слушателей и не создаёт элементы накладок, то есть картинки
   не запрашиваются вовсе.

   СИСТЕМА КООРДИНАТ — главное место блока.
   Геометрия света и выноски снята с холста эталона 1920×860, но
   привязывать её к вьюпорту нельзя: фон hero положен background-size:cover,
   поэтому кадр 1584×672 масштабируется по большей стороне и на разных
   ширинах окна встаёт по-разному. Метка уехала бы с детали.
   Поэтому строится ДВА слоя:
     .svc-hero__fx-box   — точная копия коробки .svc-hero__bg
                           (left/right 0, top = --glnz-svc-hero-bg-shift,
                           height = --glnz-svc-hero-h);
     .svc-hero__fx-frame — внутри неё flex-центрированный прямоугольник
                           с пропорцией самого кадра 1584:672 и шириной
                           max(100%, высота × 1584/672). Это ровно тот
                           прямоугольник, в который cover вписывает
                           фотографию: при узком окне ширина определяется
                           высотой (кадр вылезает по бокам), при широком —
                           шириной (вылезает сверху и снизу).
   Всё внутри .svc-hero__fx-frame позиционируется В ПРОЦЕНТАХ от него,
   поэтому свет и маркеры приклеены к пикселям фотографии, а не к окну.
   Пересчёт координат холста в доли кадра:
     x = (x_холста + 53.57) / 2027.14      y = (y_холста + 90) / 860
   (2027.14×860 — размер кадра после cover в холсте 1920×860, 53.57 —
   вылет за левый край, 90 — подъём слоя.)
   Размеры «украшений» (кольцо, ромб, подписи) при этом остаются
   в calc(Npx * var(--u)): они часть типографики, а не фотографии.

   ВЫНОСКА ЖИВЁТ В ДВУХ СИСТЕМАХ СРАЗУ — читать перед правкой координат.
   Слой .svc-hero__calloutlayer лежит inset:0 в .svc-hero, то есть в
   координатах СЕКЦИИ, а не кадра. Поэтому долевые координаты кадра
   пересчитываются в координаты секции прямо в CSS, тремя величинами:
     --co-frame-w    ширина кадра после cover = max(100%, 860 × 1584/672)
     --co-frame-left его вылет влево = (100% − ширина) / 2
     --co-drop-x     x спуска в секции = вылет + доля × ширина
     --co-drop-y     y кольца в секции = подъём слоя + доля × высота
   Ради этого пересчёта доли записаны БЕЗРАЗМЕРНЫМИ множителями
   (0.37174), а не процентами: процент на длину в calc не умножается.
   Значения при переводе не менялись, 37.174% и 0.37174 — одна точка.

   Ближний к списку конец линии к кадру НЕ привязан — он привязан
   к строке списка:
     по вертикали --co-row-y = отступ списка + черта + (n−1) × шаг
                               + половина строки, где n = --co-n, номер
                               строки в своей колонке;
     по горизонтали --co-list-edge = гутер + ширина колонки + зазор
                               (--glnz-svc-fx-callout-gap, 26 из эталона).
   Так линия попадает в строку на любой ширине окна и не копит по 1px
   на каждой черте. Дальний конец, спуск, кольцо и ромб остаются
   на кадре: они показывают на деталь машины, а не на текст.

   ПОРЯДОК СЛОЁВ. .svc-hero__fx намеренно БЕЗ z-index: элемент с z-index
   создаёт контекст наложения, а он изолирует mix-blend-mode — накладки
   перестали бы смешиваться с фотографией и светились бы в пустоту.
   Слой без z-index рисуется по порядку в разметке: после .svc-hero__bg
   (z-index:0) и до списков (z-index:2). Выноска смешивания не требует,
   ей z-index:4 — поверх списков, как в эталоне.
   ========================================================================= */

/* ---------- Общие слои: коробка кадра и его cover-прямоугольник --------- */
body[data-hero-hover] .svc-hero__fx,
body[data-hero-hover] .svc-hero__calloutlayer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
body[data-hero-hover] .svc-hero__calloutlayer { z-index: 4; }

body[data-hero-hover] .svc-hero__fx-box {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--glnz-svc-hero-bg-shift);
  height: var(--glnz-svc-hero-h);
  display: flex;
  align-items: center;
  justify-content: center;
}
body[data-hero-hover] .svc-hero__fx-frame {
  position: relative;
  flex: 0 0 auto;
  width: max(100%, calc(var(--glnz-svc-hero-h) * 1584 / 672));
  aspect-ratio: 1584 / 672;
}

/* ---------- Затемнение сцены ------------------------------------------- */
body[data-hero-hover] .svc-hero__scenedim {
  position: absolute;
  inset: 0;
  background-color: var(--glnz-svc-fx-dim);
  opacity: 0;
  transition: opacity var(--glnz-svc-fx-dur) ease-out;
}
body[data-hero-hover] .svc-hero[data-svc-fx] .svc-hero__scenedim { opacity: 1; }

/* ---------- Световые накладки ------------------------------------------ */
/* Элементы создаёт JS после события load; в разметке первого экрана их нет.
   Эллипс режется border-radius'ом на слое — ровно как в эталоне, поэтому
   в самих картинках прозрачного запаса по краям нет и обрезать нечего. */
body[data-hero-hover] .svc-hero__pool {
  position: absolute;
  left: var(--fx-l);
  top: var(--fx-t);
  width: var(--fx-w);
  height: var(--fx-h);
  border-radius: 50%;
  mix-blend-mode: screen;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  opacity: 0;
  transition: opacity var(--glnz-svc-fx-dur) ease-out;
}
body[data-hero-hover] .svc-hero[data-svc-fx="01"] .svc-hero__pool--01,
body[data-hero-hover] .svc-hero[data-svc-fx="02"] .svc-hero__pool--02,
body[data-hero-hover] .svc-hero[data-svc-fx="03"] .svc-hero__pool--03,
body[data-hero-hover] .svc-hero[data-svc-fx="04"] .svc-hero__pool--04,
body[data-hero-hover] .svc-hero[data-svc-fx="05"] .svc-hero__pool--05,
body[data-hero-hover] .svc-hero[data-svc-fx="06"] .svc-hero__pool--06,
body[data-hero-hover] .svc-hero[data-svc-fx="07"] .svc-hero__pool--07 { opacity: 1; }

/* 01 керамика — кузов: капот, крылья, двери, крыша */
body[data-hero-hover] .svc-hero__pool--01-1 { --fx-l: 19.908%; --fx-t: 47.907%; --fx-w: 61.170%; --fx-h: 23.953%; background-image: url("../img/services/hero-fx/01-1.webp"); }
body[data-hero-hover] .svc-hero__pool--01-2 { --fx-l: 44.278%; --fx-t: 35.349%; --fx-w: 21.015%; --fx-h: 14.419%; background-image: url("../img/services/hero-fx/01-2.webp"); }
body[data-hero-hover] .svc-hero__pool--01-3 { --fx-l: 21.191%; --fx-t: 48.837%; --fx-w: 25.652%; --fx-h: 13.721%; background-image: url("../img/services/hero-fx/01-3.webp"); }
/* 02 антигравий — передняя зона удара, зеркала, пороги */
body[data-hero-hover] .svc-hero__pool--02-1 { --fx-l: 18.428%; --fx-t: 50.000%; --fx-w: 27.625%; --fx-h: 25.581%; background-image: url("../img/services/hero-fx/02-1.webp"); }
body[data-hero-hover] .svc-hero__pool--02-2 { --fx-l: 23.855%; --fx-t: 50.000%; --fx-w: 20.719%; --fx-h: 13.953%; background-image: url("../img/services/hero-fx/02-2.webp"); }
body[data-hero-hover] .svc-hero__pool--02-3 { --fx-l: 41.860%; --fx-t: 48.256%; --fx-w:  5.920%; --fx-h:  8.372%; background-image: url("../img/services/hero-fx/02-3.webp"); }
body[data-hero-hover] .svc-hero__pool--02-4 { --fx-l: 44.574%; --fx-t: 64.535%; --fx-w: 26.638%; --fx-h:  9.302%; background-image: url("../img/services/hero-fx/02-4.webp"); }
/* 03 полировка — лак борта, узкий протяжённый блик */
body[data-hero-hover] .svc-hero__pool--03-1 { --fx-l: 37.174%; --fx-t: 54.884%; --fx-w: 44.397%; --fx-h: 10.698%; background-image: url("../img/services/hero-fx/03-1.webp"); }
body[data-hero-hover] .svc-hero__pool--03-2 { --fx-l: 41.121%; --fx-t: 56.744%; --fx-w: 36.505%; --fx-h:  5.349%; background-image: url("../img/services/hero-fx/03-2.webp"); }
body[data-hero-hover] .svc-hero__pool--03-3 { --fx-l: 23.362%; --fx-t: 51.395%; --fx-w: 18.746%; --fx-h:  9.302%; background-image: url("../img/services/hero-fx/03-3.webp"); }
/* 04 жидкое стекло — ЛКП, оптика, бамперы, диски */
body[data-hero-hover] .svc-hero__pool--04-1 { --fx-l: 19.908%; --fx-t: 46.512%; --fx-w: 63.636%; --fx-h: 27.907%; background-image: url("../img/services/hero-fx/04-1.webp"); }
body[data-hero-hover] .svc-hero__pool--04-2 { --fx-l: 44.574%; --fx-t: 35.814%; --fx-w: 20.719%; --fx-h: 13.953%; background-image: url("../img/services/hero-fx/04-2.webp"); }
/* Диски: картинка одна, мест два — левое и правое. */
body[data-hero-hover] .svc-hero__pool--04-3 { --fx-l: 25.433%; --fx-t: 56.744%; --fx-w: 10.261%; --fx-h: 24.186%; background-image: url("../img/services/hero-fx/04-3.webp"); }
body[data-hero-hover] .svc-hero__pool--04-4 { --fx-l: 62.727%; --fx-t: 56.744%; --fx-w: 10.261%; --fx-h: 24.186%; background-image: url("../img/services/hero-fx/04-3.webp"); }
body[data-hero-hover] .svc-hero__pool--04-5 { --fx-l: 19.415%; --fx-t: 56.047%; --fx-w:  7.893%; --fx-h:  8.140%; background-image: url("../img/services/hero-fx/04-5.webp"); }
body[data-hero-hover] .svc-hero__pool--04-6 { --fx-l: 75.159%; --fx-t: 55.116%; --fx-w:  7.400%; --fx-h:  7.209%; background-image: url("../img/services/hero-fx/04-6.webp"); }
body[data-hero-hover] .svc-hero__pool--04-7 { --fx-l: 18.231%; --fx-t: 59.070%; --fx-w:  9.866%; --fx-h: 13.023%; background-image: url("../img/services/hero-fx/04-7.webp"); }
body[data-hero-hover] .svc-hero__pool--04-8 { --fx-l: 77.428%; --fx-t: 59.070%; --fx-w:  8.386%; --fx-h: 13.023%; background-image: url("../img/services/hero-fx/04-8.webp"); }
/* 05 химчистка — салон через открытую дверь */
body[data-hero-hover] .svc-hero__pool--05-1 { --fx-l: 45.560%; --fx-t: 44.884%; --fx-w: 14.799%; --fx-h: 26.047%; background-image: url("../img/services/hero-fx/05-1.webp"); }
body[data-hero-hover] .svc-hero__pool--05-2 { --fx-l: 49.013%; --fx-t: 49.535%; --fx-w:  8.682%; --fx-h: 16.744%; background-image: url("../img/services/hero-fx/05-2.webp"); }
/* 06 тонировка — боковые и заднее стекло */
body[data-hero-hover] .svc-hero__pool--06-1 { --fx-l: 46.350%; --fx-t: 39.302%; --fx-w: 13.615%; --fx-h: 14.419%; background-image: url("../img/services/hero-fx/06-1.webp"); }
body[data-hero-hover] .svc-hero__pool--06-2 { --fx-l: 58.682%; --fx-t: 39.767%; --fx-w:  6.610%; --fx-h: 12.093%; background-image: url("../img/services/hero-fx/06-2.webp"); }
/* 07 предпродажная — автомобиль целиком */
body[data-hero-hover] .svc-hero__pool--07-1 { --fx-l: 17.442%; --fx-t: 35.349%; --fx-w: 69.063%; --fx-h: 48.837%; background-image: url("../img/services/hero-fx/07-1.webp"); }
body[data-hero-hover] .svc-hero__pool--07-2 { --fx-l: 23.362%; --fx-t: 50.000%; --fx-w: 44.397%; --fx-h: 23.256%; background-image: url("../img/services/hero-fx/07-2.webp"); }

/* ---------- Выноска: линия, спуск, кольцо, подпись ---------------------- */
/* Геометрия каждой из семи выносок — ТРИ величины (было пять):
     --co-n       номер строки в своей колонке, 1..4 — от него вертикаль
     --co-vx      x спуска, доля ширины кадра (он же ось кольца и ромба)
     --co-ring-y  y кольца и ромба, доля высоты кадра
   --co-hl / --co-hw / --co-y / --co-vh больше нет: ближний конец линии
   и её высота теперь считаются от списка, а не от холста, а длина линии
   получается сама — она растянута между двумя якорями через left+right.
   Ближний к списку конец линии прозрачный (градиент из #E8933800),
   поэтому зазор --glnz-svc-fx-callout-gap читается как воздух, а не
   как обрыв. */
/* ЗАМОК ВЫНОСКИ. Отдельная коробка вокруг выноски, нужная ровно за одним:
   дать CSS сравнить ДЛИНУ ЛИНИИ с порогом, без единого замера из JS.
   Приём: высота замка = длина линии минус порог, прижатая нулём снизу.
   Линия длиннее порога — высота положительная; короче — ровно 0. Дальше
   замок объявлен size-контейнером, и вся выноска показывается изнутри
   запроса @container (min-height: 1px). Порог сидит в токене и крутится
   без правки запроса — в самом запросе стоит неизменяемый 1px.
   Ширина замка — во всю секцию, поэтому горизонтальные проценты внутри
   выноски считаются от неё, как и раньше. Высота у него служебная:
   вертикальных процентов в выноске нет ни одного, всё в px * --u,
   поэтому схлопывание высоты ничего не двигает. Дети из нулевой высоты
   свободно вылезают: contain от container-type НЕ обрезает рисование.
   Длина линии для замка считается в vw, а не в процентах: проценты
   в height мерились бы по вертикали. Разница с реальной шириной — полоса
   прокрутки, ~15px; для порога, который подбирают на глаз, это шум. */
body[data-hero-hover] .svc-hero__callout-gate {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: max(0px, calc(var(--co-len) - var(--glnz-svc-fx-callout-min)));
  container-type: size;
  container-name: co-gate;

  /* Кадр после cover и его вылет влево — пересчёт долей кадра
     в координаты секции. Проценты здесь горизонтальные: значения
     используются только в left/right. */
  --co-frame-w: max(100%, calc(var(--glnz-svc-hero-h) * 1584 / 672));
  --co-frame-left: calc((100% - var(--co-frame-w)) / 2);
  --co-drop-x: calc(var(--co-frame-left) + var(--co-vx) * var(--co-frame-w));
  --co-drop-y: calc(var(--glnz-svc-hero-bg-shift) + var(--co-ring-y) * var(--glnz-svc-hero-h));

  /* Центр активной строки списка. Шаг строки — высота ПЛЮС 1px черты:
     черта волосяная и на --u не масштабируется. */
  --co-row-y: calc(
    var(--glnz-svc-nav-top) + var(--glnz-svc-nav-rule)
    + (var(--co-n) - 1) * (var(--glnz-svc-nav-link-h) + var(--glnz-svc-nav-rule))
    + var(--glnz-svc-nav-link-h) / 2
  );
  /* Ближний конец линии: от внешнего края окна до края колонки плюс зазор.
     Величина одна на обе стороны — колонки стоят симметрично. */
  --co-list-edge: calc(
    var(--glnz-svc-nav-gutter) + var(--glnz-svc-nav-w) + var(--glnz-svc-fx-callout-gap)
  );
  /* То же x спуска, но в vw — только для замера длины (см. выше).
     Вывод: x = ширина/2 + ширина_кадра × (доля − 0.5). */
  --co-frame-w-vw: max(100vw, calc(var(--glnz-svc-hero-h) * 1584 / 672));
  --co-drop-x-vw: calc(50vw + (var(--co-vx) - 0.5) * var(--co-frame-w-vw));
  /* Левый список: линия идёт от колонки вправо до спуска. */
  --co-len: calc(var(--co-drop-x-vw) - var(--co-list-edge));
}
/* Правый список: линия идёт от спуска влево до колонки — длина зеркальна. */
body[data-hero-hover] .svc-hero[data-svc-fx="05"] .svc-hero__callout-gate,
body[data-hero-hover] .svc-hero[data-svc-fx="06"] .svc-hero__callout-gate,
body[data-hero-hover] .svc-hero[data-svc-fx="07"] .svc-hero__callout-gate {
  --co-len: calc(100vw - var(--co-list-edge) - var(--co-drop-x-vw));
}

body[data-hero-hover] .svc-hero__callout {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--glnz-svc-fx-dur) ease-out;
}
/* Единственное место, где выноска зажигается. Замок короче порога —
   правило не применяется вовсе, и выноска уходит в 0 тем же переходом. */
@container co-gate (min-height: 1px) {
  body[data-hero-hover] .svc-hero[data-svc-fx] .svc-hero__callout { opacity: 1; }
}

/* Линия растянута между списком и спуском: left от списка, right от кадра.
   Ширина не задаётся — она и есть расстояние между двумя системами. */
body[data-hero-hover] .svc-hero__callout-h {
  position: absolute;
  left: var(--co-list-edge);
  right: calc(100% - var(--co-drop-x));
  top: var(--co-row-y);
  height: 1px;
  background-image: var(--glnz-svc-fx-leader-start);
}
body[data-hero-hover] .svc-hero__callout-v {
  position: absolute;
  left: var(--co-drop-x);
  top: var(--co-row-y);
  width: 1px;
  height: calc(var(--co-drop-y) - var(--co-row-y));
  background-image: var(--glnz-svc-fx-leader-drop);
}
body[data-hero-hover] .svc-hero__callout-ring {
  position: absolute;
  left: var(--co-drop-x);
  top: var(--co-drop-y);
  width: calc(41px * var(--u));
  height: calc(41px * var(--u));
  margin-left: calc(-20.5px * var(--u));
  margin-top: calc(-20.5px * var(--u));
  border: calc(1.4px * var(--u)) solid var(--glnz-svc-tick);
  border-radius: 50%;
}
/* Ромб 13×13 из эталона — квадрат стороной 13/√2, повёрнутый на 45°. */
body[data-hero-hover] .svc-hero__callout-pin {
  position: absolute;
  left: var(--co-drop-x);
  top: var(--co-drop-y);
  width: calc(9.19px * var(--u));
  height: calc(9.19px * var(--u));
  margin-left: calc(-4.6px * var(--u));
  margin-top: calc(-4.6px * var(--u));
  background-color: var(--glnz-services-accent);
  transform: rotate(45deg);
}
body[data-hero-hover] .svc-hero__callout-label,
body[data-hero-hover] .svc-hero__callout-sub {
  position: absolute;
  white-space: nowrap;
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-callout);
  line-height: normal;
}
body[data-hero-hover] .svc-hero__callout-label {
  top: calc(var(--co-row-y) - 14px * var(--u));
  font-weight: 500;
  letter-spacing: calc(2px * var(--u));
  color: var(--glnz-services-accent);
}
body[data-hero-hover] .svc-hero__callout-sub {
  top: calc(var(--co-row-y) + 6px * var(--u));
  font-weight: 400;
  letter-spacing: calc(0.6px * var(--u));
  color: var(--glnz-svc-fx-sub);
}
/* Подложка под подписью: пятно на каждой из двух строк отдельно.
   Почему не одно общее — ширина у подписей разная и заранее неизвестна
   (текст ставит JS, строка nowrap); пятно на самой строке растёт вместе
   с ней. По вертикали вылеты подобраны так, что пятна смыкаются в одно
   облако, прямоугольной плашки не образуя.
   z-index:-1 — не украшение, а требование: он уводит пятно в нижний слой
   .svc-hero__calloutlayer, ниже линии, спуска, кольца и ромба. Перекрыть
   их пятно физически не может, даже если владелец задерёт вылеты.
   Гаснет вместе с выноской само: opacity живёт на .svc-hero__callout,
   пятно внутри него. */
body[data-hero-hover] .svc-hero__callout-label::before,
body[data-hero-hover] .svc-hero__callout-sub::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: calc(var(--glnz-svc-fx-plate-y) * -1) calc(var(--glnz-svc-fx-plate-x) * -1);
  background-image: var(--glnz-svc-fx-plate);
  opacity: var(--glnz-svc-fx-plate-alpha);
}
/* Левый список (01–04): линия уходит вправо, подпись справа от спуска.
   max() — упор в край своей колонки: при узком окне спуск уезжает влево
   и утаскивает подпись на пункты меню. Дальше края колонки плюс тот же
   зазор подпись не пускаем ни при каких обстоятельствах. Многоточия нет
   намеренно: до обрезки дело не доходит, порог гашения срабатывает
   раньше — упор здесь страховка, а не рабочий режим. */
body[data-hero-hover] .svc-hero__callout-label,
body[data-hero-hover] .svc-hero__callout-sub {
  left: max(var(--co-list-edge), calc(var(--co-drop-x) + 18px * var(--u)));
  text-align: left;
}
/* Правый список (05–07): линия уходит влево, подпись слева от спуска.
   Якоря меняются местами: left теперь от кадра, right — от списка. */
body[data-hero-hover] .svc-hero[data-svc-fx="05"] .svc-hero__callout-h,
body[data-hero-hover] .svc-hero[data-svc-fx="06"] .svc-hero__callout-h,
body[data-hero-hover] .svc-hero[data-svc-fx="07"] .svc-hero__callout-h {
  left: var(--co-drop-x);
  right: var(--co-list-edge);
  background-image: var(--glnz-svc-fx-leader-end);
}
body[data-hero-hover] .svc-hero[data-svc-fx="05"] .svc-hero__callout-label,
body[data-hero-hover] .svc-hero[data-svc-fx="05"] .svc-hero__callout-sub,
body[data-hero-hover] .svc-hero[data-svc-fx="06"] .svc-hero__callout-label,
body[data-hero-hover] .svc-hero[data-svc-fx="06"] .svc-hero__callout-sub,
body[data-hero-hover] .svc-hero[data-svc-fx="07"] .svc-hero__callout-label,
body[data-hero-hover] .svc-hero[data-svc-fx="07"] .svc-hero__callout-sub {
  left: auto;
  right: max(var(--co-list-edge), calc(100% - var(--co-drop-x) + 18px * var(--u)));
  text-align: right;
}
/* Семь наборов координат выноски.
   --co-ring-y — бывшая сумма --co-y + --co-vh, то есть та же точка кольца
   на кадре, только записанная одним числом и долей вместо процента:
   0.53023 = 30.930% + 22.093%. Точки не двигались.
   --co-n — номер строки в СВОЕЙ колонке, поэтому у 05 он 1, а не 5.
   Набор стоит на ЗАМКЕ, а не на самой выноске: замку эти числа нужны
   раньше всех — он ими считает длину линии. Дальше они наследуются вниз. */
body[data-hero-hover] .svc-hero[data-svc-fx="01"] .svc-hero__callout-gate { --co-n: 1; --co-vx: 0.37174; --co-ring-y: 0.53023; }
body[data-hero-hover] .svc-hero[data-svc-fx="02"] .svc-hero__callout-gate { --co-n: 2; --co-vx: 0.28295; --co-ring-y: 0.58721; }
body[data-hero-hover] .svc-hero[data-svc-fx="03"] .svc-hero__callout-gate { --co-n: 3; --co-vx: 0.37174; --co-ring-y: 0.56744; }
body[data-hero-hover] .svc-hero[data-svc-fx="04"] .svc-hero__callout-gate { --co-n: 4; --co-vx: 0.33228; --co-ring-y: 0.54651; }
body[data-hero-hover] .svc-hero[data-svc-fx="05"] .svc-hero__callout-gate { --co-n: 1; --co-vx: 0.57893; --co-ring-y: 0.52325; }
body[data-hero-hover] .svc-hero[data-svc-fx="06"] .svc-hero__callout-gate { --co-n: 2; --co-vx: 0.64306; --co-ring-y: 0.43954; }
body[data-hero-hover] .svc-hero[data-svc-fx="07"] .svc-hero__callout-gate { --co-n: 3; --co-vx: 0.74172; --co-ring-y: 0.56395; }

/* ---------- Список услуг во время наведения ---------------------------- */
/* Активная строка — это :hover, отдельный класс не нужен. Шесть остальных
   гасятся, пока на heroи выставлен data-svc-fx (его ставит JS).
   Сдвиг активной строки сделан padding-left, а не transform: номер строки
   прижат к правому краю через space-between и должен остаться на месте —
   в эталоне сдвинута только подпись. */
body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__name { color: var(--glnz-svc-fx-lead); }
body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__index { color: var(--glnz-svc-fx-index); }
body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__link:hover { padding-left: var(--glnz-svc-fx-shift); }
body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__link:hover .svc-nav__name {
  color: var(--glnz-text-white);
  font-weight: 600;
}
body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__link:hover .svc-nav__index {
  color: var(--glnz-services-accent);
}
body[data-hero-hover] .svc-hero .svc-nav__link { transition: color var(--glnz-svc-fx-dur) ease-out, padding-left var(--glnz-svc-fx-dur) ease-out; }
body[data-hero-hover] .svc-hero .svc-nav__name,
body[data-hero-hover] .svc-hero .svc-nav__index { transition: color var(--glnz-svc-fx-dur) ease-out; }

/* ---------- Где эффект не работает ------------------------------------- */
/* Тач-устройства: слои не показываются, список статичен. JS проверяет
   тот же медиазапрос и накладок не создаёт — картинки не грузятся. */
@media (hover: none), (pointer: coarse) {
  body[data-hero-hover] .svc-hero__fx,
  body[data-hero-hover] .svc-hero__calloutlayer { display: none; }
  body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__name { color: var(--glnz-svc-lead); }
  body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__index { color: var(--glnz-svc-index); }
  body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__link:hover { padding-left: 0; }
}
/* Ниже 1025 hero перестроен (.svc-hero__bg получает top:0/height:100%),
   и координатная система накладок ломается. Порог проектный, своего
   не заводим. */
@media (max-width: 1024px) {
  body[data-hero-hover] .svc-hero__fx,
  body[data-hero-hover] .svc-hero__calloutlayer { display: none; }
  body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__name { color: var(--glnz-svc-lead); }
  body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__index { color: var(--glnz-svc-index); }
  body[data-hero-hover] .svc-hero[data-svc-fx] .svc-nav__link:hover { padding-left: 0; }
}
/* Выбранный вариант: эффект остаётся, переходы снимаются — состояния
   меняются мгновенно. Полностью гасить подсветку не стали: она несёт
   смысл (какая услуга к какой детали), а раздражает именно движение. */
@media (prefers-reduced-motion: reduce) {
  body[data-hero-hover] .svc-hero__scenedim,
  body[data-hero-hover] .svc-hero__pool,
  body[data-hero-hover] .svc-hero__callout,
  body[data-hero-hover] .svc-hero .svc-nav__link,
  body[data-hero-hover] .svc-hero .svc-nav__name,
  body[data-hero-hover] .svc-hero .svc-nav__index { transition-duration: .01ms !important; }
}
/* === /HERO-HOVER === КОНЕЦ ================================================ */

/* ---------- Секция услуги ---------------------------------------------- */
.svc {
  position: relative;
  overflow: hidden;
  background: var(--glnz-bg);
  /* 48 до верхней черты + 56 от черты до надзаголовка = 104 сверху,
     88 снизу — ритм эталона. */
  padding-top: calc(104px * var(--u));
  padding-bottom: calc(88px * var(--u));
}
.svc--even { background: var(--glnz-services-bg); }
/* Верхняя черта секции — на гутере, не во всю ширину окна. */
.svc::before {
  content: "";
  position: absolute;
  top: calc(48px * var(--u));
  inset-inline: var(--container-pad);
  height: 1px;
  background: var(--glnz-svc-hairline);
}
/* Фоновый кадр третьей секции — приём .process__bg с главной:
   отдельный слой inset:0 под контентом, приглушённый opacity. */
.svc__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .12;
  background-image: image-set(
    url("../img/services/polish-bg-1280.webp") type("image/webp"),
    url("../img/services/polish-bg-1280.jpg") type("image/jpeg")
  );
  background-size: cover;
  background-position: center;
}
@media (min-width: 1025px) {
  .svc__bg {
    background-image: image-set(
      url("../img/services/polish-bg-1920.webp") type("image/webp"),
      url("../img/services/polish-bg-1920.jpg") type("image/jpeg")
    );
  }
}

.svc__head {
  position: relative;
  z-index: 1;
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  .svc::before { inset-inline: calc(110px * var(--u)); }
  .svc__head { padding-inline: calc(110px * var(--u)); }
}
.svc__eyebrow {
  display: flex;
  align-items: center;
  gap: calc(14px * var(--u));
  margin-bottom: calc(22px * var(--u));
}
.svc__num {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-num);
  font-weight: 500;
  letter-spacing: calc(1.5px * var(--u));
  line-height: normal;
  color: var(--glnz-services-accent);
}
.svc__tick {
  flex-shrink: 0;
  width: calc(24px * var(--u));
  height: 1px;
  background: var(--glnz-svc-tick);
}
.svc__label,
.svc__kicker {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-meta);
  font-weight: 500;
  letter-spacing: calc(2px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-label);
}
/* «УСЛУГИ ДЕТЕЙЛИНГА» прижат к правому краю строки */
.svc__kicker { margin-left: auto; }
.svc__title {
  margin: 0;
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-svc-h2);
  font-weight: 700;
  letter-spacing: calc(-2px * var(--u));
  line-height: calc(97 / 92);
  color: var(--glnz-text-onbtn);
}

/* Раскладка «кадр + текст». Кадр уходит под край окна (в эталоне колонка
   1120 из 1920 стоит вплотную к краю холста), подпись под ним и текстовая
   колонка остаются на гутере. Текст центрируется по высоте КАДРА, а не
   всей колонки с подписью, — поэтому подпись отдельный элемент сетки
   во второй строке, а не часть медиа-блока. */
.svc__split {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  row-gap: calc(22px * var(--u));
  margin-top: calc(72px * var(--u));
}
.svc__media {
  position: relative;
  grid-column: 1;
  grid-row: 1;
  min-width: 0;
  line-height: 0;
}
.svc__photo,
.svc__photo img {
  display: block;
  width: 100%;
}
.svc__photo img {
  aspect-ratio: 1120 / 660;
  height: auto;
  object-fit: cover;
}
/* Два слоя эталона поверх кадра: краевая растяжка в фон секции
   и ровная вуаль. Направление растяжки — к внешнему краю окна. */
.svc__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(var(--glnz-svc-veil-dark), var(--glnz-svc-veil-dark));
}
.svc--even .svc__scrim {
  background-image: linear-gradient(var(--glnz-svc-veil-light), var(--glnz-svc-veil-light));
}
.svc__caption {
  grid-column: 1;
  grid-row: 2;
  margin: 0;
  padding-inline: var(--container-pad);
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-meta);
  font-weight: 400;
  letter-spacing: calc(.6px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-label);
}
.svc__text {
  grid-column: 1;
  grid-row: 3;
  min-width: 0;
  padding-inline: var(--container-pad);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(34px * var(--u));
}
.svc__lead {
  margin: 0;
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-lead);
  font-weight: 400;
  line-height: calc(30 / 19);
  color: var(--glnz-svc-lead);
}
.svc__body {
  margin: 0;
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-body);
  font-weight: 400;
  line-height: calc(26 / 15);
  color: var(--glnz-nav-link);
}

/* Характеристики — три строки «ключ / значение» с разделителями. */
.svc__specs { margin: 0; width: 100%; }
.svc__spec {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(16px * var(--u));
  height: calc(54px * var(--u));
  border-bottom: 1px solid var(--glnz-svc-hairline);
}
.svc__spec-key {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-meta);
  font-weight: 500;
  letter-spacing: calc(2px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-label);
}
.svc__spec-value {
  margin: 0;
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-svc-lead);
  font-weight: 600;
  letter-spacing: calc(-.2px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
  white-space: nowrap;
}

.svc__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(16px * var(--u));
}
/* Цена стоит в такой же обведённой коробке, что и вторая кнопка
   (селектор .svc__price добавлен в группу .hero__btn-secondary выше),
   но кликабельной не является — это не кнопка, а строка цены. */
.svc__price {
  margin: 0;
  padding: calc(20px * var(--u)) calc(28px * var(--u));
}
.svc__price-value {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-price);
  font-weight: 700;
  letter-spacing: calc(.3px * var(--u));
  line-height: normal;
  color: var(--glnz-services-accent);
  white-space: nowrap;
}

/* ---------- Две колонки: от 1025 ---------------------------------------
   Ниже 1025 текстовая колонка ужалась бы до ~280px при кадре 600 —
   раскладка эталона на таком экране не читается, поэтому в один столбец.
   Порог совпадает с порогом гутера, отдельного не заводим. */
@media (min-width: 1025px) {
  .svc__split {
    grid-template-columns: 1120fr 520fr;
    column-gap: calc(160px * var(--u));
    padding-right: calc(110px * var(--u));
  }
  /* align-self:start — иначе при длинном тексте строка сетки становится
     выше кадра, блок растягивается, и слои .svc__scrim (inset:0) вылезают
     ниже фотографии. */
  .svc__media   { grid-column: 1; grid-row: 1; align-self: start; }
  .svc__caption { grid-column: 1; grid-row: 2; padding-inline: 0; padding-left: calc(110px * var(--u)); }
  .svc__text    { grid-column: 2; grid-row: 1; align-self: center; padding-inline: 0; }

  /* Чётные: кадр справа, текст слева. Меняется не только сторона, но и
     ПОРЯДОК ДОРОЖЕК — иначе кадр попадает в узкую колонку, а текст
     разъезжается на широкую. Пропорция 1120:520 одна и та же во всех
     семи секциях, меняется только то, с какой стороны стоит широкая
     дорожка. Гутер уезжает на левую сторону вслед за текстом. */
  .svc--even .svc__split {
    grid-template-columns: 520fr 1120fr;
    padding-right: 0;
    padding-left: calc(110px * var(--u));
  }
  .svc--even .svc__media   { grid-column: 2; }
  .svc--even .svc__caption { grid-column: 2; padding-left: 0; }
  .svc--even .svc__text    { grid-column: 1; }

  /* Краевая растяжка кадра — к тому краю окна, под который он уходит. */
  .svc__scrim {
    background-image:
      linear-gradient(-90deg, transparent 0%, transparent 45%, var(--glnz-svc-fade-dark) 100%),
      linear-gradient(var(--glnz-svc-veil-dark), var(--glnz-svc-veil-dark));
  }
  .svc--even .svc__scrim {
    background-image:
      linear-gradient(90deg, transparent 0%, transparent 45%, var(--glnz-svc-fade-light) 100%),
      linear-gradient(var(--glnz-svc-veil-light), var(--glnz-svc-veil-light));
  }
}

/* ---------- Ступени кегля заголовка секции -----------------------------
   92px×--u — это 74px на заморозке 0.80. На узком экране такой кегль
   съедает первый экран секции и рвёт длинные названия. Ступени подобраны
   на взгляд от ритма страницы, ниже 1025 --u уже константа, поэтому
   значения записаны итоговыми px (см. тот же приём у hero главной). */
@media (max-width: 1024px) {
  .svc { --glnz-fs-svc-h2: 48px; }
}
@media (max-width: 767px) {
  .svc { --glnz-fs-svc-h2: 38px; }
  .svc__split { margin-top: calc(48px * var(--u)); }
}
@media (max-width: 419px) {
  .svc { --glnz-fs-svc-h2: 30px; }
}

/* ---------- Hero услуг на узких ширинах --------------------------------
   Ниже 1025 два списка встают в один столбец, нижняя полоса — в колонку.
   Резерв под .mobile-cta-bar не нужен: панели в разметке services.html
   нет (в отличие от index.html). */
@media (max-width: 1024px) {
  .svc-hero { min-height: auto; }
  /* Высота секции здесь идёт от содержимого, поэтому кадр возвращается
     в полный рост секции: фиксированные 860 и подъём — приём десктопного
     эталона, на узком экране от них остаётся только дыра снизу. */
  .svc-hero__bg { top: 0; height: 100%; }
  .svc-hero__lists {
    flex-direction: column;
    gap: 0;
    padding-top: calc(120px * var(--u));
    padding-bottom: calc(40px * var(--u));
  }
  .svc-nav { width: 100%; }
  .svc-nav--end { border-top: 0; }

  .svc-hero__bottom {
    grid-template-columns: 1fr;
    justify-items: stretch;
    row-gap: calc(24px * var(--u));
    padding-block: calc(28px * var(--u));
  }
  .svc-hero__cta { justify-self: stretch; flex-direction: column; align-items: stretch; }
  .svc-btn--primary,
  .svc-btn--ghost { justify-content: center; width: 100%; }
  .svc-hero__book { justify-self: stretch; }
  .svc-hero__book-btn { width: 100%; }
  .svc-hero__statement { justify-self: stretch; max-width: none; }
}

/* ---------- Кадр без краевой растяжки на узких ширинах ------------------
   Ниже 1025 кадр не уходит под край окна, а стоит в потоке во всю ширину —
   растягивать его край в фон незачем, остаётся только ровная вуаль
   (правила по умолчанию выше). */

/* =========================================================================
   FLOATING MESSENGER BUTTONS
   ========================================================================= */
.float-messengers {
  position: fixed;
  right: 1rem;
  bottom: calc(var(--stickybar-h) + 1rem);
  z-index: var(--z-float);
  display: flex;
  flex-direction: column;
  gap: .65rem;
}
.float-messengers a {
  width: 3rem; height: 3rem;
  border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-panel-raised);
  border: 1px solid var(--border-hairline);
  box-shadow: 0 10px 24px -12px rgba(0,0,0,.7);
  transition: transform .18s var(--ease), border-color .18s var(--ease);
}
.float-messengers a:hover { transform: translateY(-2px); border-color: var(--blue-on-dark); }
.float-messengers svg { width: 1.35rem; height: 1.35rem; }
.float-messengers .whatsapp svg { color: #3fd06b; }
.float-messengers .telegram svg { color: #4f9fe8; }

@media (min-width: 881px) {
  .float-messengers { bottom: 1.5rem; }
}

/* =========================================================================
   MOBILE STICKY CTA BAR
   ========================================================================= */
.mobile-cta-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: var(--z-stickybar);
  height: var(--stickybar-h);
  background: rgba(15,16,19,.94);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--border-hairline);
  display: flex;
  align-items: center;
  gap: .7rem;
  padding-inline: .85rem;
}
/* иконка звонка тут — тот же .glnz-icon-btn, что в шапке (тонкая рамка,
   без заливки, единый стиль); фон .bg-panel-raised убран — раньше был
   плотной заливкой, не по Pencil-стилю */
.mobile-cta-bar .mobile-cta-bar__btn {
  flex: 1;
  padding-block: calc(14px * var(--u));
  justify-content: center;
}

@media (min-width: 1025px) { .mobile-cta-bar { display: none; } }

/* =========================================================================
   COOKIE NOTICE
   ========================================================================= */
.cookie-notice {
  position: fixed;
  left: 0; right: 0; bottom: var(--stickybar-h);
  z-index: var(--z-cookie);
  background: var(--glnz-reviews-card-bg);
  border-top: 1px solid var(--glnz-reviews-border);
  padding: 1rem var(--container-pad);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .9rem 1.5rem;
  transform: translateY(100%);
  transition: transform .3s var(--ease);
}
.cookie-notice.is-visible { transform: translateY(0); }
.cookie-notice p { font-size: .85rem; color: var(--glnz-stat-value); flex: 1 1 260px; }
/* Ссылка внутри строки текста — приём тот же, что у согласия на обработку ПДн
   в форме записи (.booking__consent-label a): сплошная медь + подчёркивание,
   потому что ссылка сидит в строке и без подчёркивания не читается ссылкой. */
.cookie-notice a { color: var(--glnz-services-accent); text-decoration: underline; text-underline-offset: 2px; }
.cookie-notice__text--short { display: none; }

/* Кнопка «Принять» — контурная медная по образцу .booking__submit, не заливная:
   баннер не должен спорить с главным действием страницы. Геометрию (padding,
   размер шрифта, радиус) несут легаси-классы .btn/.btn--sm в разметке, здесь
   только цвет и жест. Класс .btn--accent из разметки снят — он давал синюю
   заливку и блик ::after из отменённой палитры. */
#cookie-accept {
  isolation: isolate;
  background-color: transparent;
  border: 1px solid var(--glnz-accent-border);
  color: var(--glnz-text-white);
  transition: border-color .45s ease;
}
#cookie-accept::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--glnz-accent);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform .45s cubic-bezier(.4, 0, .2, 1);
}
#cookie-accept:hover::before { transform: scaleX(1); }
#cookie-accept:hover { border-color: var(--glnz-accent); }
@media (prefers-reduced-motion: reduce) {
  #cookie-accept,
  #cookie-accept::before { transition: none; }
}

/* Порог согласован с mobile-cta-bar/hero (1024/1025) — раньше стоял 881,
   из-за чего в окне 881-1024 .cookie-notice уходил на bottom:0 (тот же, что
   у видимой ещё cta-bar) и накладывался на неё на все 64px (ЗАМЕРЕНО:
   cookie.bottom=800=cta.bottom, cookie.top=724.9 < cta.top=736). Ниже 1024
   компактный вид: короче текст, мельче шрифт, уже паддинги.

   БАГ (найден на реальном узком экране, не воспроизводился в замере
   getBoundingClientRect на фиксированной высоте вьюпорта): текст с
   ссылкой переносился на 2 строки, банер вырастал до ~112px, и на
   короткой высоте экрана кнопка «Принять» уходила за пределы видимой
   области — баннер было не закрыть. Раньше высота панели зависела от
   того, сколько строк займёт текст (переменная величина), а строк могло
   стать больше, чем закладывалось (запас по высоте экрана — ненадёжная
   гарантия). Фикс: текст и кнопка — ГАРАНТИРОВАННО в одну строку
   (flex-wrap:nowrap + text-overflow:ellipsis как страховка), ссылка на
   политику убрана из этого варианта текста (дублирует футер и чекбокс
   согласия в форме) — так высота панели фиксирована и не зависит от
   переноса. */
@media (max-width: 1024px) {
  .cookie-notice {
    flex-wrap: nowrap;
    justify-content: space-between;
    padding: .6rem var(--container-pad);
    gap: .6rem;
  }
  .cookie-notice p {
    font-size: .78rem;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .cookie-notice__text--full { display: none; }
  .cookie-notice__text--short { display: block; }
  .cookie-notice #cookie-accept { flex-shrink: 0; white-space: nowrap; }
}
@media (min-width: 1025px) { .cookie-notice { bottom: 0; } }

/* ---------- Scroll reveal (progressive enhancement, JS adds .is-visible) ---------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .55s var(--ease), transform .55s var(--ease);
}
[data-reveal].is-visible { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* === ПОЯВЛЕНИЕ СЕКЦИЙ ===
   Заголовки/значимые тексты секций выезжают при скролле: слева — если
   элемент в левой части страницы, справа — если в правой, снизу — если
   по центру. Скрывающие правила действуют ТОЛЬКО под html.has-js (класс
   ставит инлайн-скрипт в <head> ДО styles.css, см. index.html
   и services.html) — без JS
   или при его сбое всё видно сразу, без вспышки скрытого контента.
   Анимируются только transform/opacity. Токены длительности/easing/сдвига
   — см. :root выше (сняты с hero). */
html.has-js .reveal {
  opacity: 0;
  transition: opacity var(--glnz-reveal-duration) var(--glnz-reveal-ease),
              transform var(--glnz-reveal-duration) var(--glnz-reveal-ease);
}
html.has-js .reveal--left  { transform: translateX(calc(-1 * var(--glnz-reveal-shift-x))); }
html.has-js .reveal--right { transform: translateX(var(--glnz-reveal-shift-x)); }
html.has-js .reveal--up    { transform: translateY(var(--glnz-reveal-shift-y)); }

/* Ниже 768 — только вертикальное появление: боковой сдвиг на узких
   экранах и был единственным источником горизонтального переполнения. */
@media (max-width: 767px) {
  html.has-js .reveal--left,
  html.has-js .reveal--right {
    transform: translateY(var(--glnz-reveal-shift-y));
  }
}

html.has-js .reveal--delay-1 { transition-delay: var(--glnz-reveal-delay-step); }
html.has-js .reveal--delay-2 { transition-delay: calc(var(--glnz-reveal-delay-step) * 2); }
html.has-js .reveal--delay-3 { transition-delay: calc(var(--glnz-reveal-delay-step) * 3); }

html.has-js .reveal.is-revealed {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html.has-js .reveal,
  html.has-js .reveal--left,
  html.has-js .reveal--right,
  html.has-js .reveal--up {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* =========================================================================
   ABOUT.HTML — страница «О студии»
   Язык типографики общий со страницей услуг: заголовки Inter Tight,
   токены --glnz-fs-svc-*/--glnz-svc-*/--glnz-services-accent и классы
   .svc__eyebrow/.svc__num/.svc__tick/.svc__label/.svc__kicker/.svc__title/
   .svc__lead/.svc__body/.svc__caption/.svc__specs/.svc__spec/-key/-value/
   .svc-btn--primary/.svc-btn--ghost/.svc-btn__label переиспользованы
   напрямую в разметке about.html (см. бриф about.html — «переиспользовать
   существующие классы и токены»). Ниже — только то, чего в этом языке
   ещё не было: 7 обёрток секций и компоненты, которых на services.html нет
   (галерея, показатели, роли команды на .svc__specs — без нового CSS,
   партнёры).
   Фоны — существующие --glnz-bg / --glnz-services-bg, без новых токенов.
   Боковой гутер и вертикальный ритм верха (104px) — те же, что у .svc
   (см. блок .svc выше); низ (112 / 128–140 у CTA) — величины эталона
   about_as.html, у .svc другие (88) и не переносятся.
   ========================================================================= */

.about-intro,
.about-approach,
.about-space,
.about-numbers,
.about-team,
.about-materials,
.about-cta {
  position: relative;
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  .about-intro,
  .about-approach,
  .about-space,
  .about-numbers,
  .about-team,
  .about-materials,
  .about-cta { padding-inline: calc(110px * var(--u)); }
}

.about-intro     { background: var(--glnz-bg); padding-top: calc(104px * var(--u)); }
.about-approach  { background: var(--glnz-services-bg); padding-top: calc(104px * var(--u)); padding-bottom: calc(112px * var(--u)); }
.about-space     { background: var(--glnz-bg); padding-top: calc(104px * var(--u)); padding-bottom: calc(112px * var(--u)); }
.about-numbers   { background: var(--glnz-services-bg); padding-top: calc(104px * var(--u)); padding-bottom: calc(112px * var(--u)); }
.about-team      { background: var(--glnz-bg); padding-top: calc(104px * var(--u)); padding-bottom: calc(112px * var(--u)); }
.about-materials { background: var(--glnz-services-bg); padding-top: calc(104px * var(--u)); padding-bottom: calc(112px * var(--u)); }
.about-cta {
  background: var(--glnz-bg);
  border-top: 1px solid var(--glnz-svc-hairline);
  padding-top: calc(128px * var(--u));
  padding-bottom: calc(140px * var(--u));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(26px * var(--u));
  text-align: center;
}

/* Заголовок секции — 60px, общий для всех шести секций ниже интро. */
.about__heading {
  margin: 0;
  font-family: var(--glnz-font-tight);
  font-size: calc(60px * var(--u));
  font-weight: 700;
  /* em, не calc(px * var(--u)): на порогах 1024/767/419 --glnz-fs-about-h2
     переопределяется литеральным px (42/32/27), а --u при этом заморожен
     на полу 0.80 — трекинг в px*u переставал уменьшаться вместе с кеглем
     и на узких экранах откусывал непропорционально много (слова слипались).
     em считается от текущего font-size элемента и держит одну и ту же
     пропорцию -2.33% на любом кегле и любом пороге. */
  letter-spacing: -0.0233em;
  line-height: calc(66 / 60);
  color: var(--glnz-text-onbtn);
}
.about-approach .about__heading,
.about-space .about__heading,
.about-materials .about__heading { max-width: calc(1200px * var(--u)); }
.about-cta .about__heading { max-width: calc(1100px * var(--u)); }

.about__head { display: flex; flex-direction: column; gap: calc(24px * var(--u)); }

/* Вводный абзац приглушённого цвета (nav-link) — вводный абзац «В цифрах»
   и лид CTA, оба 17px в эталоне (CTA — 18px, разница на глаз не читается,
   заведён один токен вместо двух почти одинаковых). */
.about__lead-muted {
  margin: 0;
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-about-body-lg);
  font-weight: 400;
  line-height: calc(29 / 17);
  color: var(--glnz-nav-link);
}
.about-cta .about__lead-muted {
  font-size: var(--glnz-fs-about-cta-lead);
  line-height: calc(30 / 18);
}

/* Точечные поправки кегля/трекинга переиспользованных классов под эталон
   about_as.html — см. комментарий у токенов --glnz-fs-about-note-key и
   ниже в этом файле. Только те вхождения, где эталон даёт другую величину
   для конкретного места; сам переиспользуемый класс не меняем. */
.about-intro__note .svc__num,
.about-cta__eyebrow .svc__num {
  font-size: var(--glnz-fs-about-note-key);
  letter-spacing: calc(2px * var(--u));
}
.about-intro__caption-row .svc__caption:last-child {
  letter-spacing: calc(2px * var(--u));
}
.about-space__item .svc__caption {
  font-size: var(--glnz-fs-about-caption-lg);
  letter-spacing: calc(.4px * var(--u));
}
.about-materials__partner .svc__label {
  font-size: var(--glnz-fs-about-kind);
  letter-spacing: calc(1.6px * var(--u));
}
.about-materials__note .svc__caption {
  font-size: var(--glnz-fs-about-caption-lg);
  letter-spacing: calc(.3px * var(--u));
}
.about-cta .svc__caption {
  font-size: var(--glnz-fs-about-caption-lg);
  letter-spacing: calc(.4px * var(--u));
}
.about-numbers__stat .svc__spec-key {
  font-size: var(--glnz-fs-about-stat-key);
}
.about-team__text .svc__spec-value {
  font-size: var(--glnz-fs-about-role-value);
}

/* ---------- Интро -------------------------------------------------------- */
.about-intro__head { display: flex; flex-direction: column; gap: calc(28px * var(--u)); }
.about-intro__title { margin: 0; max-width: calc(1400px * var(--u)); }
.about-intro__lead-row {
  display: flex;
  flex-direction: column;
  gap: calc(32px * var(--u));
  padding-top: calc(14px * var(--u));
}
@media (min-width: 1025px) {
  .about-intro__lead-row { flex-direction: row; align-items: flex-start; gap: calc(160px * var(--u)); }
}
.about-intro__lead { margin: 0; max-width: calc(920px * var(--u)); flex-shrink: 0; }
.about-intro__note { display: flex; flex-direction: column; gap: calc(10px * var(--u)); max-width: calc(420px * var(--u)); }
.about-intro__note p { margin: 0; }

.about-intro__media { padding-top: calc(68px * var(--u)); display: flex; flex-direction: column; gap: calc(20px * var(--u)); }
.about-intro__photo,
.about-intro__photo img { display: block; width: 100%; }
.about-intro__photo img { aspect-ratio: 1680 / 620; height: auto; object-fit: cover; }
.about-intro__caption-row { display: flex; align-items: center; justify-content: space-between; gap: calc(16px * var(--u)); }
.about-intro__caption-row p { margin: 0; }

/* Интро — вход при загрузке страницы, не по скроллу: это первый экран,
   и .reveal/[data-reveal] здесь не сработают, пока пользователь не
   прокрутит. Те же keyframes и тайминг, что у входа нижней панели hero
   (glnz-in-left/right/up, .9s cubic-bezier(.22,1,.36,1), см. блок 5 —
   «Bottom-panel entrance» выше в этом файле), новых keyframes не заводим.
   Не через html.has-js .reveal: чистый CSS, работает и без JS/при его
   отказе — контент не должен зависеть от has-js. */
.about-intro__head .svc__eyebrow { animation: glnz-in-left  .9s cubic-bezier(.22, 1, .36, 1) 0s   both; }
.about-intro__title              { animation: glnz-in-left  .9s cubic-bezier(.22, 1, .36, 1) .15s both; }
.about-intro__lead               { animation: glnz-in-left  .9s cubic-bezier(.22, 1, .36, 1) .3s  both; }
.about-intro__note               { animation: glnz-in-right .9s cubic-bezier(.22, 1, .36, 1) .3s  both; }
.about-intro__media              { animation: glnz-in-up    .9s cubic-bezier(.22, 1, .36, 1) .45s both; }

/* ---------- 01 Подход ------------------------------------------------------ */
.about-approach__body {
  display: flex;
  flex-direction: column;
  gap: calc(48px * var(--u));
  padding-top: calc(64px * var(--u));
}
@media (min-width: 1025px) {
  .about-approach__body { flex-direction: row; align-items: flex-start; gap: calc(160px * var(--u)); }
}
.about-approach__lead { margin: 0; max-width: calc(560px * var(--u)); flex-shrink: 0; }
.about-approach__list { list-style: none; margin: 0; padding: 0; flex: 1 1 0; min-width: 0; }
.about-approach__item {
  display: flex;
  gap: calc(28px * var(--u));
  padding-block: calc(26px * var(--u));
  border-bottom: 1px solid var(--glnz-svc-hairline);
}
.about-approach__item-index {
  flex-shrink: 0;
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-about-item-index);
  font-weight: 500;
  letter-spacing: calc(1.5px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-index);
}
.about-approach__item-text { display: flex; flex-direction: column; gap: calc(10px * var(--u)); min-width: 0; }
.about-approach__item-title {
  margin: 0;
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-about-item-title);
  font-weight: 600;
  letter-spacing: calc(-0.3px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
}
.about-approach__item-desc { margin: 0; }

/* ---------- 02 Пространство ------------------------------------------------ */
.about-space__lead { margin: 0; max-width: calc(820px * var(--u)); }
.about-space__gallery {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: calc(40px * var(--u)) calc(24px * var(--u));
  padding-top: calc(64px * var(--u));
}
@media (min-width: 768px)  { .about-space__gallery { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1025px) { .about-space__gallery { grid-template-columns: repeat(3, 1fr); gap: calc(24px * var(--u)); } }
.about-space__item { display: flex; flex-direction: column; gap: calc(18px * var(--u)); min-width: 0; }
.about-space__photo,
.about-space__photo img { display: block; width: 100%; }
.about-space__photo img { aspect-ratio: 544 / 520; height: auto; object-fit: cover; }
.about-space__item-title {
  margin: 0;
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-svc-lead);
  font-weight: 600;
  letter-spacing: calc(-0.2px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
}

/* ---------- 03 В цифрах -----------------------------------------------------
   Левая колонка 600 фикс + статистика flex, gap 140 — от порога 1025,
   ниже одна колонка (тот же порог, что у .svc__split). */
.about-numbers__inner { display: flex; flex-direction: column; gap: calc(48px * var(--u)); }
@media (min-width: 1025px) {
  .about-numbers__inner {
    display: grid;
    grid-template-columns: 600fr 940fr;
    column-gap: calc(140px * var(--u));
    align-items: start;
  }
}
.about-numbers__left { display: flex; flex-direction: column; gap: calc(28px * var(--u)); }

.about-numbers__stats { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(1, 1fr); }
@media (min-width: 420px) { .about-numbers__stats { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 768px) { .about-numbers__stats { grid-template-columns: repeat(3, 1fr); } }
.about-numbers__stat {
  display: flex;
  flex-direction: column;
  gap: calc(12px * var(--u));
  padding: calc(34px * var(--u)) calc(32px * var(--u)) calc(34px * var(--u)) 0;
  border-top: 1px solid var(--glnz-svc-hairline);
}
@media (min-width: 420px) and (max-width: 767px) {
  .about-numbers__stat:not(:nth-child(2n+1)) { border-left: 1px solid var(--glnz-svc-hairline); padding-left: calc(32px * var(--u)); }
}
@media (min-width: 768px) {
  .about-numbers__stat:not(:nth-child(3n+1)) { border-left: 1px solid var(--glnz-svc-hairline); padding-left: calc(32px * var(--u)); }
}
.about-numbers__stat-value {
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-about-stat);
  font-weight: 700;
  letter-spacing: calc(-1.6px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
}

/* ---------- 04 Команда -------------------------------------------------------
   Кадр 860 фикс + текст flex, gap 120 — от порога 1025, ниже колонка.
   Роли команды — на существующих .svc__specs/.svc__spec/-key/-value,
   новый CSS не заводится (см. about.html). */
.about-team__inner { display: flex; flex-direction: column; gap: calc(48px * var(--u)); }
@media (min-width: 1025px) {
  .about-team__inner {
    display: grid;
    grid-template-columns: 860fr 700fr;
    column-gap: calc(120px * var(--u));
    align-items: start;
  }
}
.about-team__media { display: flex; flex-direction: column; gap: calc(18px * var(--u)); }
.about-team__photo,
.about-team__photo img { display: block; width: 100%; }
.about-team__photo img { aspect-ratio: 860 / 640; height: auto; object-fit: cover; }
.about-team__text { display: flex; flex-direction: column; gap: calc(32px * var(--u)); min-width: 0; }

/* ---------- 05 Материалы ------------------------------------------------- */
.about-materials__lead { margin: 0; max-width: calc(860px * var(--u)); }
.about-materials__partners {
  list-style: none;
  margin: 0;
  padding: calc(60px * var(--u)) 0 0 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 768px)  { .about-materials__partners { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1025px) { .about-materials__partners { grid-template-columns: repeat(6, 1fr); } }
.about-materials__partner {
  display: flex;
  flex-direction: column;
  gap: calc(10px * var(--u));
  padding: calc(30px * var(--u)) calc(20px * var(--u)) calc(30px * var(--u)) 0;
  border-top: 1px solid var(--glnz-svc-hairline);
}
@media (max-width: 767px) {
  .about-materials__partner:not(:nth-child(2n+1)) { border-left: 1px solid var(--glnz-svc-hairline); padding-left: calc(20px * var(--u)); }
}
@media (min-width: 768px) and (max-width: 1024px) {
  .about-materials__partner:not(:nth-child(3n+1)) { border-left: 1px solid var(--glnz-svc-hairline); padding-left: calc(20px * var(--u)); }
}
@media (min-width: 1025px) {
  .about-materials__partner:not(:nth-child(6n+1)) { border-left: 1px solid var(--glnz-svc-hairline); padding-left: calc(20px * var(--u)); }
}
.about-materials__brand {
  margin: 0;
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-about-brand);
  font-weight: 600;
  letter-spacing: calc(-0.4px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
}
.about-materials__note { padding-top: calc(28px * var(--u)); }
.about-materials__note p { margin: 0; }

/* ---------- CTA ------------------------------------------------------------- */
.about-cta__eyebrow { display: flex; align-items: center; gap: calc(14px * var(--u)); }
.about-cta__lead { max-width: calc(760px * var(--u)); }
.about-cta__buttons {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: calc(16px * var(--u));
  padding-block: calc(18px * var(--u)) calc(8px * var(--u));
}

/* ---------- Ступени кегля крупных заголовков about.html ниже 1025 ----------
   Тот же приём и та же лестница, что у .svc { --glnz-fs-svc-h2 }: --u уже
   на минимуме, дальше значения ступенями в px. */
@media (max-width: 1024px) {
  .about-intro { --glnz-fs-svc-h2: 48px; }
  .about-approach,
  .about-space,
  .about-numbers,
  .about-team,
  .about-materials,
  .about-cta { --glnz-fs-about-h2: 42px; }
  .about__heading { font-size: 42px; }
}
@media (max-width: 767px) {
  .about-intro { --glnz-fs-svc-h2: 38px; }
  .about-approach,
  .about-space,
  .about-numbers,
  .about-team,
  .about-materials,
  .about-cta { --glnz-fs-about-h2: 32px; }
  .about-numbers__stat-value { --glnz-fs-about-stat: 36px; }
  .about__heading { font-size: 32px; }
}
@media (max-width: 419px) {
  .about-intro { --glnz-fs-svc-h2: 30px; }
  .about-approach,
  .about-space,
  .about-numbers,
  .about-team,
  .about-materials,
  .about-cta { --glnz-fs-about-h2: 27px; }
  .about__heading { font-size: 27px; }
}

/* =========================================================================
   CONTACTS.HTML — страница «Контакты»
   Эталон: Pencil «Страница — Контакты», холст 1920. Язык общий с about.html:
   обёртки секций свои, а внутри переиспользованы .svc__eyebrow/.svc__num/
   .svc__tick/.svc__label/.svc__kicker/.svc__title/.svc__lead/.svc__body/
   .svc__caption, .about__head/.about__heading и весь блок CTA (.about-cta
   и его потроха) — как есть, без копирования значений.
   Боковой гутер 110 и верхний ритм 104 — те же, что у .svc и .about-*;
   низ 112 — величина эталона.
   Фон интро — декоративная Pencil-текстура, перенесена тем же приёмом,
   что фон «Как добраться»: отдельный слой .contacts-intro__bg под
   контентом, cover-crop, без растяжки 100% 100% из эталона (см.
   tools/build-contacts-images.py).
   ========================================================================= */

.contacts-intro,
.contacts-place,
.contacts-route {
  position: relative;
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  .contacts-intro,
  .contacts-place,
  .contacts-route { padding-inline: calc(110px * var(--u)); }
}

.contacts-intro {
  background: var(--glnz-bg);
  overflow: hidden;
  padding-top: calc(104px * var(--u));
  padding-bottom: calc(96px * var(--u));
}
.contacts-intro__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: image-set(
    url("../img/contacts-intro-bg.webp") type("image/webp"),
    url("../img/contacts-intro-bg.jpg") type("image/jpeg")
  );
  background-size: cover;
  background-position: center;
}
.contacts-place {
  background: var(--glnz-services-bg);
  padding-top: calc(104px * var(--u));
  padding-bottom: calc(112px * var(--u));
}
.contacts-route {
  background: var(--glnz-bg);
  overflow: hidden;
  padding-top: calc(104px * var(--u));
  padding-bottom: calc(112px * var(--u));
}

/* Ширина заголовка секции — 1200 из эталона (у about-секций свои значения
   на том же .about__heading, поэтому селектор точечный). */
.contacts-place .about__heading,
.contacts-route .about__heading { max-width: calc(1200px * var(--u)); }

/* ---------- Интро -------------------------------------------------------- */
.contacts-intro__head { position: relative; z-index: 1; display: flex; flex-direction: column; gap: calc(24px * var(--u)); }
.contacts-intro__title { margin: 0; max-width: calc(1400px * var(--u)); }
.contacts-intro__lead  { margin: 0; max-width: calc(900px * var(--u)); }

/* Вход при загрузке страницы, не по скроллу — как у .about-intro:
   первый экран, .reveal здесь не сработает. Те же keyframes и тайминг. */
.contacts-intro__head .svc__eyebrow { animation: glnz-in-left .9s cubic-bezier(.22, 1, .36, 1) 0s   both; }
.contacts-intro__title              { animation: glnz-in-left .9s cubic-bezier(.22, 1, .36, 1) .15s both; }
.contacts-intro__lead               { animation: glnz-in-left .9s cubic-bezier(.22, 1, .36, 1) .3s  both; }

/* ---------- 01 Контакты и карта -------------------------------------------
   Эталон: Split — колонка контактов 520 фикс + карта flex, gap 120,
   отступ сверху 64. Ниже 1025 (тот же порог, что у .svc__split и
   .about-numbers__inner) — одна колонка, контакты первыми: в разметке
   они и стоят первыми, переставлять порядок не требуется. */
.contacts-place__split {
  display: flex;
  flex-direction: column;
  gap: calc(48px * var(--u));
  padding-top: calc(64px * var(--u));
}
@media (min-width: 1025px) {
  .contacts-place__split { flex-direction: row; align-items: flex-start; gap: var(--glnz-cts-gap); }
  .contacts-place__list  { width: var(--glnz-cts-list-w); flex-shrink: 0; }
  .contacts-place__map-col { flex: 1 1 0; min-width: 0; }
}

.contacts-place__list { list-style: none; margin: 0; padding: 0; }
.contacts-place__row {
  display: flex;
  align-items: center;
  gap: calc(22px * var(--u));
  padding-block: calc(28px * var(--u));
  border-bottom: 1px solid var(--glnz-svc-hairline);
}
/* Квадрат иконки — тот же элемент языка, что .why-item__icon и иконка
   строки контактов на главной: рамка приглушённой медью, значок сплошной. */
.contacts-place__icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--glnz-cts-icon);
  height: var(--glnz-cts-icon);
  border: 1px solid var(--glnz-svc-tick);
  border-radius: var(--radius-md);
}
.contacts-place__icon svg {
  width: calc(20px * var(--u));
  height: calc(20px * var(--u));
  color: var(--glnz-services-accent);
}
.contacts-place__cell { display: flex; flex-direction: column; gap: calc(9px * var(--u)); min-width: 0; }
.contacts-place__key {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-about-note-key);
  font-weight: 500;
  letter-spacing: calc(2px * var(--u));
  line-height: normal;
  color: var(--glnz-cts-key);
}
.contacts-place__value {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-lead);
  font-weight: 500;
  line-height: normal;
  color: var(--glnz-text-onbtn);
}
.contacts-place__value--link { text-decoration: none; }

/* Мессенджеры — последний блок списка: без нижней черты, в колонку. */
.contacts-place__row--msgs {
  flex-direction: column;
  align-items: flex-start;
  gap: calc(16px * var(--u));
  padding-block: calc(30px * var(--u)) 0;
  border-bottom: 0;
}
.contacts-place__msgs { display: flex; flex-wrap: wrap; gap: calc(12px * var(--u)); }
.contacts-place__msg {
  display: flex;
  align-items: center;
  gap: calc(10px * var(--u));
  padding: calc(15px * var(--u)) calc(20px * var(--u));
  border: 1px solid var(--glnz-svc-tick);
  border-radius: var(--radius-md);
  text-decoration: none;
}
.contacts-place__msg svg {
  flex-shrink: 0;
  width: calc(18px * var(--u));
  height: calc(18px * var(--u));
  color: var(--glnz-services-accent);
}
.contacts-place__msg-label {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-cts-btn);
  font-weight: 500;
  letter-spacing: calc(.3px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-lead);
  white-space: nowrap;
}

/* ---------- Карта ---------------------------------------------------------
   Бокс держит кадр-заглушку; настоящий виджет Яндекса скрипт кладёт
   в .contacts-map__slot (js/main.js). Заглушка, слот и бейдж — три
   самостоятельных слоя внутри .contacts-map (не background на самом
   боксе): все три должны пережить подмену содержимого слота и уметь
   гаснуть/проявляться каждый своим переходом.
   z-index здесь локальный, внутри компонента (как слои hero, см. CLAUDE.md):
   0 — заглушка, 1 — слот с виджетом (внутри него ссылки атрибуции Яндекса
   на своём инлайновом z-index:1 — с заглушкой не конфликтует, они в разных
   стековых контекстах), 2 — бейдж. pointer-events: none и на заглушке,
   и на бейдже — оба декоративны и не должны перехватывать колесо/жесты
   карты.
   Переход — кроссфейд заглушки в карту, оба слоя гасят/проявляют СВОЙ
   opacity одновременно, классом .is-live: заглушка 1→0, слот 0→1, бейдж
   1→0 (последний — частью того же перехода, не отдельным шагом). Раньше
   заглушка сидела как background-image на самом .contacts-map, а не своим
   слоем — переход был навешен только на слот, и хотя формально это тоже
   должно было крестфейдить (alpha-blend слота поверх фона), понадёжнее
   развести на два явно анимируемых слоя, а не полагаться на то, как
   браузер скомпонует непрозрачность поверх чужого фона с живым iframe
   внутри.
   Класс .is-live ставится НЕ в том кадре, что вставка разметки в слот
   (см. main.js) — иначе браузер схлопывает начальное и конечное состояние
   в одно вычисление, и transition не проигрывается вовсе (та же причина,
   что чинили в reveal.js для элементов первого экрана).
   Длительность — --glnz-cts-map-fade, одна точка правки на все три слоя
   (заглушка/слот/бейдж должны идти строго синхронно). .6s — черновое
   значение, калибруется в DevTools при приёмке. */
.contacts-place__map-col { display: flex; flex-direction: column; gap: calc(18px * var(--u)); }
.contacts-map {
  --glnz-cts-map-fade: .6s; /* длительность кроссфейда заглушка↔карта, см. комментарий выше */
  position: relative;
  height: var(--glnz-cts-map-h);
  border-radius: var(--radius-md);
  overflow: hidden;
  background-color: var(--glnz-bg);
}
.contacts-map__placeholder {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: image-set(
    url("../img/contacts-map-placeholder.webp") type("image/webp"),
    url("../img/contacts-map-placeholder.jpg") type("image/jpeg")
  );
  background-size: cover;
  background-position: center;
  transition: opacity var(--glnz-cts-map-fade) var(--ease);
}
.contacts-map.is-live .contacts-map__placeholder { opacity: 0; }
.contacts-map__slot {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0;
  transition: opacity var(--glnz-cts-map-fade) var(--ease);
}
.contacts-map__slot iframe { display: block; border: 0; }
.contacts-map.is-live .contacts-map__slot { opacity: 1; }
.contacts-map__pin {
  position: absolute;
  z-index: 2;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: calc(10px * var(--u));
  padding: calc(13px * var(--u)) calc(20px * var(--u));
  border: 1px solid var(--glnz-services-accent);
  border-radius: 100px;
  background: var(--glnz-cts-pin-bg);
  pointer-events: none;
  transition: opacity var(--glnz-cts-map-fade) var(--ease);
}
.contacts-map.is-live .contacts-map__pin { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .contacts-map__placeholder,
  .contacts-map__slot,
  .contacts-map__pin { transition: none; }
}
.contacts-map__pin svg {
  flex-shrink: 0;
  width: calc(16px * var(--u));
  height: calc(16px * var(--u));
  color: var(--glnz-services-accent);
}
.contacts-map__pin-label {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-cts-btn);
  font-weight: 500;
  letter-spacing: calc(.3px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
  white-space: nowrap;
}
/* Подпись под боксом: цвет в эталоне медный 50%, а не серый .svc__caption.
   padding-inline: 0 — гасит гутер, который .svc__caption получает от
   раскладки секций услуг (там подпись стоит под кадром, уходящим под край
   окна; здесь бокс стоит в потоке). */
.contacts-map__caption {
  padding-inline: 0;
  letter-spacing: calc(.6px * var(--u));
  color: var(--glnz-cts-caption);
}

/* ---------- 02 Как добраться ---------------------------------------------
   Фон — отдельный слой под контентом (приём .svc__bg / .process__bg),
   cover + center. В эталоне кадр растянут (background-size: 100% 100%),
   здесь — cover: пропорции кадра не искажаются. */
.contacts-route__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: image-set(
    url("../img/contacts-route-bg-1280.webp") type("image/webp"),
    url("../img/contacts-route-bg.jpg") type("image/jpeg")
  );
  background-size: cover;
  background-position: center;
}
@media (min-width: 1025px) {
  .contacts-route__bg {
    background-image: image-set(
      url("../img/contacts-route-bg-1920.webp") type("image/webp"),
      url("../img/contacts-route-bg.jpg") type("image/jpeg")
    );
  }
}
.contacts-route__inner { position: relative; z-index: 1; }

.contacts-route__ways {
  list-style: none;
  margin: 0;
  padding: calc(64px * var(--u)) 0 0 0;
  display: grid;
  grid-template-columns: 1fr;
}
@media (min-width: 1025px) {
  .contacts-route__ways { grid-template-columns: repeat(3, 1fr); }
}
.contacts-route__way {
  display: flex;
  flex-direction: column;
  gap: calc(14px * var(--u));
  padding: calc(34px * var(--u)) calc(40px * var(--u)) calc(34px * var(--u)) 0;
  border-top: 1px solid var(--glnz-svc-hairline);
}
@media (min-width: 1025px) {
  .contacts-route__way:not(:first-child) {
    border-left: 1px solid var(--glnz-svc-hairline);
    padding-left: calc(40px * var(--u));
  }
}
.contacts-route__index {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-about-item-index);
  font-weight: 500;
  letter-spacing: calc(1.5px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-index);
}
.contacts-route__title {
  margin: 0;
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-about-item-title);
  font-weight: 600;
  letter-spacing: calc(-.3px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
}
.contacts-route__desc { margin: 0; }
.contacts-route__meta {
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-about-kind);
  font-weight: 500;
  letter-spacing: calc(1.6px * var(--u));
  line-height: normal;
  color: var(--glnz-cts-key);
}

/* Адрес под кнопками CTA — тот же гутер .svc__caption, что и у подписи
   карты выше: в центрированной колонке CTA он сдвигал строку вправо.
   Правило общее с about.html — компонент .about-cta один на две страницы. */
.about-cta .svc__caption { padding-inline: 0; }

/* ---------- Ступени ниже 1025 ---------------------------------------------
   Кегли крупных заголовков едут по общей лестнице (.svc { --glnz-fs-svc-h2 }
   для h1 интро и .about__heading для заголовков секций), здесь — только
   высота бокса карты: --u ниже 1536 заморожен, поэтому значения в px. */
@media (max-width: 1024px) {
  .contacts-intro { --glnz-fs-svc-h2: 48px; }
  .contacts-place,
  .contacts-route { --glnz-fs-about-h2: 42px; }
  .contacts-place .about__heading,
  .contacts-route .about__heading { font-size: 42px; }
  .contacts-map { --glnz-cts-map-h: 460px; }
}
@media (max-width: 767px) {
  .contacts-intro { --glnz-fs-svc-h2: 38px; }
  .contacts-place,
  .contacts-route { --glnz-fs-about-h2: 32px; }
  .contacts-place .about__heading,
  .contacts-route .about__heading { font-size: 32px; }
  .contacts-map { --glnz-cts-map-h: 360px; }
  .contacts-route__way { padding-right: 0; }
}
@media (max-width: 419px) {
  .contacts-intro { --glnz-fs-svc-h2: 30px; }
  .contacts-place,
  .contacts-route { --glnz-fs-about-h2: 27px; }
  .contacts-place .about__heading,
  .contacts-route .about__heading { font-size: 27px; }
  .contacts-map { --glnz-cts-map-h: 280px; }
  .contacts-place__msg { flex: 1 1 auto; justify-content: center; }
}

/* =========================================================================
   POLICY.HTML — «Политика конфиденциальности»
   Эталона в Pencil для страницы нет: собрана по образцу about.html
   и contacts.html. Ничего собственного в типографике не заводится —
   переиспользованы .svc__eyebrow/.svc__tick/.svc__label/.svc__kicker/
   .svc__title/.svc__lead/.svc__body/.svc__caption и весь блок CTA
   (.about-cta с потрохами). Ниже — только обёртки секций и компоненты
   длинного текста, которых в языке ещё не было.
   Кегли заголовков документа взяты существующими ступенями Inter Tight,
   новых токенов под них не вводится: h2 раздела — --glnz-fs-about-item-title
   (21, как заголовок принципа в «Подходе» и способа в «Как добраться»),
   h3 подраздела — --glnz-fs-about-role-value (18, как значение роли
   в «Команде»). Абзацы — .svc__body как есть.
   Боковой гутер 110 и верхний ритм 104 — те же, что у секций .svc,
   .about- и .contacts- (звёздочку в комментарии не пишем: пара
   «звёздочка+слэш» закрывает комментарий досрочно и съедает
   следующее за ним правило).
   ========================================================================= */

.policy-intro,
.policy-doc {
  position: relative;
  padding-inline: var(--container-pad);
}
@media (min-width: 1025px) {
  .policy-intro,
  .policy-doc { padding-inline: calc(110px * var(--u)); }
}

/* ---------- Интро ---------------------------------------------------------
   Полная копия приёма .contacts-intro: та же декоративная текстура
   отдельным слоем под контентом (общий файл img/contacts-intro-bg.*,
   своего кадра у страницы нет), cover-crop, тот же ритм и та же
   анимация входа при загрузке. */
.policy-intro {
  background: var(--glnz-bg);
  overflow: hidden;
  padding-top: calc(104px * var(--u));
  /* Низ 0, а не 96 как у .contacts-intro: воздух под лидом даёт верхний
     ритм следующей секции (.policy-doc, 104) — ровно так же устроен стык
     интро и «01 Подход» на about.html, где .about-intro тоже без нижнего
     отступа. Сумма 96+104=200 читалась экраном пустоты: на contacts.html
     её держит крупный заголовок секции (60), а здесь первый раздел
     открывается мелким 21 и подпереть двести пикселей ему нечем. */
  padding-bottom: 0;
}
.policy-intro__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: image-set(
    url("../img/contacts-intro-bg.webp") type("image/webp"),
    url("../img/contacts-intro-bg.jpg") type("image/jpeg")
  );
  background-size: cover;
  background-position: center;
}
.policy-intro__head { position: relative; z-index: 1; display: flex; flex-direction: column; gap: calc(24px * var(--u)); }
.policy-intro__title { margin: 0; max-width: calc(1400px * var(--u)); }
.policy-intro__lead  { margin: 0; max-width: calc(900px * var(--u)); }

/* Вход при загрузке страницы, не по скроллу — как у .about-intro
   и .contacts-intro: первый экран, .reveal здесь не сработает.
   Те же keyframes и тайминг, новых не заводим. */
.policy-intro__head .svc__eyebrow { animation: glnz-in-left .9s cubic-bezier(.22, 1, .36, 1) 0s   both; }
.policy-intro__title              { animation: glnz-in-left .9s cubic-bezier(.22, 1, .36, 1) .15s both; }
.policy-intro__lead               { animation: glnz-in-left .9s cubic-bezier(.22, 1, .36, 1) .3s  both; }

/* ---------- Тело документа ------------------------------------------------
   Читаемая колонка ограниченной ширины — 900, та же величина, что держит
   лид интро (.contacts-intro__lead / .policy-intro__lead): строка длинного
   текста не должна быть шире вводного абзаца страницы.
   Раздел = линия-отбивка сверху + индекс + заголовок + текст: тот же приём
   и те же отступы, что у .contacts-route__way (34 по вертикали, 14 между
   строками блока). */
.policy-doc {
  /* Единая точка калибровки кегля документа. По умолчанию — ровно тот же
     .svc__body, что и на всех остальных страницах: своей величины страница
     не вводит. Но здесь этот кегль держит не пару абзацев внутри карточки,
     а весь текст страницы, поэтому переопределение вынесено в одну
     переменную — менять при приёмке тут, а не в трёх правилах. */
  --glnz-policy-fs-body: var(--glnz-fs-svc-body);
  background: var(--glnz-services-bg);
  padding-top: calc(104px * var(--u));
  padding-bottom: calc(112px * var(--u));
}
.policy-doc .svc__body,
.policy-doc__list { font-size: var(--glnz-policy-fs-body); }
.policy-doc__col { max-width: calc(900px * var(--u)); }

.policy-doc__section {
  display: flex;
  flex-direction: column;
  gap: calc(14px * var(--u));
  padding-block: calc(34px * var(--u));
  border-top: 1px solid var(--glnz-svc-hairline);
}
.policy-doc__section:first-child { border-top: 0; padding-top: 0; }
.policy-doc__section:last-child { padding-bottom: 0; }

/* Индекс и заголовок раздела стоят в строку: короткий номер слева, как
   у .svc__eyebrow (тот же gap 14). */
.policy-doc__head {
  display: flex;
  align-items: baseline;
  gap: calc(14px * var(--u));
  margin: 0;
}
.policy-doc__index {
  flex-shrink: 0;
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-about-item-index);
  font-weight: 500;
  letter-spacing: calc(1.5px * var(--u));
  line-height: normal;
  color: var(--glnz-svc-index);
}
.policy-doc__title {
  margin: 0;
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-about-item-title);
  font-weight: 600;
  letter-spacing: calc(-.3px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
}
/* Подзаголовок внутри раздела — ступень ниже заголовка раздела. Отбит
   сверху чуть больше обычного межстрочного зазора блока (14): иначе
   визуально прилипает к предыдущему абзацу и перестаёт читаться как
   новый уровень. */
.policy-doc__subtitle {
  margin: calc(10px * var(--u)) 0 0 0;
  font-family: var(--glnz-font-tight);
  font-size: var(--glnz-fs-about-role-value);
  font-weight: 600;
  letter-spacing: calc(-.2px * var(--u));
  line-height: normal;
  color: var(--glnz-text-onbtn);
}

/* Списки — маркер тем же приглушённым цветом, что и сам текст (.svc__body,
   --glnz-nav-link): медный маркер спорил бы с индексами разделов. */
.policy-doc__list {
  margin: 0;
  padding-left: calc(20px * var(--u));
  list-style: disc;
  display: flex;
  flex-direction: column;
  gap: calc(10px * var(--u));
  font-family: var(--glnz-font-body);
  font-size: var(--glnz-fs-svc-body);
  font-weight: 400;
  line-height: calc(26 / 15);
  color: var(--glnz-nav-link);
}
.policy-doc__list::marker { color: var(--glnz-nav-link); }

/* Ссылка в потоке текста — сплошная медь, тот же цвет, что у «→ подробнее»
   и активных элементов страницы услуг. */
.policy-doc__link {
  color: var(--glnz-services-accent);
  text-decoration: none;
}

/* Служебная оговорка про демо-статус проекта и строка даты редакции —
   приглушены до цвета подписей (.svc__caption), чтобы не спорить
   с основным текстом документа. */
.policy-doc__aside,
.policy-doc__updated { color: var(--glnz-svc-label); }

/* ---------- Ступени ниже 1025 ---------------------------------------------
   Кегль h1 интро едет по той же лестнице, что на about/contacts
   (--glnz-fs-svc-h2 литералом: --u ниже 1536 заморожен на полу).
   Заголовки разделов документа (21/18) на этой лестнице не участвуют —
   они и на 1920 близки к минимуму читаемости, уменьшать нечего. */
@media (max-width: 1024px) {
  .policy-intro { --glnz-fs-svc-h2: 48px; }
}
@media (max-width: 767px) {
  .policy-intro { --glnz-fs-svc-h2: 38px; }
}
@media (max-width: 419px) {
  .policy-intro { --glnz-fs-svc-h2: 30px; }
}
