/* ==========================================================================
   ZAFFIRO CLINIC - слой точного повторения текущего дизайна с Tilda.
   Все значения сняты замерами с живого zaffiroclinic.ru на 1440px
   (harvest/tilda-map.json), а не подобраны на глаз.

   Десктоп: один в один.
   Мобайл: та же композиция и порядок блоков, но читаемые кегли - на Тильде
   мобильная версия ужимается пропорционально до 10px в кнопках и 8px
   в надзаголовке, это нечитаемо и ломает главный сценарий.
   ========================================================================== */

:root {
  --tl-container: 1200px;      /* с padding 20px даёт контент ровно x=140..1300, как в оригинале */
  --tl-gap: 20px;              /* шаг сетки 295 при плитке 275 */
  --tl-ink: #222222;
  --tl-white: #ffffff;
}

.tl { width: 100%; max-width: var(--tl-container); margin-inline: auto; padding-inline: 20px; }

/* --- Заголовок секции: Tenor Sans 30px, капс, слева, #222 --- */
.tl-head {
  font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
  font-size: clamp(22px, 2.1vw, 30px); line-height: 1.28; color: var(--tl-ink);
  letter-spacing: .02em;            /* капс Tenor Sans без трекинга слипается */
  margin-bottom: clamp(20px, 2.4vw, 34px);
  /* Неразрывные пробелы склеивают слова в длинные связки («НЕ ВЫБИРАЙТЕ»), и на 320 px
     такая связка не помещалась в плашку формы - страница уезжала вбок на 36 px.
     break-word рвёт только то, что целиком не влезает, обычные строки не трогает.
     То же правило ниже - для остальных крупных наборов (цитаты, имена, слоганы). */
  overflow-wrap: break-word;
  text-wrap: balance;               /* заголовок не оставляет одинокое слово на строке */
  /* max-width тут был в ch: единица считает по ширине цифры «0», а не прописной кириллицы,
     и 22ch давали всего 394 px - «ИНЪЕКЦИОННАЯ КОСМЕТОЛОГИЯ» (нужно 590 px) рвалось надвое.
     Ширину не ограничиваем вовсе: balance сам держит строки ровными, как на оригинале. */
}
/* Страница белая, полосы фона убраны - срез на границе двух белых полос был бы невидим
   (замер показал ровно такой случай у «о клинике»). Разделяет секции воздух, а не цвет,
   поэтому он одинаковый у всех: 88 px сверху и снизу на десктопе. */
.tl-sec { padding-block: clamp(40px, 4.6vw, 66px); }
/* Замер показал зазор 183 px между последней строкой акций и заголовком «Добро пожаловать» -
   два отступа по 88 подряд. Ритм ужат до 66: зазор становится 139 px, блоки читаются
   как соседние, а не как разные страницы. */
/* Фирменная деталь Тильды: крупный скруглённый угол на стыке секций.
   Отступ сверху не меньше радиуса, иначе заголовок попадает в вырез. */
.tl-sec--curve { border-radius: 300px 0 0 0; padding-top: clamp(90px, 12vw, 170px); position: relative; margin-top: -1px; }
.tl-sec--curve-r { border-radius: 0 300px 0 0; padding-top: clamp(90px, 12vw, 170px); position: relative; margin-top: -1px; }

/* ============================ ГЕРОЙ ============================ */
.tl-hero { position: relative; min-height: clamp(560px, 55vw, 800px); display: flex; align-items: flex-end; overflow: hidden;
           padding-bottom: clamp(28px, 4vw, 56px);
           /* фирменный срез снизу справа - подпись бренда на первом экране */
           border-radius: 0 0 clamp(120px, 20vw, 300px) 0; }
.tl-hero__bg { position: absolute; inset: 0; }
/* Плагин картинок оборачивает img в <picture>. Без явных размеров у обёртки
   height:100% у img считается от неё, а не от героя - снимок не растягивается
   и снизу остаётся серая плашка. */
.tl-hero__bg, .tl-hero__bg picture { display: block; width: 100%; height: 100%; }
.tl-hero__bg img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; }
.tl-hero__bg::after {
  content: ""; position: absolute; inset: 0;
  /* Команда снята на светлом фоне в белом - белый текст читается только по плотной
     подложке снизу. Горизонтальная составляющая держит левый край. */
  background:
    linear-gradient(to top, rgba(20,17,14,.88) 0%, rgba(20,17,14,.62) 26%, rgba(20,17,14,.16) 52%, rgba(20,17,14,0) 74%),
    linear-gradient(90deg, rgba(20,17,14,.42) 0%, rgba(20,17,14,.16) 46%, rgba(20,17,14,0) 78%);
}
.tl-hero__body { position: relative; z-index: 2; color: #fff; }
.tl-hero__body > * { max-width: 700px; }   /* ограничиваем строку, а не сдвигаем весь блок */
/* h1 героя - только обёртка: размеры и вид задают классы внутри (надстрочник и две
   строки слогана). Собственные отступы и кегль заголовка снимаем, иначе включение
   надстрочника в h1 сдвинуло бы первый экран. */
.tl-hero__h1 { margin: 0; font: inherit; letter-spacing: inherit; }
.tl-hero__eyebrow {
  font-family: var(--font-display); font-size: clamp(13px, 1.4vw, 16px); letter-spacing: .12em;
  text-transform: uppercase; color: rgba(255,255,255,.9); display: block;
}
.tl-hero__t1 {
  display: block;
  font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
  font-size: clamp(20px, 1.95vw, 28px); line-height: 1.25; margin-top: 10px;
}
.tl-hero__t2 {
  display: block;
  font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
  font-size: clamp(26px, 2.8vw, 40px); line-height: 1.16; letter-spacing: .015em;
  text-wrap: balance;
}
.tl-hero__sub {
  font-family: var(--font-body); font-weight: 500; text-transform: uppercase;
  font-size: clamp(16px, 1.5vw, 22px); line-height: 1.45; letter-spacing: .04em; margin-top: 16px; max-width: 520px;
  color: rgba(255,255,255,.96);
}
.tl-hero__btns { display: flex; gap: 16px; margin-top: clamp(20px, 2.6vw, 36px); flex-wrap: wrap; }

/* --- Кнопки как на Тильде: пилюля, Montserrat 18/600 --- */
.tl-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px; padding: 14px 30px; border-radius: 999px;
  border: 1.5px solid transparent;   /* резерв под обводку: иначе залитая и обводочная разной высоты */
  font-family: var(--font-body); font-weight: 600; font-size: clamp(14px, 1.25vw, 18px);
  transition: background .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.tl-btn--white { background: #fff; color: var(--tl-ink); }
.tl-btn--ghost { border-color: var(--gold); color: #fff; }
.tl-btn--dark { background: var(--graphite); color: #fff; }
.tl-btn--outline { border-color: var(--line-strong); color: var(--tl-ink); background: #fff; }
@media (hover: hover) and (pointer: fine) {
  .tl-btn--white:hover { background: var(--sand); }
  .tl-btn--ghost:hover { background: rgba(176,147,110,.22); border-color: var(--gold); }
  .tl-btn--dark:hover { background: var(--graphite-deep); }
  .tl-btn--outline:hover { border-color: var(--gold); }
}

/* ============================ КАРУСЕЛИ ============================
   На Тильде акции, специалисты и популярные - слайдеры. Сохраняем. */
.tl-rail { display: flex; gap: var(--tl-gap); overflow-x: auto; scroll-snap-type: x mandatory;
           scrollbar-width: none; padding-bottom: 6px; }
.tl-rail::-webkit-scrollbar { display: none; }
.tl-rail > * { flex: 0 0 auto; scroll-snap-align: start; }
.tl-rail--3 > * { width: min(84vw, 373px); }   /* шаг 392 = 373 + 20 */
.tl-rail--4 > * { width: min(72vw, 275px); }   /* шаг 295 = 275 + 20 */
/* Если карточек ровно на ряд - раскладываем сеткой, а не оставляем ленту,
   вылезающую на несколько пикселей. Карусель включается сама, когда карточек больше. */
.is-static .tl-rail { display: grid; overflow: visible; }
.is-static .tl-rail > * { width: 100%; }   /* иначе карточка ужимается по содержимому */
.is-static .tl-rail--3 { grid-template-columns: repeat(3, 1fr); }
.is-static .tl-rail--4 { grid-template-columns: repeat(4, 1fr); }
.is-static .tl-nav { display: none; }
@media (max-width: 900px) {
  .is-static .tl-rail--3, .is-static .tl-rail--4 { grid-template-columns: 1fr 1fr; }
}
.tl-nav { display: flex; gap: 10px; justify-content: center; margin-top: 22px; }
.tl-nav button {
  width: 48px; height: 48px; border-radius: 999px; border: 1px solid var(--gold);
  color: var(--gold-deep); background: transparent; display: grid; place-items: center; font-size: 20px;
}
@media (hover: hover) { .tl-nav button:hover:not(:disabled) { background: var(--gold); color: #fff; } }
/* disabled у стрелок - общий канон в styles.css (.tl-btn/button:disabled), дубль снят */
.tl-nav button:active:not(:disabled) { transform: scale(.94); }
/* Видимый фокус с клавиатуры - обязателен, а не опционален */
.tl-rail:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 6px; border-radius: 8px; }
.tl-btn:focus-visible, .tl-tile:focus-visible, .tl-doc:focus-visible,
.tl-nav button:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 3px; }
.tl-hero .tl-btn:focus-visible, .tl-tile:focus-visible, .tl-doc:focus-visible {
  outline: 2px solid #fff; outline-offset: 2px; box-shadow: 0 0 0 4px rgba(24,21,18,.75);
}
.tl-btn--dark:active, .tl-btn--white:active, .tl-btn--outline:active { transform: translateY(1px); }
/* Карточки-ссылки: сдержанный отклик, только на настоящем указателе */
@media (hover: hover) and (pointer: fine) {
  .tl-promo, .tl-pop { transition: box-shadow .3s var(--ease), transform .3s var(--ease); }
  .tl-promo:hover, .tl-pop:hover { box-shadow: 0 18px 44px rgba(42,38,34,.12); transform: translateY(-2px); }
  .tl-doc img { transition: transform .6s var(--ease); }
  .tl-doc:hover img { transform: scale(1.03); }
}

/* --- Карточка акции --- */
.tl-promo { background: var(--sand); border-radius: 20px 100px 20px 20px; overflow: hidden;
            display: flex; flex-direction: column; }
.tl-promo__img { aspect-ratio: 16 / 9; overflow: hidden; background: var(--taupe); }
.tl-promo__img img { width: 100%; height: 100%; object-fit: cover; }
.tl-promo__body { padding: 22px; display: flex; flex-direction: column; gap: 12px; flex: 1; }
.tl-promo__t { font-family: var(--font-display); font-weight: 400; font-size: clamp(17px, 1.5vw, 20px);
               line-height: 1.3; color: var(--tl-ink); text-wrap: balance; }
.tl-promo__d { font-family: var(--font-body); font-size: 14px; line-height: 1.55; color: var(--ink-soft);
               text-wrap: pretty; overflow-wrap: break-word; }
.tl-promo__p { font-family: var(--font-body); font-size: 16px; color: var(--tl-ink);
               font-variant-numeric: tabular-nums; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.tl-promo__p s { color: var(--ink-faint); }  /* старая цена - декоративная, ей норма контраста не нужна */
.tl-promo__p b { font-size: 19px; }
.tl-promo .tl-btn { margin-top: auto; align-self: flex-start; }

/* --- О клинике и цифры --- */
/* Фото и текст выровнены по обеим кромкам: stretch тянет снимок на высоту колонки текста.
   Замер до правки: верх совпадал, а низ расходился на 106 px - фото 418, текст 524. */
.tl-about { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 3vw, 56px); align-items: stretch; }
/* Рамка как на оригинале: за снимком лежит фигура на 2 px больше с золотым градиентом,
   у неё радиус 20/100/20/20, у самого снимка - 18/98/18/18. Значения и цвета сняты
   из стилей живого сайта (#c49b68 -> #f8d5af -> #c49b68, наклон 0.417turn). */
.tl-about__media { order: -1; padding: 2px; border-radius: 20px 100px 20px 20px;
  background: linear-gradient(0.417turn, #c49b68 0%, #f8d5af 51%, #c49b68 100%); }
.tl-about__media img { border-radius: 18px 98px 18px 18px; }
@media (max-width: 640px) {
  /* на узком экране оригинал скругляет угол мягче */
  .tl-about__media { border-radius: 20px 50px 20px 20px; }
  .tl-about__media img { border-radius: 18px 48px 18px 18px; }
}
/* На узком экране блок складывается в колонку, и тянуть снимок не по чему -
   возвращаем ему собственную пропорцию. */
@media (max-width: 860px) { .tl-about__media { aspect-ratio: 4/3; } }
.tl-about__media img { width: 100%; height: 100%; object-fit: cover; }
.tl-about h2 { font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
               font-size: clamp(20px, 2.1vw, 30px); line-height: 1.3; color: var(--tl-ink);
               letter-spacing: .02em; text-wrap: balance; }
.tl-about p { font-family: var(--font-body); font-size: 16px; line-height: 1.65; color: var(--ink-soft);
             margin-top: 16px; max-width: 62ch; text-wrap: pretty; }
.tl-stats { display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--tl-gap); margin-top: clamp(28px, 3.4vw, 48px); }
.tl-stats > :nth-child(1), .tl-stats > :nth-child(2) { grid-column: span 3; }
.tl-stats > :nth-child(3), .tl-stats > :nth-child(4), .tl-stats > :nth-child(5) { grid-column: span 2; }
.tl-stat { background: var(--sand); border-radius: 20px; padding: 26px 18px; text-align: center; min-width: 0; }
.tl-stat b { display: block; font-family: var(--font-display); font-weight: 400; /* у Tenor Sans нет
             жирного: на <b> браузер синтезировал фальшивый жир и мазал контур */
             font-size: clamp(28px, 3vw, 44px);
             line-height: 1; color: var(--gold-deep); text-shadow: none;
             font-variant-numeric: tabular-nums; letter-spacing: .01em; }
.tl-stat span { display: block; margin-top: 10px; font-family: var(--font-display); font-size: 16px;
                line-height: 1.4; color: var(--tl-ink); text-wrap: balance; }

/* --- Карточка врача: фото, поверх низа - имя и должность --- */
.tl-doc { position: relative; display: block; border-radius: 20px; overflow: hidden; aspect-ratio: 3/4; }
.tl-doc img { width: 100%; height: 100%; object-fit: cover; object-position: center 18%; }
/* Замер на iPhone 13: белая подпись на светлом кадре давала контраст 3,3:1 при норме
   4,5 - на солнце имя врача читалось с трудом. Усилили середину градиента, верх кадра
   остался открытым. */
.tl-doc::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20,17,14,.92) 0%, rgba(20,17,14,.70) 42%, rgba(20,17,14,0) 78%); }
.tl-doc__cap { position: absolute; left: 20px; right: 20px; bottom: 18px; z-index: 2; color: #fff; }
/* ФИО отдельной строкой, СПЕЦИАЛЬНОСТЬ под ним (как на бою). Оба span - блочные:
   инлайновыми они склеивались в одну строку, и отступ margin-top не работал. */
.tl-doc__n { display: block; font-family: var(--font-display); font-size: clamp(16px, 1.4vw, 19px);
             text-transform: uppercase; line-height: 1.25; letter-spacing: .03em; text-wrap: balance; }
.tl-doc__r { display: block; font-family: var(--font-body); font-size: 14px; font-weight: 500; line-height: 1.4;
             margin-top: 6px; color: rgba(255,255,255,.88); }
/* Карточка врача в карусели: под фото - кнопка записи (на бою она у каждого врача) */
.tl-docc { display: flex; flex-direction: column; gap: 14px; }
.tl-docc .tl-doc { flex: 1 1 auto; }
.tl-docc__cta { align-self: stretch; text-align: center; }

/* --- Плитка услуг: 4 колонки, подпись Tenor 16 капсом поверх фото --- */
/* Плагин картинок оборачивает каждый <img> в <picture>. У обёртки высота auto, поэтому
   height:100% у картинки считается от неё, схлопывается - и object-fit:cover не включается:
   кадры рисовались в натуральной пропорции, оставляя серые дыры до 226 px. Даём обёртке размеры. */
.tl-tile > picture, .tl-doc > picture, .tl-pop__img > picture, .tl-promo__img > picture,
.tl-about__media > picture, .tl-cert__mock > picture, .tl-consult__media > picture,
.tl-lead__media > picture, .tl-doc-hero__media > picture {
  display: block; width: 100%; height: 100%;
}

/* Safari (WebKit) и aspect-ratio: Chromium сначала ограничивает блок шириной колонки
   и уже из неё считает высоту, а WebKit берёт высоту (от min-height или содержимого)
   и вычисляет ширину, на доступную ширину не глядя. Замер на iPhone 13 (390):
   кадр «о клинике» 441 вместо 350, кадр у формы 392 вместо 350 - страница уезжала
   вбок на 71 px на главной и на 22 px у врача, правый край фото срезался.
   Явные width/max-width/min-width возвращают обоим движкам одинаковый расчёт.
   Матрица этого не видела: она ходит только Chromium. */
.tl-about__media, .tl-consult__media, .tl-lead__media, .tl-doc-hero__media,
.tl-welcome__media, .tl-cert__mock, .tl-faq__media, .tl-map, .tl-pb__media, .tl-video {
  width: 100%; max-width: 100%; min-width: 0;
}

/* Крупный набор с неразрывными пробелами на узком экране: связка слов не помещается
   в колонку и тянет страницу вбок (замер на iPhone SE: цитата в биоревитализации
   давала +14 px). Разрешаем перенос только тому, что целиком не влезает. */
.tl-page__t, .tl-page__slogan, .tl-doc-hero__name,
.tl-pull blockquote, .tl-credo blockquote, .tl-welcome__sub { overflow-wrap: break-word; }

/* Мозаика повторяет боевую: четыре колонки, все плитки квадратные, кроме двух
   двойной ширины - «Эстетическая косметология» и «Коррекция фигуры». Размеры сняты
   с живого сайта: 275x275 и 570x275 при контейнере 1160 и зазоре 20. */
.tl-tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--tl-gap); }
.tl-tile { position: relative; display: block; border-radius: 20px; overflow: hidden; aspect-ratio: 1/1; }
.tl-tile--wide { grid-column: span 2; aspect-ratio: 2 / 1; }
/* Последняя плитка добирает остаток ряда - иначе внизу справа зияла дыра (владелец
   27.08.2026: «в конце нижнего ряда не должно быть пусто»). Сам по себе
   grid-column-end: -1 не работает: при автоматической раскладке элемент с заданным
   концом всё равно получает одну колонку. Поэтому шаблон печатает число КЛЕТОК
   сетки (широкая плитка = две), а таблица правил ниже добирает остаток. */
.tl-tile--fill { aspect-ratio: auto; min-height: clamp(150px, 14vw, 220px); }
.tl-tile--fill > picture, .tl-tile--fill img { position: absolute; inset: 0; }
.tl-tile img { width: 100%; height: 100%; object-fit: cover; transition: transform .6s var(--ease); }
.tl-tile::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20,17,14,.86) 0%, rgba(20,17,14,.55) 38%, rgba(20,17,14,0) 78%); }
.tl-tile__t { position: absolute; left: 18px; right: 18px; bottom: 16px; z-index: 2; color: #fff;
  font-family: var(--font-display); font-size: clamp(13px, 1.15vw, 16px); text-transform: uppercase;
  line-height: 1.3; letter-spacing: .03em; text-shadow: 0 1px 8px rgba(0,0,0,.45);
  text-wrap: balance; }
@media (hover: hover) { .tl-tile:hover img { transform: scale(1.03); } }

/* --- Популярная услуга --- */
.tl-pop { background: var(--sand); border-radius: 20px; overflow: hidden; display: flex; flex-direction: column; }
.tl-pop__img { aspect-ratio: 1/1; overflow: hidden; }
.tl-pop__img img { width: 100%; height: 100%; object-fit: cover; }
/* Поля и кнопка сняты с живого сайта: карточка 275, поля 30, заголовок ровно на 30
   ниже фото, цена через 8, кнопка 215x60 у нижней кромки с отступом 30 и тенью
   0 7px 15px rgba(0,0,0,.2). Радиус кнопки у оригинала 30 при высоте 60 - это та же
   пилюля, что и наш 999px, поэтому радиус не трогаем. */
.tl-pop__body { padding: 30px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.tl-pop__t { font-family: var(--font-display); font-size: 16px; text-transform: uppercase; line-height: 1.35;
             letter-spacing: .03em; color: var(--tl-ink); min-height: 3em; text-wrap: balance; }
.tl-pop__p { font-family: var(--font-body); font-size: 18px; font-weight: 500; color: var(--tl-ink);
             font-variant-numeric: tabular-nums; }
/* На внутренних страницах в этой ленте у оригинала не цена, а слоган: Montserrat 14
   обычным начертанием - он не должен спорить с названием услуги. */
.tl-pop__p--note { font-size: 14px; font-weight: 400; color: var(--ink-soft); line-height: 1.45; }
.tl-pop .tl-btn { margin-top: auto; width: 100%; min-height: 60px; padding: 12px 18px;
                  box-shadow: 0 7px 15px rgba(42,38,34,.22); }

/* --- Сертификаты. Замер живого сайта на 1512: кремовая полоса #f9f5f2 во всю ширину,
   срез 300 справа сверху и снизу; макет 564x357 слева, текст 531 справа, зазор 42;
   ниже ряд из четырёх карт 274x141 с шагом 295; внутренние поля полосы 100 сверху и снизу.
   На 390: срез 100 только сверху справа, порядок «текст - макет - карты 2x2». --- */
/* Секция белая, полоса кремовая поверх - ровно как на бою (там под плашкой лежит белый
   артборд 1512x721). Без белой подложки срез 300 не виден вовсе: фон body сам кремовый,
   и полоса сливается с ним - тот же закон, что уже ловили на срезах между секциями. */
.tl-sec--cert { padding-block: 40px 0; background: var(--surface); }
.tl-cert-band { background: var(--cream); border-radius: 0 300px 300px 0; padding-block: clamp(56px, 6.6vw, 100px); }
.tl-cert { display: grid; grid-template-columns: minmax(0, 564fr) minmax(0, 531fr);
           gap: clamp(24px, 3vw, 42px); align-items: center; }
.tl-cert__mock { position: relative; border-radius: 18px; overflow: hidden; aspect-ratio: 564 / 357;
                 border: 2px solid var(--gold); }
.tl-cert__mock img { width: 100%; height: 100%; object-fit: cover; }
/* Вуаль под знаком. Замер: при .42 самый тёмный пиксель фона давал знаку контраст 2,99 -
   ровно на границе порога 3,0 для крупного текста, знак местами сливался с мебелью.
   При .55 худший пиксель даёт 4,73, средний фон - 8,89. */
.tl-cert__mock::after { content: ""; position: absolute; inset: 0; background: rgba(255,255,255,.55); }
.tl-cert__mock .zmark { position: absolute; inset: 0; z-index: 2; }
.tl-cert__lead { font-family: var(--font-body); font-size: 16px; line-height: 1.6; color: var(--ink-soft); }
.tl-cert ul { list-style: none; padding: 0; margin: 18px 0 0; display: flex; flex-direction: column; gap: 8px; }
.tl-cert li { position: relative; padding-left: 20px; font-family: var(--font-body); font-size: 16px; color: var(--ink-soft); }
.tl-cert li::before { content: "•"; position: absolute; left: 4px; color: var(--gold-deep); }

/* Ряд карт: срез 100 смотрит наружу - у первой в левый нижний угол, у последней в правый. */
.tl-cert__cards { list-style: none; padding: 0; margin: clamp(18px, 2vw, 22px) 0 0;
                  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--tl-gap); }
.tl-cert__card { aspect-ratio: 274 / 141; border-radius: 20px; display: grid; place-items: center; }
/* Срез задан долями, а не 100 px: на десктопе доли дают ровно 100 (36,5% от 274 и 71% от 141),
   а на планшете угол остаётся геометрически подобным. С жёсткими 100 px при высоте карты 86
   срез превышал саму высоту и угол вырождался в полукруг. */
.tl-cert__card:first-child { border-radius: 20px 20px 20px 36.5% / 20px 20px 20px 71%; }
.tl-cert__card:last-child  { border-radius: 20px 20px 36.5% 20px / 20px 20px 71% 20px; }
.tl-cert__card--pink  { background: #ffebec; }
.tl-cert__card--grey  { background: #e2e3e5; }
.tl-cert__card--lilac { background: #c8a2c9; }
.tl-cert__card--peach { background: #ebc8b2; }

/* Знак: тот же вектор, что в шапке, но в столбик - как на картах оригинала. */
.zmark { display: grid; place-content: center; justify-items: center; gap: 6px;
         color: var(--tl-ink); text-align: center; }
.zmark__d { width: clamp(26px, 2.4vw, 34px); height: auto; }
.zmark__w { font-family: var(--font-display); font-size: clamp(15px, 1.5vw, 21px); letter-spacing: .3em;
            line-height: 1; text-indent: .3em; }
.zmark__s { font-family: var(--font-body); font-size: clamp(7px, .62vw, 9px); letter-spacing: .58em;
            line-height: 1; text-indent: .58em; }

/* На макете знак крупный: у оригинала слово занимает 43% ширины карточки (242 из 564),
   у общего размера знака вышло бы 25% - карточка читалась бы как просто фото. */
.tl-cert__mock .zmark { gap: 11px; }
.tl-cert__mock .zmark__d { width: clamp(52px, 6.8vw, 102px); }
.tl-cert__mock .zmark__w { font-size: clamp(20px, 2.6vw, 39px); }
.tl-cert__mock .zmark__s { font-size: clamp(9px, 1.1vw, 17px); }

/* Кнопка на кремовой полосе - белая с тенью и шириной 300, как на оригинале. */
.tl-btn--raised { box-shadow: 0 7px 15px rgba(42,38,34,.22); }
/* Вторая кнопка героя врача: заливка бежевая, как на бою, но текст ТЁМНЫЙ.
   На бою он белый (#fff на #d5c4b3 - контраст 1,7:1), и на песочной плашке кнопка
   читалась как выключенная. Тёмный текст даёт 8:1 при том же силуэте. */
.tl-btn--sand { background: #d5c4b3; color: var(--tl-ink); }
.tl-btn--sand:hover { background: #c9b5a1; }
.tl-cert__txt .tl-btn { min-width: 300px; }

/* --- Форма и контакты --- */
/* Форма и снимок заканчиваются на одной линии. До правки низ расходился на 107 px
   (форма 311, фото 418): фото живёт своей пропорцией 4:3, а форма - высотой содержимого.
   Тянем форму на высоту строки и распределяем её поля - снимок при этом не кадрируется. */
.tl-consult { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 3vw, 56px); align-items: stretch; }
.tl-consult .tl-form { height: auto; align-content: start; }
/* Кадр формы на бою стоит в золотой рамке 2px со срезом сверху-справа (замер: 370x448,
   радиус 20/100/20/20) - у нас рамки не было, и кадр выглядел вклеенным. Рамка рисуется
   градиентной подложкой с padding 2px, кадр внутри с радиусом на 2 меньше. */
.tl-consult__media { border-radius: 20px 100px 20px 20px; overflow: hidden; aspect-ratio: 4/3;
                     padding: 2px; background: linear-gradient(150deg, #c49b68 0%, #f3ddbc 48%, #c49b68 100%); }
/* Кроп по верху: портретный кадр владелицы (consult-form) в ландшафтной рамке иначе
   резал лицо - показывалась середина. Ландшафтному кадру ресепшена позиция безразлична. */
.tl-consult__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 12%;
                         border-radius: 18px 98px 18px 18px; }
/* Паттерн №5 боя: форма живёт НА песочной капсуле со срезом снизу слева (плашка 766x448).
   Канон подачи - как на бою: заголовок одной строкой, имя + телефон + кнопка В ОДИН РЯД,
   согласие мелкой строкой-звёздочкой (чекбокса на бою нет). */
.tl-consult__card { background: var(--sand); border-radius: 20px 20px 20px 100px;
                    padding: clamp(28px, 3.5vw, 46px) clamp(24px, 3vw, 44px) clamp(40px, 4vw, 60px);
                    display: flex; flex-direction: column; justify-content: center; }
.tl-consult__card .tl-head { margin-bottom: 10px; font-size: clamp(22px, 2.1vw, 30px); }
.tl-consult__lead { font-family: var(--font-body); font-size: clamp(15px, 1.4vw, 17px);
                    line-height: 1.55; color: var(--tl-ink); max-width: 52ch; margin-bottom: 22px; }
.tl-form__row { display: flex; gap: 12px; flex-wrap: wrap; }
.tl-form__row input { flex: 1 1 150px; min-width: 0; }
.tl-form__row .tl-btn { flex: 0 0 auto; }
.tl-consult__card .tl-form input[type="text"], .tl-consult__card .tl-form input[type="tel"] { border-color: transparent; }
.tl-consult__card .tl-btn--white:hover { background: var(--cream); }
.tl-form__consent { font-family: var(--font-body); font-size: 11.5px; line-height: 1.5;
                    color: var(--ink-mute); max-width: 56ch; }
.tl-form__consent a { color: inherit; }
/* Фото-вариант боя: плашка широкая, кадр - узкий ПОРТРЕТ во всю высоту плашки,
   срез сверху-слева (диагональ к срезу плашки), лицо не кропится ландшафтным окном */
.tl-consult--photo { grid-template-columns: 1.75fr 1fr; }
.tl-consult--photo .tl-consult__media { aspect-ratio: auto; height: 100%; min-height: 380px; }
.tl-consult--photo .tl-consult__media img { object-position: 50% 18%; }
@media (max-width: 860px) {
  .tl-consult--photo { grid-template-columns: 1fr; }
  .tl-consult--photo .tl-consult__media { aspect-ratio: 3/4; height: auto; max-width: min(420px, 100%); }
}
.tl-form { display: grid; gap: 14px; max-width: 540px; }
/* Ритуал «Заявка принята»: поля прячутся, остаётся подтверждение с шагами 01-03 */
.tl-form.is-done > :not(.tl-ritual) { display: none; }
.tl-ritual__t { font-family: var(--font-display); font-size: clamp(22px, 2.2vw, 28px);
                text-transform: uppercase; letter-spacing: .02em; color: var(--tl-ink); }
.tl-ritual__steps { list-style: none; padding: 0; margin: 18px 0 0; display: grid; gap: 14px; }
.tl-ritual__steps li { display: flex; gap: 14px; align-items: baseline; }
.tl-ritual__steps b { font-family: var(--font-display); font-weight: 400; font-size: 19px;
                      color: var(--gold-deep); }
.tl-ritual__steps span { font-family: var(--font-body); font-size: 15px; line-height: 1.55;
                         color: var(--tl-ink); }
.tl-form input[type="text"], .tl-form input[type="tel"] {
  width: 100%; min-height: 52px; padding: 14px 20px; font-size: 16px;
  border: 1.5px solid var(--line-strong); border-radius: 999px; background: #fff; color: var(--tl-ink);
}
.tl-form input:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 2px; border-color: var(--gold); }
.tl-note { font-family: var(--font-body); font-size: 12px; line-height: 1.5; color: var(--ink-mute); }
/* Карта крупнее текстовой колонки: контакты занимают треть, карта - две трети.
   Верх карты выровнен по первой строке контактов (align-items: start). */
/* Обе колонки одной высоты: карта и контакты кончаются на одной линии.
   Контакты распределяются по высоте, поэтому низ сходится без подгонки пикселями. */
.tl-contacts { display: grid; grid-template-columns: minmax(260px, 1fr) 2fr; gap: clamp(24px, 3vw, 56px); align-items: stretch; }
/* Левую колонку не растягиваем по содержимому: space-between разгонял адрес и кнопки
   к краям и оставлял 120 px дыры посередине. Содержимое идёт сверху ровным шагом,
   коробки колонок при этом по-прежнему одной высоты. */
.tl-contacts > div:first-child { display: flex; flex-direction: column; justify-content: flex-start; gap: 30px; }
.tl-contacts__list { display: flex; flex-direction: column; gap: 10px; font-family: var(--font-body); font-size: 16px; }

/* Контакты строками с иконками, как в оригинале */
.tl-cont { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 14px; }
.tl-cont li { display: grid; grid-template-columns: 22px 1fr; gap: 12px; align-items: start;
              font-family: var(--font-body); font-size: 16px; line-height: 1.45; }
.tl-cont svg { width: 18px; height: 18px; margin-top: 3px; fill: none;
               stroke: var(--gold-deep); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.tl-cont small { display: block; margin-top: 3px; font-size: 14px; color: var(--ink-mute); }
.tl-cont a { border-bottom: 1px solid transparent; }
@media (hover: hover) { .tl-cont a:hover { border-bottom-color: var(--gold); } }
.tl-contacts__media { border-radius: 20px 20px 200px 20px; overflow: hidden; aspect-ratio: 4/3; }
/* Карта - без скруглений: это функциональный элемент, а не карточка.
   Высота привязана к колонке контактов, чтобы низ обоих блоков сошёлся. */
/* Карта как в оригинале: тонкая золотая рамка, мягкое скругление, чистая карта с меткой.
   Крупный фирменный срез здесь неуместен - это функциональный элемент. */
/* Высоту карте задаёт колонка контактов, а не своя мера. Раньше стояло
   min-height: clamp(320px, 34vw, 480px) - карта выходила ниже последней кнопки
   на 68 px при 1512 и на 32 px при 1280. Теперь карта тянется ровно по колонке,
   а нижний предел оставлен на случай, если контактов вдруг станет мало. */
/* Высота карты равна высоте колонки контактов (align-items: stretch у .tl-contacts),
   нижняя граница поднята до 400 - размер из кода, который дал владелец 27.08.2026 */
.tl-map { border-radius: 20px; overflow: hidden; aspect-ratio: auto;
          min-height: clamp(260px, 18vw, 300px); height: 100%;
          border: 1px solid var(--gold); background: var(--sand); }
.tl-map { background: var(--sand); }
.tl-map iframe { width: 100%; height: 100%; border: 0; display: block; }
/* Фасад ленивой карты (Ф5): снимок заполняет окно карты, кнопка - пилюля по центру */
.tl-contacts__media img { width: 100%; height: 100%; object-fit: cover; }
/* Значки мессенджеров стоят вплотную под контактами и ровно по левому краю колонки.
   Кнопка 44px нужна пальцу, но её поле сдвигало значок вправо на 8px - ряд «валялся
   в стороне» от текста (владелец 27.08.2026). Компенсируем отрицательным отступом. */
.tl-msg { display: flex; flex-direction: column; gap: 12px; margin-top: 0; align-items: flex-start; }

/* --- Подвал: три колонки, слева фото --- */
.tl-foot { background: var(--sand); padding-block: 40px; }
.tl-foot__grid { display: grid; grid-template-columns: 1.1fr 1fr 1fr 1fr; gap: clamp(20px, 2.6vw, 40px); }
.tl-foot h4 { font-family: var(--font-display); font-weight: 400; font-size: 16px; text-transform: uppercase;
              letter-spacing: .06em; color: #232323; margin-bottom: 14px; }
.tl-foot ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.tl-foot a, .tl-foot li { font-family: var(--font-body); font-size: 14px; color: #232323; }
.tl-foot__legal { margin-top: 32px; padding-top: 18px; border-top: 1px solid rgba(35,35,35,.14);
                  font-family: var(--font-body); font-size: 12px; line-height: 1.6; color: rgba(35,35,35,.72); }
.tl-foot__legal p { max-width: 68ch; margin: 0; }

/* Подвал: знак-ромб и подпись, как на бою */
.tl-foot__logo { display: inline-flex; align-items: center; gap: 14px; color: #232323;
  text-decoration: none; }
.tl-foot__logo .zmark__d { width: 46px; height: 52px; flex: 0 0 auto; }
.tl-foot__name { font-family: var(--font-display); font-size: 22px; letter-spacing: .16em;
  line-height: 1; display: flex; flex-direction: column; gap: 6px; }
.tl-foot__name small { font-size: 10px; letter-spacing: .34em; opacity: .75; }
.tl-foot__tagline { margin: 18px 0 0; font-family: var(--font-body); font-size: 14px;
  line-height: 1.6; color: #232323; max-width: 30ch; }
/* адрес строками: раньше «д. 7» уезжало на следующую строку в одиночестве */
.tl-foot__addr { display: flex; flex-direction: column; gap: 6px; margin: 14px 0 0;
  font-family: var(--font-body); font-size: 14px; line-height: 1.5; color: #232323;
  text-wrap: pretty; }
.tl-foot__contacts { gap: 10px; }
/* нижняя полоса боя: слева права и политика, справа реквизиты */
.tl-foot__legal .tl-foot__med { margin-bottom: 18px; max-width: 96ch; }
.tl-foot__row { display: grid; grid-template-columns: 1fr auto; gap: 20px 40px; align-items: end; }
/* реквизиты не должны уезжать под круг «Онлайн-запись» (он fixed поверх страницы) */
.tl-foot__row p:last-child { text-align: right; padding-right: 130px; }
@media (max-width: 900px) { .tl-foot__row p:last-child { padding-right: 0; } }
@media (max-width: 720px) {
  .tl-foot__row { grid-template-columns: 1fr; }
  .tl-foot__row p:last-child { text-align: left; }
}

/* ============================ МОБАЙЛ ============================
   Композиция та же, кегли читаемые. */
@media (min-width: 601px) and (max-width: 900px) {
  .tl-tiles { grid-template-columns: repeat(3, 1fr); }
  .tl-tile--wide { grid-column: span 2; }
}
@media (max-width: 900px) {
  .tl-about, .tl-contacts, .tl-consult { grid-template-columns: minmax(0, 1fr); }
  .tl-contacts > div:first-child { display: block; }
  .tl-about__media, .tl-contacts__media { order: -1; }
  /* На телефоне первая цифра - на всю ширину, остальные четыре по две в ряд.
     В колонке 185 px подпись «лет работы на рынке эстетической медицины» ломалась
     на четыре строки и растягивала плашку до 167 px против 122 у соседей,
     а пятая карточка оставалась одна в ряду. */
  /* minmax(0, 1fr), а не 1fr: минимум у 1fr - это min-content содержимого, и на 320 px
     колонки распухали до 164+130 при доступных 280 - блок цифр вылезал за экран
     (замер в Safari на iPhone SE). Ноль в минимуме разрешает колонке сжиматься. */
  .tl-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tl-stats > * { grid-column: span 1 !important; }
  .tl-stats > :nth-child(1) { grid-column: 1 / -1 !important; }
  .tl-sec--curve, .tl-sec--curve-r { border-radius: 140px 0 0 0; padding-top: 80px; }
  .tl-sec--curve-r { border-radius: 0 140px 0 0; }
  .tl-tiles { grid-template-columns: 1fr 1fr; }
  /* на двух колонках двойная плитка занимает всю ширину и остаётся 2:1 */
  .tl-tile--wide { grid-column: 1 / -1; }
  .tl-foot__grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 720px) {
  .tl-hero { min-height: 78vh; }
  .tl-hero__body { max-width: none; }
  .tl-hero__btns .tl-btn { flex: 1 1 100%; }
  /* Сертификаты переходят в одну колонку только здесь, а не на 900: на планшете четыре
     карты в две колонки раздувались до квадратов 420x420, и на них уходило полтора экрана.
     Это единственный блок, где на телефоне первым идёт ТЕКСТ, а не снимок - так на бою
     (заголовок 173, макет 549, карты 893). Срез у полосы остаётся один, сверху справа,
     карты становятся квадратами 2x2 без срезов - тоже как на бою. */
  .tl-cert { grid-template-columns: 1fr; }
  .tl-cert-band { border-radius: 0 100px 0 0; }
  .tl-cert__mock { order: 2; aspect-ratio: 4 / 3; }
  .tl-cert__cards { grid-template-columns: 1fr 1fr; }
  .tl-cert__card, .tl-cert__card:first-child, .tl-cert__card:last-child {
    aspect-ratio: 1 / 1; border-radius: 20px; }
  /* На узком экране кнопка живёт по содержимому, как на бою (219 px против 300 на десктопе). */
  .tl-cert__txt .tl-btn { min-width: 0; }

  .tl-rail--4 > * { width: min(62vw, 240px); }
  /* Карточка на телефоне уже (240 против 275), поэтому поля и кнопка не берутся
     с десктопа буквально: 30+30 оставили бы под текст 180 px и заголовок тулиевого
     пилинга ломался бы на пять строк. Доля поля к ширине карточки та же, что на бою. */
  .tl-pop__body { padding: 24px; }
  .tl-pop .tl-btn { min-height: 48px; }
  .tl-pop__t { min-height: 0; }
  .tl-stat { padding: 18px 12px; }
}

/* ==========================================================================
   ШАПКА как на живом сайте.
   Открытие страницы: прозрачная поверх фото, белым.
   Скролл: липкая светлая, компактнее, с тенью.
   ========================================================================== */
.hdr {
  position: fixed; top: 0; left: 0; right: 0; z-index: 200;
  padding-block: 18px;
  color: #fff;
  /* Затемнение под шапкой: с 27.08.2026 меню лежит прямо на кадре страницы услуг,
     и на светлых снимках белые пункты пропадали (замер контраста: 2,2-4,1:1).
     Усилено до уровня, при котором любой кадр даёт не меньше 4,5:1. */
  background: linear-gradient(180deg, rgba(20,17,14,.72) 0%, rgba(20,17,14,.42) 55%,
                              rgba(20,17,14,.14) 82%, rgba(20,17,14,0) 100%);
  /* padding НЕ анимируем: это свойство раскладки, на каждом кадре пересчитывается высота
     шапки, и она физически прыгает с 78 на 62 px прямо во время прокрутки. Только краска. */
  transition: background .28s var(--ease), box-shadow .28s var(--ease), color .28s var(--ease);
}
.hdr__in {
  width: 100%; max-width: var(--tl-container); margin-inline: auto; padding-inline: 20px;
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: clamp(16px, 3vw, 48px);
}

/* Логотип: ромб с монограммой + слово */
.hdr__logo { display: flex; align-items: center; gap: 14px; color: inherit; min-height: 44px; }
.hdr__mark { width: 46px; height: 52px; flex: 0 0 auto; transition: width .3s var(--ease), height .3s var(--ease); }
.hdr__word { font-family: var(--font-display); font-size: 26px; letter-spacing: .3em; line-height: 1; }
.hdr__word small { display: block; font-family: var(--font-body); font-size: 9px; font-weight: 400;
                   letter-spacing: .58em; margin-top: 6px; opacity: .9; }

/* Центр: два ряда с линией между ними */
.hdr__mid { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.hdr__top { display: flex; align-items: center; justify-content: center; gap: clamp(14px, 2.4vw, 34px);
            padding-bottom: 10px; border-bottom: 1px solid currentColor; }
.hdr__top { border-bottom-color: rgba(255,255,255,.34); }
.hdr__meta { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
             font-family: var(--font-body); font-size: 15px; font-weight: 500; color: inherit; }
.hdr__meta svg { width: 16px; height: 16px; flex: 0 0 auto; fill: none;
                 stroke: var(--gold); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* Телефон в шапке - главная кнопка звонка с телефона. Замер: 139x19 CSS-пикселей,
   палец в такую строку не попадает (норма 44). Растим только зону касания
   вертикальными отступами, сама строка и раскладка шапки не двигаются. */
.hdr__phone { font-weight: 600; display: inline-flex; align-items: center;
              min-height: 44px; padding-block: 4px; }
.hdr__nav { display: flex; align-items: center; justify-content: center; gap: clamp(12px, 1.8vw, 26px); flex-wrap: wrap; }
.hdr__nav a { font-family: var(--font-body); font-size: 15px; font-weight: 500; color: inherit;
              border-bottom: 1px solid transparent; padding-bottom: 2px; }

/* Кнопка записи в шапке */
.hdr__cta {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 12px 30px; border-radius: 999px;
  border: 1.5px solid currentColor; color: inherit;
  font-family: var(--font-body); font-weight: 600; font-size: 15px; white-space: nowrap;
  transition: background .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.hdr__icons { display: none; gap: 8px; }
.hdr__ico { width: 44px; height: 44px; border-radius: 999px; border: 1.5px solid currentColor;
            display: grid; place-items: center; color: inherit; background: transparent; }
.hdr__ico svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7;
                stroke-linecap: round; stroke-linejoin: round; }

/* --- Прилипшее состояние --- */
.hdr.is-stuck {
  background: rgba(255,255,255,.97); color: var(--tl-ink);
  box-shadow: 0 6px 26px rgba(42,38,34,.10); padding-block: 10px;
}
/* Размытие подложки оставляем только там, где оно бесплатно. На телефоне это дорогая
   операция на всю ширину экрана в каждом кадре прокрутки, а фон и так непрозрачен на 97%. */
@media (min-width: 721px) { .hdr.is-stuck { backdrop-filter: blur(8px); } }
/* На телефоне размытия нет, и оставшиеся 3% прозрачности давали «призрак» яркого текста
   страницы за телефоном в шапке (QA 2026-08-13) - фон глухой, дизайн не меняется. */
@media (max-width: 720px) { .hdr.is-stuck { background: #fff; } }
.hdr.is-stuck .hdr__top { border-bottom-color: var(--line); }
/* Логотип ужимается при прокрутке ТОЛЬКО на десктопе. На телефоне базовый размер уже
   меньше этих значений (34px/18px), и правило работало наоборот - логотип рос на 29 px,
   сдвигал вправо блок метро с телефоном, и тот заезжал под кнопку меню. */
@media (min-width: 721px) {
  .hdr.is-stuck .hdr__mark { width: 38px; height: 43px; }
  .hdr.is-stuck .hdr__word { font-size: 22px; }
}
.hdr.is-stuck .hdr__cta { border-color: var(--graphite); }

@media (hover: hover) and (pointer: fine) {
  .hdr__nav a:hover { border-bottom-color: currentColor; }
  .hdr__cta:hover { background: #fff; color: var(--tl-ink); border-color: #fff; }
  .hdr.is-stuck .hdr__cta:hover { background: var(--graphite); color: #fff; border-color: var(--graphite); }
  .hdr__meta:hover { color: var(--gold); }
}
.hdr__nav a:focus-visible, .hdr__cta:focus-visible, .hdr__logo:focus-visible, .hdr__ico:focus-visible {
  outline: 2px solid currentColor; outline-offset: 3px; border-radius: 4px;
}

/* Герой уходит под шапку, поэтому даём ему запас сверху */
.tl-hero { padding-top: 150px; }

/* Внутренние страницы: шапка всегда светлая, контент не уезжает под неё */
body:not(.has-hero) .hdr { background: rgba(255,255,255,.97); color: var(--tl-ink); box-shadow: 0 6px 26px rgba(42,38,34,.08); }
body:not(.has-hero) .hdr .hdr__top { border-bottom-color: var(--line); }
body:not(.has-hero) .hdr .hdr__cta { border-color: var(--graphite); }
/* Отступ ровно под высоту шапки: было 158 при шапке 128, и разница читалась
   светлой полосой между меню и первым блоком (замечание клиники 27.08.2026) */
body:not(.has-hero) { padding-top: 128px; }

@media (max-width: 1100px) {
  .hdr__word { font-size: 20px; letter-spacing: .22em; }
  .hdr__meta, .hdr__nav a { font-size: 14px; }
  .hdr__cta { padding: 11px 20px; font-size: 14px; }
}
/* Кнопка записи в шапке телефона: на широком экране её роль играет .hdr__cta */
.hdr__book { display: none; }
@media (max-width: 900px) {
  .hdr__book { display: inline-flex; align-items: center; justify-content: center;
               min-height: 40px; padding: 0 16px; border: 0; border-radius: 999px;
               font-family: var(--font-body); font-size: 13.5px; font-weight: 600;
               letter-spacing: .01em; cursor: pointer; white-space: nowrap;
               background: #fff; color: var(--tl-ink); }
  body.has-hero .hdr:not(.is-stuck) .hdr__book { background: rgba(255,255,255,.94); }
  .hdr.is-stuck .hdr__book { background: var(--graphite); color: #fff; }
}
@media (max-width: 360px) {
  /* SE: бургер вылезал за экран на 3px - ужимаем поля контейнера, логотип и кнопку */
  .hdr__in { padding-inline: 12px; gap: 8px; }
  .hdr__word { font-size: 16px; letter-spacing: .18em; }
  .hdr__book { padding: 0 12px; font-size: 12.5px; }
}
@media (max-width: 430px) {
  .hdr__book { padding: 0 14px; font-size: 13px; }
}
@media (max-width: 360px) {
  /* Трубку прячем только на самых узких экранах. Раньше порог был 430: в шапке рядом
     стояли ещё метро и телефон строкой, и всё вместе не помещалось (замер: 406 против
     390). Теперь этого блока на телефоне нет, места хватает - номер снова под пальцем,
     а не только в шторке. */
  .hdr__icons .hdr__ico:not(.burger) { display: none; }
}
@media (max-width: 900px) {
  /* Высота шапки на телефоне ОДНА в обоих состояниях: если она меняется при прокрутке,
     контент под ней прыгает, и это читается как рывок. Меняется только краска. */
  .hdr, .hdr.is-stuck { padding-block: 10px; }
  .hdr__in { grid-template-columns: auto auto; justify-content: space-between; }
  .hdr__mid, .hdr__cta { display: none; }
  .hdr__icons { display: flex; }
  .hdr__mark { width: 34px; height: 38px; }
  .hdr__word { font-size: 18px; }
  .hdr__word small { font-size: 7px; letter-spacing: .42em; margin-top: 4px; }
  .tl-hero { padding-top: 96px; }
  body:not(.has-hero) { padding-top: 68px; }
}

/* --- Первое окно записи --- */
.modal__win {
  position: absolute; z-index: 2; left: 50%; top: 50%; transform: translate(-50%, -46%) scale(.97);
  width: min(94vw, 420px); background: var(--surface); color: var(--tl-ink);
  border-radius: 20px 100px 20px 20px; padding: clamp(24px, 3vw, 34px);
  box-shadow: 0 30px 80px rgba(20,17,14,.34);
  display: flex; flex-direction: column; gap: 14px;
  opacity: 0; transition: opacity .25s var(--ease), transform .25s var(--ease);
}
.drawer[aria-hidden="false"] .modal__win { opacity: 1; transform: translate(-50%, -50%) scale(1); }
/* Мобила: окно записи - НИЖНИЙ ЛИСТ (пакет «Консьерж», референс Remedy Lab):
   выезжает снизу во всю ширину, не выше 70dvh, углы скруглены только сверху.
   Большому пальцу ближе, чем центральная модалка, и не прыгает при клавиатуре. */
@media (max-width: 720px) {
  .modal__win {
    left: 0; right: 0; top: auto; bottom: 0; width: 100%;
    transform: translateY(12%); border-radius: 24px 24px 0 0;
    max-height: 70dvh; overflow-y: auto;
    padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  }
  .drawer[aria-hidden="false"] .modal__win { transform: none; }
}
.modal__x { position: absolute; top: 14px; right: 16px; width: 40px; height: 40px; border-radius: 999px;
            display: grid; place-items: center; color: var(--ink-mute); font-size: 15px; }
.modal__x:hover { color: var(--tl-ink); background: var(--cream); }
.modal__lead { font-family: var(--font-body); font-size: 15px; line-height: 1.5; color: var(--ink-soft); }
.field { display: flex; flex-direction: column; gap: 6px; }
.field__label { font-family: var(--font-body); font-size: 13px; font-weight: 600;
                letter-spacing: .04em; text-transform: uppercase; color: var(--ink-soft); }
.field__label i { color: var(--err); font-style: normal; margin-left: 3px; }
.modal__win input[type="text"], .modal__win input[type="tel"] {
  width: 100%; min-height: 52px; padding: 14px 20px; font-size: 16px;
  border: 1.5px solid var(--line-strong); border-radius: 999px; background: #fff; color: var(--tl-ink);
}
.modal__win input:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 2px; border-color: var(--gold); }
.modal__win input.is-bad { border-color: var(--err); }
.modal__win .tl-btn { width: 100%; margin-top: 4px; }
@media (prefers-reduced-motion: reduce) {
  .modal__win { transition: none; transform: translate(-50%, -50%) scale(1); }
}

/* --- Кнопка онлайн-записи YCLIENTS.
       Их правило `.yButton.bottom.right` специфичнее нашего, поэтому селектор такой же тяжёлый.

       Два вывода из замеров, оба дались кровью:

       1. НИКАКОГО `transform: scale()` на этой кнопке. У пульсирующего кольца свой
          `transform-origin: 140.328px 140.328px` в абсолютных пикселях. Масштаб родителя
          этот origin не пересчитывает - кольцо уезжало с центра кружка на 8.6 px по диагонали,
          и глазом это читалось как «обводка не синхронна с кружком». Без масштаба все три
          центра (кнопка, кружок, кольцо) совпадают до десятой пикселя.

       2. Кольцо на пике пульсации - 199 px против 100 px самого кружка, то есть ровно 50 px
          в каждую сторону от края кружка. Значит отступ от края экрана должен быть 50 px:
          тогда кольцо на максимуме касается края и НИ РАЗУ за него не выходит, а кружок
          заодно уходит от скругления угла телефона (проверено на радиусе 55 px).

       Отступ справа и снизу одинаковый - круг стоит на диагонали угла, на оси симметрии
       скругления. --- */
.ya-widget-button, .yclients-widget-button, .yButton.bottom.right,
[class*="yButton"], #ya-booking-widget-button {
  z-index: 130 !important;
  /* Панель «Записаться / Позвонить» выезжает за 0.3 s, и кнопка виджета обязана
     ехать вместе с ней. Без перехода она прыгала вверх скачком ровно на границе
     секции - это и читалось как «поднимается чуть выше». */
  transition: bottom .3s var(--ease) !important;
  /* Родной текст виджета - белый по бежевому, контраст 1,57:1, читать нечем.
     Графит из нашей палитры даёт 9,58:1. Заодно снимаем шрифт Play, который виджет
     тянул третьим гарнитуром с чужого домена (правило 25: два шрифта на сайт). */
  color: var(--graphite) !important;
  font-family: var(--font-body) !important;
  right: 50px !important;
  bottom: calc(50px + env(safe-area-inset-bottom, 0px)) !important;
}


/* Виджет красит текст внутренними узлами, поэтому накрываем всё поддерево. Селектор с
   html body не для красоты: их таблица подключается ПОСЛЕ нашей, и при равной
   специфичности их `!important` побеждает просто порядком. Утяжеляем селектор. */
html body .yButton, html body .yButton *, html body .yButtonText, html body .yButtonText * {
  font-family: var(--font-body) !important;
  color: var(--graphite) !important;
}

@media (max-width: 720px) {
  /* На телефоне кнопка стоит ниже: 30 px от края вместо 50. Отступ справа и снизу
     по-прежнему одинаковый, значит круг остаётся на диагонали угла. Кольцо пульсации
     на пике выходит за края на 20 px - одинаково с двух сторон, поэтому читается
     как срез в углу, а не как ошибка. */
  .ya-widget-button, .yclients-widget-button, .yButton.bottom.right,
  [class*="yButton"], #ya-booking-widget-button {
    right: 30px !important;
    bottom: calc(30px + env(safe-area-inset-bottom, 0px)) !important;
  }

  /* Уменьшать кнопку пробовали и `transform: scale()`, и `zoom` - оба ломают виджет:
     его скрипт считает размер кольца от измеренных px, и в обоих случаях кольцо
     съезжает с центра кружка (transform: на 8.6 px, zoom: на 14.3 px). Поэтому размер
     оставляем родной. Если кнопку надо мельче - это настройка в кабинете YCLIENTS,
     а не CSS поверх чужого виджета. */
  /* Круг записи виден и на телефоне - решение клиники (17.08): «кнопку онлайн-записи
     оставляем». Прежде мы его прятали, потому что он дублировал липкую панель
     «Записаться / Позвонить»; теперь снята панель, а не круг - канал записи один.
     Уменьшить круг нельзя: его размер задаётся в кабинете YCLIENTS, а не CSS
     (масштаб через transform/zoom смещает кольцо с центра, проверено замерами). */
}

/* Кольцо пульсации виджета на пике выходит за круг на 20 px с каждой стороны.
   На 390 px запаса в 30 хватает, а на 320 (iPhone SE) кольцо вылезало за правый край
   и тянуло страницу вбок - там отступ 40. Правило верхнего уровня: вложенный @media
   внутри @media в обычном CSS не применяется. */
@media (max-width: 360px) {
  .ya-widget-button, .yclients-widget-button, .yButton.bottom.right,
  [class*="yButton"], #ya-booking-widget-button {
    right: 40px !important;
    bottom: calc(40px + env(safe-area-inset-bottom, 0px)) !important;
  }
}

/* ==========================================================================
   МОБАЙЛ: герой как в оригинале - фото почти на весь экран, текст лежит
   прямо на снимке, кнопки в ряд. Раньше кадр обрывался высоко и плотный
   градиент читался как отдельная тёмная подложка под текстом.
   ========================================================================== */
@media (max-width: 720px) {
  .tl-hero {
    min-height: 86vh;
    padding-top: 190px;                 /* под двухрядную шапку */
    padding-bottom: clamp(30px, 7vw, 52px);
    border-radius: 0 0 clamp(90px, 26vw, 140px) 0;
  }
  .tl-hero__bg img { object-position: center 42%; }
  /* подложка мягче: снимок должен читаться как фотография, а не как плашка */
  .tl-hero__bg::after {
    background:
      linear-gradient(to top, rgba(20,17,14,.62) 0%, rgba(20,17,14,.34) 24%, rgba(20,17,14,.06) 52%, rgba(20,17,14,0) 72%),
      linear-gradient(180deg, rgba(20,17,14,.46) 0%, rgba(20,17,14,.12) 26%, rgba(20,17,14,0) 46%);
  }
  .tl-hero__btns { gap: 10px; flex-wrap: nowrap; }
  .tl-hero__btns .tl-btn { flex: 1 1 0; min-width: 0; padding: 13px 12px; font-size: 15px; }
  .tl-hero__sub { margin-top: 12px; }

  /* Шапка на мобайле: логотип слева, кнопка записи, трубка и бургер справа.
     Метро и телефон строкой сюда не помещаются: 02.09.2026 владелец прислал снимок
     с iPhone, где от них остались обрубки «М. м.» и «+7» - колонка между логотипом
     и кнопками у'же, чем нужный блоку 146 px. Прежняя попытка ужимать их по одному
     (метро с 400 px, весь блок с 380) не спасала: на 430 текст уже резался.
     Поэтому на телефоне блока нет вовсе - метро и телефон живут в выезжающем меню,
     в подвале и на «Контактах», а позвонить можно иконкой-трубкой рядом с бургером. */
  .hdr__nav { display: none; }
}
@media (max-width: 420px) {
  .hdr__word { font-size: 15px; letter-spacing: .16em; }
  .hdr__meta { font-size: 12px; }
  .tl-hero { padding-top: 176px; }
}

/* Арт-дирекция героя: вертикальный кадр телефону, горизонтальный десктопу */

@media (max-width: 720px) {
  .tl-hero__bg img { object-position: center 32%; }
}

/* Метро: одна метка на два адреса, как в оригинале */
.hdr__metro { align-items: flex-start; }
.hdr__metro svg { margin-top: 3px; }
.hdr__metro > span { line-height: 1.35; }
.hdr__metro-list { display: flex; flex-direction: column; line-height: 1.35; }
@media (min-width: 721px) {
  /* В строку через точку-разделитель: <br> тут не годится - после него текстовый узел,
     и отступ применить не к чему, две станции слипались в одно слово. */
  .hdr__metro-list { flex-direction: row; align-items: center; white-space: nowrap; }
  .hdr__metro-list span + span::before { content: "·"; margin: 0 6px; opacity: .55; }
}

/* Герой на телефоне во весь экран - и при этом вся команда в кадре.
   Раньше это было несовместимо: рамка телефона 0.46, а самый узкий возможный кадр
   команды 0.582, и cover срезал по 74 px с боков - крайние врачи уезжали.
   Решение не в кадрировании, а в наращивании: кадр достроен по вертикали до 0.44
   (1160x2636) там, где людей нет - потолок сверху, пол снизу, зеркальной полосой
   с растворённым стыком. По горизонтали берём ВСЮ ширину исходника: иначе у крайних
   врачей не остаётся поля и они читаются как срезанные краем экрана.
   Теперь рамка УЖЕ кадра по пропорции, поэтому cover режет верх и низ (достроенное),
   а не бока (людей). Запас 0.44 против 0.450 у самого
   узкого телефона - на любом экране режется только достройка. */
@media (max-width: 720px) {
  .tl-hero { min-height: 100svh; padding-bottom: clamp(34px, 8vw, 60px); }
  .tl-hero__bg img { object-position: center center; }
}

/* Низ первого экрана на телефоне: шильдик слева и круг записи справа стоят ОДНОЙ строкой,
   текст с кнопками - прямо над ней.
   Круг виджета 100 px в 50 px от низа, значит его центр на 100 px от края - на эту же линию
   центруем шильдик (50 px высотой -> нижняя кромка на 75 px). Шильдик выводим из потока,
   иначе он поднимает кнопки на свою высоту.
   Отступ снизу 150 px = ровно верхняя кромка круга. Больше не берём: на живом телефоне
   видимая высота экрана меньше 100svh на высоту браузерной обвязки (у 430x932 остаётся
   около 727), и каждый лишний пиксель отступа там весит втрое. */
@media (max-width: 720px) {
  /* Тот же env(), что у шильдика ниже: иначе на телефонах с ненулевой безопасной зоной
     шильдик поднимается, а отступ нет - и шильдик наезжает на кнопку «Записаться».
     В headless-браузере эта зона всегда 0, поэтому в проверках дефект не воспроизводился. */
  .tl-hero { padding-bottom: calc(150px + env(safe-area-inset-bottom, 0px)); }
}

/* После цветокоррекции снимок стал светлее, и белый текст на белых костюмах
   читался хуже. Усиливаем подложку под текстом на телефоне. */
@media (max-width: 720px) {
  .tl-hero__bg::after {
    background:
      linear-gradient(to top, rgba(18,15,12,.86) 0%, rgba(18,15,12,.72) 18%,
                              rgba(18,15,12,.44) 38%, rgba(18,15,12,.12) 58%,
                              rgba(18,15,12,0) 76%),
      linear-gradient(180deg, rgba(18,15,12,.48) 0%, rgba(18,15,12,.14) 24%, rgba(18,15,12,0) 44%);
  }
  .tl-hero__eyebrow { color: rgba(255,255,255,.94); }
  .tl-hero__t1, .tl-hero__t2, .tl-hero__sub { text-shadow: 0 1px 12px rgba(18,15,12,.45); }
}

/* Текст героя на телефоне стоит не у самого низа, а выше кнопок - значит и
   подложка должна быть плотной именно там, а не только у нижней кромки. */
@media (max-width: 720px) {
  .tl-hero__bg::after {
    background:
      linear-gradient(to top,
        rgba(18,15,12,.82) 0%,  rgba(18,15,12,.80) 30%,
        rgba(18,15,12,.66) 52%, rgba(18,15,12,.34) 68%,
        rgba(18,15,12,.10) 82%, rgba(18,15,12,0)   94%),
      linear-gradient(180deg, rgba(18,15,12,.46) 0%, rgba(18,15,12,.12) 22%, rgba(18,15,12,0) 40%);
  }
}

/* Затемнение не «по всему кадру», а мягким пятном под текстом.
   Верх снимка и правая часть остаются светлыми - клиника про свет и воздух. */
@media (max-width: 720px) {
  .tl-hero__bg::after {
    background:
      /* мягкое пятно под текстовым блоком, уходит в ноль вправо и вверх */
      radial-gradient(115% 62% at 8% 86%,
        rgba(16,13,11,.80) 0%, rgba(16,13,11,.66) 32%,
        rgba(16,13,11,.36) 56%, rgba(16,13,11,.10) 76%, rgba(16,13,11,0) 92%),
      /* тонкая опора у нижней кромки под кнопки */
      linear-gradient(to top, rgba(16,13,11,.42) 0%, rgba(16,13,11,.14) 12%, rgba(16,13,11,0) 26%),
      /* лёгкая тень под шапкой, чтобы читались контакты */
      linear-gradient(180deg, rgba(16,13,11,.42) 0%, rgba(16,13,11,.10) 20%, rgba(16,13,11,0) 34%);
  }
  .tl-hero__t1, .tl-hero__t2 { text-shadow: 0 2px 18px rgba(16,13,11,.55); }
  .tl-hero__sub, .tl-hero__eyebrow { text-shadow: 0 1px 10px rgba(16,13,11,.5); }
}

/* Текстовый блок занимает 40-80% высоты героя (замер). Затемняем именно эту полосу,
   верхние 35% - чистое фото: там арка, лица и весь свет кадра. */
@media (max-width: 720px) {
  .tl-hero__bg::after {
    background:
      linear-gradient(to bottom,
        rgba(16,13,11,0)   0%,
        rgba(16,13,11,0)   30%,
        rgba(16,13,11,.14) 37%,
        rgba(16,13,11,.52) 46%,
        rgba(16,13,11,.62) 58%,
        rgba(16,13,11,.60) 74%,
        rgba(16,13,11,.44) 88%,
        rgba(16,13,11,.34) 100%),
      /* лёгкий крен влево: справа снимок остаётся светлее */
      linear-gradient(100deg, rgba(16,13,11,.20) 0%, rgba(16,13,11,.06) 45%, rgba(16,13,11,0) 72%),
      linear-gradient(180deg, rgba(16,13,11,.40) 0%, rgba(16,13,11,.08) 18%, rgba(16,13,11,0) 30%);
  }
}

/* ==========================================================================
   МОУШЕН. Сдержанный, но живой: премиальная клиника, а не аттракцион.
   Всё на transform и opacity - без дёрганья раскладки.
   ========================================================================== */
html.js [data-anim], html.js [data-anim-group] > * {
  opacity: 0; transform: translateY(22px);
  transition: opacity .62s var(--ease), transform .62s var(--ease);
  transition-delay: var(--d, 0ms);
  /* will-change тут не ставим: на переходе opacity+transform выигрыш околонулевой,
     а свойство висело бы вечно на трёх десятках узлов и держало слои в памяти GPU. */
}
html.js [data-anim].is-in, html.js [data-anim-group].is-in > * { opacity: 1; transform: none; }

/* Заголовок секции въезжает чуть иначе - вбок, это читается как подпись */
html.js .tl-head[data-anim] { transform: translateY(0) translateX(-18px); }
html.js .tl-head[data-anim].is-in { transform: none; }

/* Герой: медленный наезд кадра - «дышит», пока человек читает */
@media (prefers-reduced-motion: no-preference) {
  /* Медленный наезд кадра - только на десктопе. На телефоне это непрерывная перерисовка
     картинки во весь экран, и вместе с прокруткой она даёт рывки; в покое разницы не видно. */
  @media (min-width: 721px) {
    .tl-hero__bg img { animation: tl-breathe 22s ease-in-out infinite alternate; }
  }
  @keyframes tl-breathe { from { transform: scale(1) } to { transform: scale(1.07) } }
  /* Текст героя проявляется по строкам при загрузке */
  .tl-hero__eyebrow, .tl-hero__t1, .tl-hero__t2, .tl-hero__sub, .tl-hero__btns {
    animation: tl-rise .9s var(--ease) both;
  }
  .tl-hero__t1  { animation-delay: .10s }
  .tl-hero__t2  { animation-delay: .18s }
  .tl-hero__sub { animation-delay: .28s }
  .tl-hero__btns{ animation-delay: .38s }
  /* Старт с .28, не с нуля: при opacity:0 браузер не считает заголовок отрисованным,
     и LCP героя сдвигался на конец анимации (+1.7 с в Lighthouse). Глазу разницы нет. */
  @keyframes tl-rise { from { opacity:.28; transform: translateY(26px) } to { opacity:1; transform:none } }
}

/* Цифры: подчёркивание прорастает под числом */
.tl-stat b { position: relative; display: inline-block; }
.tl-stat b::after {
  content: ""; position: absolute; left: 50%; bottom: -8px; height: 2px; width: 0;
  background: var(--gold); transform: translateX(-50%);
  transition: width .9s var(--ease) .35s;
}
.tl-stats.is-in .tl-stat b::after { width: 42px; }

/* Плитки услуг: кадр чуть выезжает, подпись приподнимается */
.tl-tile img { transition: transform .8s var(--ease); }
.tl-tile__t { transition: transform .5s var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .tl-tile:hover img { transform: scale(1.06); }
  .tl-tile:hover .tl-tile__t { transform: translateY(-4px); }
}

/* Кнопки: заливка наплывает слева, а не мигает цветом */
.tl-btn { position: relative; overflow: hidden; z-index: 0; }
.tl-btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1; transform: scaleX(0); transform-origin: left;
  transition: transform .45s var(--ease); background: currentColor; opacity: .1;
}
@media (hover: hover) and (pointer: fine) { .tl-btn:hover::before { transform: scaleX(1); } }

@media (prefers-reduced-motion: reduce) {
  html.js [data-anim], html.js [data-anim-group] > * { opacity: 1 !important; transform: none !important; }
  .tl-hero__bg img { animation: none !important; }
  .tl-hero__eyebrow, .tl-hero__t1, .tl-hero__t2, .tl-hero__sub, .tl-hero__btns { animation: none !important; }
}

/* ==========================================================================
   ПРИЁМ 2 «Дыхание пространства» (план вау-слоя, Ф3).
   Свет проходит по странице вместе со скроллом и фото внутри срезов
   двигаются медленнее страницы. Всё на opacity/transform - компоновка
   не пересчитывается, скролл остаётся 60 fps даже на среднем Android.
   ========================================================================== */
.tl-sec--bg-surface { --bg: var(--surface); }
.tl-sec--bg-cream   { --bg: var(--cream); }
.tl-sec--bg-sand    { --bg: var(--sand); }
.tl-sec[class*="--bg-"] { background: var(--bg); position: relative; isolation: isolate; }

.tl-sec[class*="--bg-"]::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: 0;
  background: radial-gradient(58% 46% at 50% 38%,
              color-mix(in oklab, var(--gold) 20%, transparent), transparent 72%);
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Свечение по секциям снято вместе с цветными полосами: на белой странице оно читается
       как пятно позади содержимого. Параллакс фото ниже остаётся - он на самих снимках. */
    @keyframes tl-glow {
      0%   { opacity: 0;   transform: translateY(5%); }
      50%  { opacity: .55; transform: none; }
      100% { opacity: 0;   transform: translateY(-5%); }
    }
    /* Параллакс фото. Только там, где кадр заведомо крупнее рамки.
       Макет сертификата сюда больше не входит: это не снимок, а карточка со знаком
       поверх - если фон поедет под неподвижным знаком, знак прочтётся как наклейка. */
    .tl-about__media, .tl-consult__media { overflow: hidden; }
    .tl-about__media img, .tl-consult__media img,
    .tl-pb__media--img img, .tl-season__media img {
      animation: tl-para linear both; animation-timeline: view(); animation-range: entry 0% exit 100%;
    }
    @keyframes tl-para {
      from { transform: translateY(-3.5%) scale(1.09); }
      to   { transform: translateY(3.5%)  scale(1.09); }
    }
  }
}

/* Микро-детали исполнения: отклик на нажатие и общий фокус (правила 10, 33, 40) */
.tl-btn:active, .hdr__cta:active, .tl-nav button:active { transform: translateY(1px); }
.tl-btn, .hdr__cta, .tl-nav button { transition: background-color .3s, color .3s, border-color .3s, transform .12s; }
/* Фокус-кольцо задаётся ОДНИМ правилом в styles.css (#7d6243 - золото для текста и
   контуров на светлом). Дубль с var(--gold) удалён: два цвета спорили в каскаде. */

/* ==========================================================================
   ВНУТРЕННИЕ СТРАНИЦЫ на общем каркасе .tl (вау-план, Ф2).
   ========================================================================== */
/* Отступ сверху был двойным: body уже компенсирует фиксированную шапку (158 px на десктопе,
   74 на телефоне), а секция добавляла сверху ещё 132. Между шапкой и хлебными крошками
   получалось 182 px пустоты, до H1 - 254. Оставляем только воздух: 40 и 24. */
.tl-page { padding-top: clamp(24px, 2.6vw, 40px); padding-bottom: clamp(28px, 3.4vw, 46px); }
.tl-page__eyebrow { font-family: var(--font-body); font-size: 13px; letter-spacing: .16em;
                    text-transform: uppercase; color: var(--gold-deep); margin-bottom: 12px; }
.tl-page__t { font-family: var(--font-display); font-weight: 400; line-height: 1.08;
              font-size: clamp(30px, 4.4vw, 56px); text-transform: uppercase;
              letter-spacing: .01em; color: var(--tl-ink);
              overflow-wrap: break-word; }
/* «КОНФИДЕНЦИАЛЬНОСТИ» требует 435 px, а колонка на 390 даёт 350: слово вылезало
   и растягивало страницу. Перенос по словарю - ТОЛЬКО на узких экранах: на десктопе
   словарный перенос рвал заголовки, которым места хватает («ЛЕЧЕ-/НИЯ»). */
@media (max-width: 640px) { .tl-page__t { hyphens: auto; } }
.tl-page__lead { font-family: var(--font-body); font-size: clamp(15px, 1.5vw, 19px);
                 line-height: 1.6; color: var(--ink-soft); max-width: 62ch; margin-top: 14px; }

/* Подводка героя («цепляющая фраза» боя). Клиника: «фразы цепляющие психологически,
   но для зрения незаметны» - раньше печатались тем же классом, что рядовые вводные
   абзацы. Теперь капс Montserrat 500 с разрядкой, акцентный цвет и золотая черта
   сверху: читается как манифест, а не как обычный текст. На бою фраза белым капсом
   лежит поверх фото - у нас герой в две колонки, поэтому берём типографику, а не
   раскладку. */
.tl-page__slogan { font-family: var(--font-body); font-weight: 500; text-transform: uppercase;
                   font-size: clamp(14px, 1.35vw, 18px); line-height: 1.5; letter-spacing: .05em;
                   color: var(--gold-deep); max-width: 34ch; margin-top: 18px;
                   padding-top: 16px; position: relative; text-wrap: balance; }
.tl-page__slogan::before { content: ""; position: absolute; top: 0; left: 0; width: 56px; height: 2px;
                           background: linear-gradient(90deg, #c49b68, #f3ddbc); }
/* Цена шла впритык к слогану - между манифестом и цифрой нужен воздух */
.tl-page__slogan + .tl-price { margin-top: 18px; }
@media (max-width: 720px) { .tl-page__slogan { letter-spacing: .04em; max-width: none; } }

/* Сетки карточек внутренних страниц */
.tl-grid { display: grid; gap: var(--tl-gap); }
.tl-grid--2 { grid-template-columns: repeat(2, 1fr); }
.tl-grid--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .tl-grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .tl-grid--2, .tl-grid--3 { grid-template-columns: 1fr; } }

/* Карточка-ссылка в фирменной ДНК: песок, срез угла, золотая линия при наведении */
.tl-card { display: flex; flex-direction: column; gap: 10px; background: var(--sand);
           border-radius: 20px 100px 20px 20px; padding: 26px 24px; color: var(--tl-ink);
           text-decoration: none; min-height: 190px; position: relative;
           transition: transform .5s var(--ease), box-shadow .5s; }
/* Срез у зеркальной карточки - снизу, а не сверху-слева: ярлык стоит в верхнем левом
   углу с отступом 24-26px, и срез 100px съедал его (закон «подпись на прямой кромке»,
   прецедент плиток из плана 0-бис). Чередование срезов сохраняется по диагонали. */
.tl-card--flip { border-radius: 20px 20px 20px 100px; }
/* На песочной секции карточка того же цвета, что фон - сетка переставала читаться.
   Палитру не расширяем: берём вторую фирменную плоскость (белую). */
.tl-sec--bg-sand .tl-card { background: var(--surface); }
.tl-card__eyebrow { font-family: var(--font-body); font-size: 12px; letter-spacing: .14em;
                    text-transform: uppercase; color: var(--gold-deep); }
.tl-card h2, .tl-card .tl-card__t { font-family: var(--font-display); font-weight: 400;
                    font-size: clamp(17px, 1.6vw, 21px); line-height: 1.25; text-transform: uppercase; }
.tl-card p { font-family: var(--font-body); font-size: 15px; line-height: 1.55; color: var(--ink-soft); }
/* #75593c вместо --gold-deep: на песочной карточке тот давал 4,15:1 при норме 4,5 */
.tl-card__more { margin-top: auto; font-family: var(--font-body); font-size: 14px;
                 letter-spacing: .04em; color: #75593c; }
.tl-card__more::after { content: ""; display: block; height: 1px; width: 26px; margin-top: 6px;
                        background: var(--gold); transition: width .45s var(--ease); }
@media (hover: hover) and (pointer: fine) {
  a.tl-card:hover { transform: translateY(-4px); box-shadow: 0 18px 44px rgba(42,38,34,.10); }
  a.tl-card:hover .tl-card__more::after { width: 64px; }
}

/* Сетка врачей: та же карточка, что в карусели на главной */
.tl-docs { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--tl-gap); }
/* Хвост сетки: после ухода сотрудника врачей стало семеро, и последний ряд из одной
   карточки прижимался к левому краю - клиника про эту пустоту писала отдельно.
   Одиночный хвост ставим в среднюю колонку, пару - в свою сетку по центру. */
.tl-docs > :last-child:nth-child(3n + 1) { grid-column: 2; }
.tl-docs--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 786px; margin-inline: auto; }
.tl-docs--pair > :last-child:nth-child(3n + 1) { grid-column: auto; }
/* Тот же приём для карточек каталога: одинокая карточка в конце ряда встаёт по центру.
   Модификатор точечный - у сеток отзывов и «популярного» свои ряды, их не трогаем. */
.tl-grid--tail > :last-child:nth-child(3n + 1) { grid-column: 2; }
@media (max-width: 900px) { .tl-grid--tail > :last-child:nth-child(3n + 1) { grid-column: auto; } }
@media (max-width: 900px) { .tl-docs > :last-child:nth-child(3n + 1) { grid-column: auto; } }
@media (max-width: 900px) { .tl-docs { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .tl-docs { grid-template-columns: 1fr; } }
.tl-docs .tl-doc { width: auto; }

/* Длинный юридический текст */
.tl-prose { max-width: 74ch; font-family: var(--font-body); font-size: 16px; line-height: 1.7; color: var(--tl-ink); }
.tl-prose p { margin-top: 14px; }
.tl-prose a { color: var(--gold-deep); text-decoration: underline; }

/* Хлебные крошки и карточка врача на его странице */
.tl-crumbs { font-family: var(--font-body); font-size: 13px; color: var(--ink-soft); margin-bottom: 18px; }
.tl-crumbs a { color: var(--ink-soft); text-decoration: none; transition: color .2s; }
.tl-crumbs a:hover { color: var(--gold-deep); }
.tl-crumbs span { margin: 0 8px; opacity: .6; }
.tl-crumbs > span:last-child { margin: 0; opacity: 1; color: var(--tl-ink); }

/* Герой врача - раскладка действующего сайта (замер 17.08.2026 при 1512: песочная
   плашка 568x583 слева со срезом снизу-слева, портрет 568x583 справа в золотой рамке
   со срезом сверху-справа, зазор 20). Все правила героя держим ОДНИМ блоком: раньше
   они были раскиданы по файлу в двух местах, и правка в одном тихо отменялась другим. */
.tl-doc-hero { display: grid; grid-template-columns: 1fr 1fr; gap: 20px;
               align-items: stretch; margin-top: 8px; }
.tl-doc-hero__card { background: var(--sand); border-radius: 20px 20px 20px 100px;
                     padding: clamp(28px, 3.4vw, 52px) clamp(24px, 3.4vw, 52px);
                     display: flex; flex-direction: column; justify-content: center; }
.tl-doc-hero__name { font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
                     font-size: clamp(21px, 2vw, 30px); line-height: 1.26; letter-spacing: .02em;
                     color: var(--tl-ink); text-wrap: balance; }
/* должность на бою идёт буллитом - точка рисуется псевдоэлементом, а не списком:
   это одна строка, а не перечень */
.tl-doc-hero__role { position: relative; padding-left: 20px; margin-top: 22px;
                     font-family: var(--font-body); font-weight: 500; line-height: 1.4;
                     font-size: clamp(15px, 1.25vw, 18px); color: var(--tl-ink); }
.tl-doc-hero__role::before { content: ""; position: absolute; left: 2px; top: .58em;
                             width: 6px; height: 6px; border-radius: 50%; background: var(--tl-ink); }
.tl-doc-hero__lead { margin-top: 14px; font-size: 14px; line-height: 1.62; color: var(--tl-ink); }
.tl-doc-hero__lead + .tl-doc-hero__lead { margin-top: 10px; }
/* философия врача - курсивом, как на бою: это подпись, а не рядовой абзац */
.tl-doc-hero__lead--credo { font-style: italic; font-weight: 500; }
.tl-doc-hero__btns { display: flex; flex-wrap: wrap; gap: 14px; margin-top: clamp(22px, 2.6vw, 34px); }
/* Портрет: рамка боя - золотой градиент 2px, поэтому обёртка красится градиентом,
   а кадр внутри лежит с радиусом на 2 меньше. */
.tl-doc-hero__media { border-radius: 20px 100px 20px 20px; overflow: hidden; padding: 2px;
                      background: linear-gradient(150deg, #c49b68 0%, #f3ddbc 48%, #c49b68 100%); }
.tl-doc-hero__media img { display: block; width: 100%; height: 100%; object-fit: cover;
                          object-position: center 18%;   /* портреты вертикальные: держим лицо в кадре */
                          aspect-ratio: 568 / 583; border-radius: 18px 98px 18px 18px; }
@media (max-width: 860px) {
  .tl-doc-hero { grid-template-columns: 1fr; }
  /* На телефоне порядок как на десктопе: сначала портрет, потом плашка с именем и
     должностью, потом видео-визитка (владелец 27.08.2026: «сначала фото, потом текст
     и видео»). Раньше портрет уходил вниз - берегли высоту до H1; кадр укорочен до
     4:5 и в тонкой обойме, поэтому имя всё равно видно почти сразу. */
  .tl-doc-hero__media { order: -1; }
  /* Кнопки в плашке врача - как в героях остальных страниц: две равные в один ряд.
     Раньше они шли столбиком и разной ширины («Записаться» 148, «Смотреть услуги» 188),
     ряд смотрелся рваным (вопрос владельца 27.08.2026). На узком экране, где два
     столбца дают меньше 130px на кнопку, возвращаемся к столбику во всю ширину. */
  .tl-doc-hero__btns { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
  .tl-doc-hero__btns .tl-btn { width: 100%; justify-content: center; padding-inline: 12px; }
  /* Порог 480: на 390px в ряд помещается по 146px на кнопку, и «Смотреть услуги»
     ломается на две строки - кнопки становятся 75px против 53. Ниже 480 столбик,
     но обе кнопки во всю ширину плашки: ряд ровный, цель крупная. */
  @media (max-width: 479px) {
    .tl-doc-hero__btns { grid-template-columns: 1fr; }
  }
  .tl-doc-hero__media img { aspect-ratio: 4 / 5; }
}

/* Ввод внутренней страницы: фото слева, заголовок справа - тот же ритм, что «о клинике» */
/* minmax(0, 1fr) во второй колонке снимает автоминимум по содержимому: без него ширина
   правой колонки зависела от длины заголовка, и фото гуляло по горизонтали на 122 px
   от страницы к странице. */
.tl-lead { display: grid; grid-template-columns: minmax(280px, 560px) minmax(0, 1fr); gap: clamp(24px, 3vw, 46px);
           align-items: center; margin-top: 8px; }
.tl-lead__media { border-radius: 20px 20px 100px 20px; overflow: hidden; background: var(--sand); }
.tl-lead__media img { display: block; width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4/3; }
@media (max-width: 860px) { .tl-lead { grid-template-columns: 1fr; } }

/* Строки услуг внутри направления */
.tl-rows { display: flex; flex-direction: column; }
.tl-rows a { display: flex; align-items: center; justify-content: space-between; gap: 18px;
             padding: 16px 4px; border-bottom: 1px solid rgba(42,38,34,.14); text-decoration: none;
             font-family: var(--font-body); color: var(--tl-ink); transition: padding-left .35s, color .35s; }
.tl-rows a u { text-decoration: none; white-space: nowrap; color: var(--gold-deep); font-weight: 600; }
/* На узком экране строка прайса не помещается в одну линию: цена набрана nowrap и
   flex её не сжимает - на 320 px «34 900 ₽ 50 000 ₽» уезжало за край на 47 px.
   Разрешаем перенос: название сверху, цена под ним. */
@media (max-width: 520px) {
  .tl-rows a { flex-wrap: wrap; row-gap: 6px; }
  .tl-rows a u { white-space: normal; }
  .tl-rows a > :first-child { flex: 1 1 100%; }
}
@media (hover: hover) and (pointer: fine) { .tl-rows a:hover { padding-left: 12px; color: var(--gold-deep); } }

/* Отзыв */
/* Отзыв - карточка боя: ПЕСОЧНАЯ плашка с ровным радиусом 20 (срез здесь не наш -
   на бою его нет), имя антиквой сверху, текст, ссылка «Читать весь отзыв».
   Звёзд на бою нет: рейтинг живёт на Яндекс.Картах, свой не рисуем. */
.tl-review { display: flex; flex-direction: column; gap: 14px; background: var(--sand);
             border-radius: 20px; padding: 28px 26px; }
.tl-review__who { font-family: var(--font-display); font-size: 19px; line-height: 1.25;
                  color: var(--tl-ink); }
.tl-review__t { font-family: var(--font-body); font-size: 14.5px; line-height: 1.6;
                color: var(--tl-ink); margin: 0; }
.tl-review__more { font-family: var(--font-body); font-size: 14px; font-weight: 600;
                   color: var(--tl-ink); text-decoration: none; margin-top: auto; }
@media (hover: hover) { .tl-review__more:hover { color: var(--gold-deep); } }
/* Шапка блока: вводный текст слева, белая пилюля «Все отзывы» справа (бой) */
.tl-rev__top { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: clamp(20px, 3vw, 48px);
               align-items: center; margin-bottom: 26px; }
.tl-rev__top .tl-page__lead { max-width: 62ch; }
@media (max-width: 720px) {
  .tl-rev__top { grid-template-columns: 1fr; }
  .tl-rev__top .tl-btn { justify-self: start; }
}

/* Страница процедуры: текст + липкая карточка записи */
.tl-doc-layout { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: clamp(24px, 3vw, 48px); align-items: start; }
@media (max-width: 980px) { .tl-doc-layout { grid-template-columns: 1fr; } }
.tl-aside { position: sticky; top: calc(var(--header-h, 72px) + 16px); }
@media (max-width: 980px) { .tl-aside { position: static; } }
.tl-book { display: flex; flex-direction: column; gap: 12px; background: var(--sand);
           border-radius: 20px 100px 20px 20px; padding: 26px 24px; }
.tl-book__t { font-family: var(--font-display); font-size: 20px; line-height: 1.25; text-transform: uppercase; }
.tl-book__meta { font-family: var(--font-body); font-size: 13px; color: var(--ink-soft); line-height: 1.5; }
.tl-price { font-family: var(--font-body); font-size: 15px; color: var(--ink-soft); }
.tl-price b { font-family: var(--font-display); font-size: 26px; color: var(--tl-ink); margin-left: 6px; }
.tl-prose__lead { font-size: 18px; line-height: 1.6; color: var(--tl-ink); }
.tl-prose__h { font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
               font-size: clamp(19px, 2vw, 25px); line-height: 1.25; margin-top: 30px; }
/* Подзаголовок внутри раздела - у оригинала это Tenor 18 без капса («01. Подготовка
   и диагностика.»), то есть ступенью ниже раздела и заметно тише его. */
.tl-prose__h3 { font-family: var(--font-display); font-weight: 400; font-size: clamp(17px, 1.5vw, 19px);
                line-height: 1.3; margin-top: 22px; color: var(--tl-ink); }

/* padding: 0 гасит браузерный отступ ul (40px) - список стоит под ярлыком, а не
   в случайном жёлобе. margin-block: auto центрует список в свободном месте карточки:
   при разном числе пунктов обе плашки ряда смотрятся уравновешенно. */
.tl-ticks { list-style: none; display: flex; flex-direction: column; gap: 8px;
            margin-block: auto; padding: 0; }
.tl-ticks li { position: relative; padding-left: 24px; font-family: var(--font-body);
               font-size: 15px; line-height: 1.5; color: var(--tl-ink); }
.tl-ticks li::before { content: "✓"; position: absolute; left: 0; color: var(--gold-deep); }
.tl-ticks--no li::before { content: "—"; opacity: .6; }
/* Вводная строка боя над списком («Безопасность — наш приоритет. Процедуру не проводят при:»):
   не пункт, ромба не несёт. Пара «вводная + список» прижата к верху карточки, а не центруется -
   иначе вводные соседних карточек ряда пляшут по высоте (QA губ: 56px против 10px). */
.tl-ticks__lead { font-family: var(--font-body); font-size: 15px; line-height: 1.5;
                  color: var(--tl-ink); opacity: .82; margin-block: 0; }
.tl-ticks__lead + .tl-ticks { margin-block: 10px auto; }
/* Группа внутри списка боя («Профилактические показания:», «Относительные противопоказания:»):
   подзаголовок, не пункт - без маркера, полужирным, с воздухом сверху. */
.tl-ticks li.tl-ticks__grp { padding-left: 0; font-weight: 600; margin-top: 10px; }
.tl-ticks li.tl-ticks__grp::before { content: none; }

/* Блок вопросов боя: слева кадр со срезом угла, справа строки-карточки.
   На узком экране кадр уходит наверх, карточки - под ним. */
.tl-faq-split { display: grid; grid-template-columns: minmax(280px, 380px) minmax(0, 1fr);
                gap: clamp(20px, 3vw, 48px); align-items: start; margin-top: 30px; }
.tl-faq__media { border-radius: 100px 20px 20px 20px; overflow: hidden; aspect-ratio: 3/2; }
.tl-faq__media > picture { display: block; width: 100%; height: 100%; }
.tl-faq__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 860px) {
  .tl-faq-split { grid-template-columns: 1fr; }
  .tl-faq__media { max-width: 420px; }
}
/* Строка-карточка: белая пилюля с мягкой тенью, плюс справа (бой) */
.tl-faq--cards { display: grid; gap: 14px; }
.tl-faq--cards details { background: var(--surface); border: 0; border-radius: 20px;
                         padding: 20px 26px; box-shadow: 0 6px 18px rgba(42,38,34,.07); }
.tl-faq--cards summary { font-size: 15.5px; align-items: center; }
.tl-faq--cards summary::after { font-size: 26px; font-weight: 300; line-height: 1;
                                color: var(--ink-mute); }
.tl-faq details { border-bottom: 1px solid rgba(42,38,34,.14); padding: 14px 0; }
.tl-faq summary { cursor: pointer; list-style: none; font-family: var(--font-body); font-weight: 600;
                  color: var(--tl-ink); display: flex; justify-content: space-between; gap: 16px; }
.tl-faq summary::-webkit-details-marker { display: none; }
.tl-faq summary::after { content: "+"; color: var(--gold-deep); transition: transform .3s; }
.tl-faq details[open] summary::after { transform: rotate(45deg); }
.tl-faq p { font-family: var(--font-body); font-size: 15px; line-height: 1.6; color: var(--ink-soft); margin-top: 10px; }

/* Подложка героя: размытый кадр 24 px в data-URI (<1 КБ на экран).
   Пока грузится настоящий снимок, человек видит тот же кадр в цвете, а не серый прямоугольник. */
.tl-hero__bg { background: var(--graphite) center/cover no-repeat; background-image: url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABMNDhEODBMRDxEVFBMXHTAfHRoaHToqLCMwRT1JR0Q9Q0FMVm1dTFFoUkFDX4JgaHF1e3x7SlyGkIV3j214e3b/2wBDARQVFR0ZHTgfHzh2T0NPdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnb/wAARCAANABgDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDcaN5Iz5dH2Wby/vfN6VBo87yqdxzV/edxFJJMbYyAOi4kIzRVaa4ZZCBRSbsM/9k="); }
@media (max-width: 720px) { .tl-hero__bg { background-image: url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABMNDhEODBMRDxEVFBMXHTAfHRoaHToqLCMwRT1JR0Q9Q0FMVm1dTFFoUkFDX4JgaHF1e3x7SlyGkIV3j214e3b/2wBDARQVFR0ZHTgfHzh2T0NPdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnb/wAARCAA3ABgDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDfXpT0xUEhKAYp+4bMg81mjRhJiimRnfyaKYhtzbyyoPLbvT1sG8v/AFh3YpbacNCCTipFmUH71CSBtlaK1liJaR+PSipLi4UcZooAogH7oPFPC+9NTrUlJDZFIuTzRTpOtFACLw1SCiihAxj9aKKKAP/Z"); } }
.tl-hero__bg .hero-img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* --- Доверие в первом экране. Левый нижний угол был пуст, а разбор показал,
       что выше линии сгиба нет ни одного доказательства. Ставим официальный шильдик
       Яндекс.Бизнеса: он уравновешивает круглую кнопку записи справа, а рейтинг в нём
       живой - значит не протухнет, как протухла бы цифра в вёрстке. --- */
/* Круг записи: 100 px высотой в 30 px от низа - его центр на 80 px от края экрана.
   Шильдик 50 px центруем на ту же линию: нижняя кромка на 55 px. Отсчёт идёт от .tl-hero
   (единственный position: relative), поэтому шильдик и лежит его прямым потомком. */
/* По горизонтали шильдик центруем по кнопке «Записаться», а не по краю экрана.
   Кнопки: контейнер с полями 20 px, две равные, зазор 10 px. Значит центр левой кнопки =
   20 + (100vw - 40 - 10) / 4, а левая кромка шильдика шириной 150 = этот центр минус 75.
   Сводится к 25vw - 67.5px: на 430 даёт 40, на 390 - 30, на 360 - 22.5. */
.tl-trust { position: absolute; left: calc(25vw - 67.5px); z-index: 3;
            bottom: calc(55px + env(safe-area-inset-bottom, 0px));
            width: 150px; height: 50px; border-radius: 8px; overflow: hidden;
            box-shadow: 0 6px 22px rgba(20,17,14,.28); }
.tl-trust iframe { display: block; width: 150px; height: 50px; border: 0; }
/* На десктопе шильдика нет - решение владельца. Прячем именно медиазапросом, а не вторым
   правилом без него: два `display` на один селектор спорили бы порядком в файле. */
@media (min-width: 721px) { .tl-trust { display: none; } }

/* Короткие экраны (небольшой Android с браузерной обвязкой): при отступе сверху 176 px
   тело героя не помещается, герой перерастает видимую высоту и шильдик уходит под сгиб.
   Прижимаем содержимое к шапке - высоты хватает. */
@media (max-width: 720px) and (max-height: 700px) {
  .tl-hero { padding-top: 96px; }
}

/* Пока открыто наше меню или модалка, виджет YCLIENTS с экрана убираем совсем.
   Его крестик закрытия сидит на инлайновом z-index: 10002 и всплывал поверх шторки,
   а сама кнопка просвечивала сквозь затемнение. Модальное окно должно быть верхним слоем. */
html.drawer-open .yButton, html.drawer-open .yCloseIcon,
html.drawer-open [class*="yButton"], html.drawer-open [class*="yCloseIcon"],
html.drawer-open .ya-widget-button, html.drawer-open .yclients-widget-button {
  display: none !important;
}

/* Секция акций: белый фон и ничего позади - как на живом сайте.
   Тёплое свечение, которое проходит по остальным секциям, здесь выключено. */
.tl-sec--flat::before { display: none !important; }
.tl-promo__p small { display: block; margin-top: 2px; font-family: var(--font-body);
                     font-size: 12px; color: var(--ink-soft); }

/* --- Видео: фасад вместо плеера ---
   Кадр-подложка с кнопкой; плеер VK встаёт на её место по клику. Пропорция 16:9
   зафиксирована, чтобы подстановка iframe не двигала страницу (CLS = 0). */
.tl-video { position: relative; aspect-ratio: 16 / 9; border-radius: 20px; overflow: hidden;
            background: var(--sand); }
/* Клипы VK вертикальные (9:16): горизонтальное окно дало бы чёрные поля по бокам.
   Вертикальный режим - узкое окно по центру, как рилс. */
.tl-video--vertical { aspect-ratio: 9 / 16; max-width: min(400px, 86vw); margin-inline: auto; }
/* Знак и кнопка стоят в потоке друг под другом, а не оба по центру: при абсолютном
   центрировании кнопка накрывала слово ZAFFIRO. */
.tl-video__facade { position: absolute; inset: 0; width: 100%; height: 100%; padding: 0;
                    border: 0; cursor: pointer; display: grid; place-content: center;
                    justify-items: center; gap: clamp(18px, 2.4vw, 30px);
                    background: linear-gradient(140deg, var(--cream) 0%, var(--sand) 62%, var(--taupe) 100%); }
.tl-video__facade .zmark { opacity: .5; }
.tl-video__facade .zmark__d { width: clamp(30px, 3vw, 42px); }
.tl-video__facade .zmark__w { font-size: clamp(15px, 1.7vw, 23px); }
.tl-video__facade .zmark__s { font-size: clamp(7px, .72vw, 10px); }
.tl-video__play { z-index: 2; width: clamp(64px, 6vw, 84px); aspect-ratio: 1; border-radius: 999px;
                  background: rgba(255,255,255,.94); color: var(--tl-ink);
                  display: grid; place-items: center; box-shadow: 0 7px 15px rgba(42,38,34,.22);
                  transition: transform .3s var(--ease); }
.tl-video__play svg { width: 34%; height: auto; margin-left: 8%; }
.tl-video__hint { position: absolute; left: 50%; bottom: 18px; translate: -50% 0; z-index: 2;
                  font-family: var(--font-body); font-size: 14px; font-weight: 500; color: var(--tl-ink);
                  /* пилюля-подложка: на пёстрых постерах-стоп-кадрах подпись без неё нечитаема */
                  background: rgba(255,255,255,.85); backdrop-filter: blur(6px);
                  padding: 6px 14px; border-radius: 999px; white-space: nowrap; }
.tl-video__frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.tl-video__error { position: absolute; inset: 0; display: grid; place-items: center; padding: 24px;
                   margin: 0; text-align: center; font-family: var(--font-body); color: var(--tl-ink);
                   background: var(--sand); }
@media (hover: hover) { .tl-video__facade:hover .tl-video__play { transform: scale(1.06); } }
.tl-video__facade:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .tl-video__play { transition: none; } }

/* --- Полоса «текст + кадр» для контентных страниц ---
   У оригинала смысловые разделы идут отдельными полосами: снимок и текст рядом,
   у текста своя кнопка. Стороны чередуются (--flip), поэтому страница не читается
   под копирку - это и есть уникальность композиции вместо клонирования блоков. */
/* Нижняя граница отступа полосы - 44, а не 30: на телефоне кнопка главы («Хочу пройти
   3D диагностику») почти касалась следующего блока - владелец 27.08.2026 «прилипание
   кнопки к блоку». На широких экранах ничего не меняется, там работает 3.4vw. */
.tl-band { padding-block: clamp(44px, 3.4vw, 52px); }
/* Пропорции с боя: снимок 366, текст 750 при контейнере 1160 - то есть треть на кадр,
   две трети на текст. При 50/50 заголовок ломался на четыре строки вместо двух,
   а текст шёл узкой колонкой в двадцать строк. */
.tl-band__in { display: grid; grid-template-columns: minmax(0, 366fr) minmax(0, 750fr);
               gap: clamp(24px, 2.8vw, 44px); align-items: center; }
.tl-band--flip .tl-band__in { grid-template-columns: minmax(0, 750fr) minmax(0, 366fr); }
.tl-band--flip .tl-band__media { order: 2; }
.tl-band__media { border-radius: 20px 100px 20px 20px; overflow: hidden; aspect-ratio: 366 / 545;
                  background: var(--sand); border: 1px solid var(--gold); }
.tl-band--flip .tl-band__media { border-radius: 100px 20px 20px 20px; }
.tl-band__media > picture { display: block; width: 100%; height: 100%; }
.tl-band__media img { width: 100%; height: 100%; object-fit: cover; }
.tl-band__h { font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
              font-size: clamp(20px, 2.2vw, 28px); line-height: 1.24; color: var(--tl-ink);
              margin-bottom: 14px; text-wrap: balance; }
.tl-band__text p { font-family: var(--font-body); font-size: clamp(15px, 1.5vw, 16px);
                   line-height: 1.62; color: var(--ink-soft); text-wrap: pretty; }
.tl-band__text p + p { margin-top: 16px; }
.tl-band__text .tl-prose__h3 { margin-top: 18px; }
/* Финальная полоса - призыв: кремовый фон и крупнее набор, как у оригинала. */
.tl-band--final { background: var(--cream); }
.tl-band--final .tl-band__text p { font-size: clamp(16px, 1.7vw, 19px); color: var(--tl-ink); }
@media (max-width: 900px) {
  .tl-band__in { grid-template-columns: 1fr; }
  .tl-band__media, .tl-band--flip .tl-band__media { order: -1; border-radius: 20px 60px 20px 20px;
                                                     aspect-ratio: 4 / 3; }
  .tl-band--flip .tl-band__in { grid-template-columns: 1fr; }
}
/* Раздел без кадра - одна колонка на всю ширину контейнера. */
.tl-band--plain .tl-band__in { grid-template-columns: 1fr; }
/* Мера 62ch - только ТЕКСТОВЫМ элементам; плашки и карточки занимают всю полосу
   (на бою плашки-шаги 570px парами на контейнере 1160 - зажатые в 62ch они
   сбивались влево узкой колонкой) */
.tl-band--plain .tl-band__text { max-width: none; }
.tl-band--plain .tl-band__text > p,
.tl-band--plain .tl-band__text > h3,
.tl-band--plain .tl-band__text > ul { max-width: 62ch; }
.tl-band--plain .tl-band__text > .tl-plates { max-width: none; grid-template-columns: repeat(2, 1fr); }

/* --- Плашки-шаги «01…04» ---
   Размеры сняты с боя: плашка 570x195 при контейнере 1160, то есть две колонки
   с шагом 590 (зазор 20), заливка var(--sand), радиус 20, внутренний отступ 40.
   У последней плашки срез 100 в правом нижнем углу - тот же фирменный приём,
   что у крайних карт сертификатов на главной. */
.tl-steps__top { display: flex; align-items: flex-start; justify-content: space-between;
                 gap: clamp(16px, 3vw, 40px); margin-bottom: clamp(20px, 2.4vw, 34px); }
.tl-steps__lead { font-family: var(--font-body); font-size: 15px; line-height: 1.6;
                  color: var(--ink-soft); max-width: 62ch; }
.tl-steps { list-style: none; padding: 0; margin: 0; display: grid;
            grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--tl-gap); }
.tl-step { background: var(--sand); border-radius: 20px; padding: clamp(22px, 2.6vw, 40px); }
.tl-step:last-child { border-radius: 20px 20px 36.5% 20px / 20px 20px 52% 20px; }
.tl-step__n { display: block; font-family: var(--font-display); font-size: clamp(22px, 2.2vw, 30px);
              line-height: 1; color: var(--gold-deep); margin-bottom: 10px; }
.tl-step__t { font-family: var(--font-display); font-weight: 400; font-size: clamp(16px, 1.6vw, 18px);
              line-height: 1.3; color: var(--tl-ink); margin-bottom: 10px; text-wrap: balance; }
.tl-step__p { font-family: var(--font-body); font-size: 14px; line-height: 1.6; color: var(--ink-soft);
              text-wrap: pretty; }
@media (max-width: 720px) {
  .tl-steps { grid-template-columns: 1fr; }
  .tl-steps__top { flex-direction: column; }
  .tl-step:last-child { border-radius: 20px 20px 60px 20px; }
}

/* --- Лента живых кадров клиники с подписями (раздел трихологии, 26.08.2026) ---
   Три колонки при контейнере 1160, кадр 4:3 в золотой рамке тем же приёмом, что
   у карточек с фото в плашках; у крайнего кадра ряда фирменный срез 60. */
.tl-gal { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
          gap: var(--tl-gap); margin-top: clamp(20px, 2.4vw, 34px); }
.tl-gal__item { margin: 0; }
.tl-gal__item img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3;
                    object-fit: cover; object-position: 50% 35%; border-radius: 20px;
                    border: 1px solid var(--gold); background: var(--sand); }
/* срез - у крайнего кадра ряда, поэтому шаг привязан к числу колонок:
   на трёх колонках это каждый третий, на двух - каждый второй, на одной - только последний */
.tl-gal__item:nth-child(3n) img { border-radius: 20px 60px 20px 20px; }
.tl-gal__item:last-child img { border-radius: 20px 20px 60px 20px; }
.tl-gal__cap { font-family: var(--font-body); font-size: 13.5px; line-height: 1.5;
               color: var(--ink-soft); margin-top: 10px; text-wrap: pretty; }
@media (max-width: 900px) {
  .tl-gal { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tl-gal__item:nth-child(3n) img { border-radius: 20px; }
  .tl-gal__item:nth-child(2n) img { border-radius: 20px 60px 20px 20px; }
  .tl-gal__item:last-child img { border-radius: 20px 20px 60px 20px; }
}
@media (max-width: 560px) {
  .tl-gal { grid-template-columns: 1fr; }
  .tl-gal__item:nth-child(3n) img, .tl-gal__item:nth-child(2n) img { border-radius: 20px; }
  .tl-gal__item:last-child img { border-radius: 20px 20px 60px 20px; }
}

/* --- Лендинг: переключатели и карточки пакетов (лазерная эпиляция, 27.08.2026) ---
   На Тильде это восемь отдельных каруселей с повторяющимися карточками; у нас один
   набор данных и две оси переключения. Кнопка-пилюля в песочной обойме, выбранная -
   тёмная. Карточка: схема зон в золотой рамке, название, старая и новая цена. */
.tl-switch { display: flex; flex-wrap: wrap; gap: 12px; margin: clamp(18px, 2.2vw, 28px) 0 0; }
.tl-switch__row { display: inline-flex; gap: 4px; background: var(--sand); border-radius: 999px; padding: 4px; }
/* padding 14 - чтобы кнопка была не ниже 44px: мобильные ворота считают всё,
   что меньше 40, слишком мелкой мишенью для пальца */
.tl-switch__btn { appearance: none; border: 0; cursor: pointer; font-family: var(--font-body);
                  font-size: 14px; line-height: 1.2; padding: 14px 20px; border-radius: 999px;
                  background: transparent; color: var(--ink-soft); transition: background .25s var(--ease), color .25s var(--ease); }
.tl-switch__btn[aria-selected="true"] { background: var(--tl-ink); color: #fff; }
.tl-switch__btn:hover { color: var(--tl-ink); }
.tl-switch__btn[aria-selected="true"]:hover { color: #fff; }
.tl-packs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
            gap: var(--tl-gap); margin-top: clamp(18px, 2.2vw, 28px); }
.tl-pack { display: flex; flex-direction: column; background: var(--sand); border-radius: 20px;
           overflow: hidden; }
.tl-pack:last-child { border-radius: 20px 20px 60px 20px; }
.tl-pack__media { position: relative; background: #fff; }
.tl-pack__media img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover;
                      object-position: 50% 25%; }
.tl-pack__badge { position: absolute; top: 14px; left: 14px; z-index: 2; font-family: var(--font-body);
                  font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
                  color: #fff; background: var(--gold-deep); border-radius: 999px; padding: 6px 12px; }
.tl-pack__body { display: flex; flex-direction: column; gap: 10px; padding: 20px 22px 24px; flex: 1; }
.tl-pack__t { font-family: var(--font-display); font-weight: 400; font-size: clamp(14px, 1.35vw, 16px);
              line-height: 1.3; color: var(--tl-ink); text-transform: uppercase; letter-spacing: .02em; }
.tl-pack__price { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
                  font-family: var(--font-body); margin-top: auto; }
.tl-pack__price s { font-size: 14px; color: var(--ink-soft); }
.tl-pack__price b { font-size: clamp(19px, 2vw, 24px); font-weight: 600; color: var(--tl-ink); }
.tl-pack__unit { width: 100%; font-size: 12.5px; color: var(--ink-soft); }
.tl-pack__cta { align-self: flex-start; font-size: 13.5px; padding: 12px 22px; }
/* Абонемент - тот же комплекс, что и в блоке выше, поэтому схему зон второй раз
   не показываем: на экране это был бы повтор кадра (его ловит канон §3), а карточке
   нужнее плотность. Бейдж в таком варианте встаёт в строку с названием. */
.tl-pack--flat { justify-content: space-between; }
.tl-pack--flat .tl-pack__body { padding-top: 24px; }
.tl-pack__badge--inline { position: static; display: inline-block; margin-left: 8px; vertical-align: middle; }
@media (max-width: 900px) { .tl-packs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .tl-packs { grid-template-columns: 1fr; }
  .tl-pack__media img { aspect-ratio: 16 / 10; object-position: 50% 20%; } }

/* --- Полноширинный герой страницы (возврат макета боя, 27.08.2026) ---
   Кадр на всю ширину, заголовок и кнопки поверх него в нижней части - как было на
   Тильде. Затемнение снизу обязательно: кадры разной светлоты, а текст белый. */
/* Герой занимает первый экран целиком (клиника 28.08.2026: «на весь экран, как главная
   при входе»). Единица svh, а не vh: на телефоне vh считает высоту БЕЗ учёта адресной
   строки, и низ героя с кнопками уезжал бы под неё. Потолок 1100 - чтобы на очень
   высоких мониторах герой не превращался в полосу без содержания. */
.tl-hero-cover { position: relative; display: grid; align-items: end; overflow: hidden;
                 min-height: min(100vh, 1100px); background: var(--sand); }
@supports (height: 100svh) {
  .tl-hero-cover { min-height: min(100svh, 1100px); }
}
.tl-hero-cover__img { position: absolute; inset: 0; width: 100%; height: 100%;
                      object-fit: cover; }
/* Две вуали: снизу под заголовок, сверху под меню - шапка лежит прямо на кадре */
.tl-hero-cover__veil { position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(20,17,14,.34) 0%, rgba(20,17,14,.10) 18%,
                              rgba(20,17,14,0) 30%),
              linear-gradient(to top, rgba(20,17,14,.66) 0%, rgba(20,17,14,.34) 38%,
                              rgba(20,17,14,.10) 68%, rgba(20,17,14,0) 100%); }
/* Сила затемнения - по кадру: на светлых снимках (крупный план кожи, белый кабинет)
   белый заголовок иначе не читается. Уровень хранится в реестре hero-covers.json
   и проверяется воротами harvest/check_hero.py: контраст не ниже 4.5:1. */
.tl-hero-cover--dark .tl-hero-cover__veil {
  background: linear-gradient(to bottom, rgba(20,17,14,.46) 0%, rgba(20,17,14,.16) 20%,
                              rgba(20,17,14,0) 32%),
              linear-gradient(to top, rgba(20,17,14,.80) 0%, rgba(20,17,14,.52) 40%,
                              rgba(20,17,14,.20) 72%, rgba(20,17,14,0) 100%); }
.tl-hero-cover--darker .tl-hero-cover__veil {
  background: linear-gradient(to bottom, rgba(20,17,14,.54) 0%, rgba(20,17,14,.22) 22%,
                              rgba(20,17,14,0) 34%),
              linear-gradient(to top, rgba(20,17,14,.90) 0%, rgba(20,17,14,.66) 40%,
                              rgba(20,17,14,.32) 74%, rgba(20,17,14,.06) 100%); }
.tl-hero-cover__in { position: relative; z-index: 2;
                     padding-top: clamp(70px, 8vw, 120px);
                     padding-bottom: clamp(30px, 3.6vw, 56px); }
.tl-hero-cover__t { font-family: var(--font-display); font-weight: 400; color: #fff;
                    text-transform: uppercase; letter-spacing: .01em; text-wrap: balance;
                    font-size: clamp(26px, 3.1vw, 44px); line-height: 1.16; margin: 0; }
.tl-hero-cover__sub { margin: 14px 0 0; font-family: var(--font-body); font-weight: 500;
                      text-transform: uppercase; letter-spacing: .06em; line-height: 1.5;
                      font-size: clamp(13px, 1.1vw, 16px); color: rgba(255,255,255,.92);
                      max-width: 46ch; }
.tl-hero-cover__price { margin: 12px 0 0; font-family: var(--font-body); font-size: clamp(15px, 1.3vw, 19px);
                        color: #fff; }
.tl-hero-cover__price b { font-weight: 600; }
.tl-hero-cover__btns { display: flex; flex-wrap: wrap; gap: 12px;
                       margin-top: clamp(20px, 2.4vw, 32px); }
.tl-crumbs--light { margin-bottom: 14px; color: rgba(255,255,255,.78); }
.tl-crumbs--light a { color: rgba(255,255,255,.86); }
.tl-crumbs--light a:hover { color: #fff; }
.tl-btn--ghost { border: 1px solid rgba(255,255,255,.72); color: #fff; background: transparent; }
.tl-btn--ghost:hover { background: rgba(255,255,255,.14); border-color: #fff; }
@media (max-width: 560px) {
  /* на телефоне тот же первый экран целиком, но не ниже 520 - иначе на коротких
     экранах заголовок с кнопками сжимается в кашу */
  .tl-hero-cover { min-height: max(520px, min(100svh, 900px)); }
  .tl-hero-cover__btns { display: grid; grid-template-columns: 1fr; }
  .tl-hero-cover__btns .tl-btn { width: 100%; justify-content: center; }
}

/* --- Админ-панель (/admin/): слева разделы, справа рабочая область --- */
.ad { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: clamp(20px, 3vw, 40px); align-items: start; }
.ad__side { position: sticky; top: calc(var(--header-h, 76px) + 24px); display: grid; gap: 14px; }
.ad__who { font-family: var(--font-body); font-size: 13px; color: var(--ink-soft); margin: 0; }
.ad__nav { display: grid; gap: 6px; }
.ad__tab { appearance: none; border: 0; cursor: pointer; text-align: left; background: transparent;
           font-family: var(--font-body); font-size: 15px; color: var(--ink-soft);
           padding: 11px 14px; border-radius: 12px; min-height: 44px; }
.ad__tab:hover { background: var(--sand); color: var(--tl-ink); }
.ad__tab.is-on { background: var(--tl-ink); color: #fff; }
.ad__head { display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between;
            align-items: center; margin-bottom: 18px; }
.ad__search { font-family: var(--font-body); font-size: 16px; padding: 10px 14px; min-height: 44px;
              border: 1px solid var(--line); border-radius: 12px; background: #fff; min-width: 200px; }
.ad__rows { display: grid; gap: 10px; }
.ad__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px;
           background: var(--sand); border-radius: 14px; padding: 14px 16px; }
.ad__row--plain { display: block; font-family: var(--font-body); font-size: 14px; color: var(--ink-soft); }
.ad__row.is-changed { outline: 2px solid var(--gold-deep); }
@media (max-width: 900px) {
  .ad { grid-template-columns: minmax(0, 1fr); }
  .ad__side { position: static; }
  .ad__nav { grid-auto-flow: column; grid-auto-columns: max-content; overflow-x: auto; }
}

/* Стили кабинета акций и модерации убраны 01.09.2026 вместе со страницами:
   и кабинет, и модерацию заменила админ-панель на своём каркасе, сами страницы
   лежат в harvest/legacy/promo-pages. Ни один класс .cab-* и .pm-* больше не
   встречается ни в шаблонах, ни в скриптах. */

/* Стили студии кадров переехали в admin.css: студия теперь экран админ-панели,
   а не страница сайта, и сайту эти правила больше не нужны (01.09.2026). */

/* Служебная страница согласования акций: карточки сеткой, а не каруселью -
   на согласовании варианты должны быть видны рядом, без прокрутки */
.tl-promo-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
                 gap: var(--tl-gap); margin-top: 18px; }
@media (max-width: 900px) { .tl-promo-grid { grid-template-columns: 1fr; } }
/* пометка варианта на карточке */
.tl-promo__key { font-family: var(--font-body); font-size: 12px; font-weight: 600;
                 letter-spacing: .08em; text-transform: uppercase; color: var(--gold-deep);
                 margin: 0 0 8px; }
.tl-promo__img > img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* --- ДО / ПОСЛЕ: пара кадров в одной карточке --- */
.tl-ba { margin: 0; background: var(--sand); border-radius: 20px; padding: 14px; }
.tl-ba__pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.tl-ba__side { position: relative; border-radius: 14px; overflow: hidden; aspect-ratio: 4 / 5;
               background: var(--taupe); }
.tl-ba__side > picture { display: block; width: 100%; height: 100%; }
.tl-ba__side img { width: 100%; height: 100%; object-fit: cover; }
.tl-ba__cap { position: absolute; left: 8px; bottom: 8px; padding: 4px 10px; border-radius: 999px;
              background: rgba(255,255,255,.92); color: var(--tl-ink);
              font-family: var(--font-body); font-size: 12px; font-weight: 600; letter-spacing: .04em; }
.tl-ba__cap--after { background: var(--graphite); color: #fff; }

/* ==========================================================================
   Издательский люкс - ПИЛОТ (пакет 01, план 2026-08-12/К5).
   Скоуп .tl-izd стоит только на странице биоревитализации (procedure.njk);
   тираж на 27 процедур = включить pilotIzd в true. Глобальны здесь только
   утилиты шкалы воздуха, фолио, плашка примечания и разделители - они
   инертны, пока их классы не выведены в разметку. */

/* Шкала воздуха: 4 ступени вместо россыпи инлайнов (Горбунов, правило 14) */
.tl-mt-1 { margin-top: 12px; }
.tl-mt-2 { margin-top: 20px; }
.tl-mt-3 { margin-top: 36px; }
.tl-mt-4 { margin-top: 56px; }

/* Мера набора и журнальный лид (Брингхерст: 45-75 знаков в строке) */
.tl-izd .tl-prose { max-width: 62ch; }
.tl-izd .tl-prose__lead { font-size: clamp(19px, 1.9vw, 22px); line-height: 1.55; }
.tl-izd .tl-prose p { margin-top: 16px; }

/* Фолио главы: номер Tenor золотом текста + золотая линия. Трекинг только
   на цифрах номера - на строчные Tenor он не распространяется. */
.tl-prose__ch { display: flex; align-items: center; gap: 12px; margin: 56px 0 10px; }
.tl-prose__ch b { font-family: var(--font-display); font-weight: 400; font-size: 15px;
                  letter-spacing: .08em; color: var(--gold-deep); }
.tl-prose__ch::after { content: ""; width: 36px; height: 1px; background: var(--gold); }
.tl-prose__ch + .tl-prose__h, .tl-prose__ch + .tl-head { margin-top: 0; }

/* Якоря «Содержания» не ныряют под липкую шапку */
.tl-izd [id] { scroll-margin-top: calc(var(--header-h, 72px) + 20px); }

/* Прайс-канон: имя + отточие по базовой линии + цена Tenor Sans. Золотой
   круг-стрелка вплывает на ховере и существует только там, где есть мышь. */
.tl-izd .tl-rows--menu a { align-items: baseline; }
.tl-izd .tl-rows--menu a:hover { padding-left: 0; }
.tl-izd .tl-rows--menu .n { font-size: 15px; line-height: 1.45; }
.tl-izd .tl-rows--menu .dots { flex: 1; min-width: 32px; align-self: auto;
                               border-bottom: 1px dotted var(--taupe, #cabfb4);
                               transform: translateY(-4px); }
.tl-izd .tl-rows--menu .pr { font-family: var(--font-display); font-size: 17px;
                             color: var(--tl-ink); white-space: nowrap; }
.tl-izd .tl-rows--menu .go { display: none; }
@media (hover: hover) and (pointer: fine) {
  .tl-izd .tl-rows--menu .go { width: 34px; height: 34px; border-radius: 999px;
    background: var(--gold); flex: none; align-self: center; display: grid;
    place-items: center; opacity: 0; transform: translateX(-8px);
    transition: opacity .25s ease, transform .25s var(--ease); }
  .tl-izd .tl-rows--menu .go svg { width: 14px; height: 14px; }
  .tl-izd .tl-rows--menu a:hover .go { opacity: 1; transform: none; }
}

/* Канон примечания-плашки: обязательный мелкий текст полного контраста
   на песке (Штанг, правило 23), не серое извинение */
.tl-note--band { display: block; font-family: var(--font-body); background: var(--sand);
                 border-radius: 12px; padding: 13px 18px; font-size: 13.6px;
                 line-height: 1.45; letter-spacing: .012em; color: var(--tl-ink); }

/* Наборные знаки: ромб-разделитель между зонами статьи и концевой знак */
.tl-div { display: flex; align-items: center; gap: 16px; margin: 56px 0; }
.tl-div::before, .tl-div::after { content: ""; flex: 1; height: 1px; background: rgba(42,38,34,.14); }
.tl-div i, .tl-fin i { width: 9px; height: 9px; border: 1px solid var(--gold);
                       transform: rotate(45deg); flex: none; }
.tl-fin { display: flex; justify-content: center; margin-top: 56px; }

/* «Содержание» в правом рейле: карточка под липкой карточкой записи.
   Активная глава подсвечивается только цветом. На мобиле рейла нет. */
.tl-toc { margin-top: 20px; background: var(--surface); border: 1px solid rgba(42,38,34,.1);
          border-radius: 20px; padding: 22px 24px; }
.tl-toc ol { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; }
.tl-toc a { display: flex; gap: 12px; align-items: baseline; padding: 8px 0; text-decoration: none;
            font-family: var(--font-body); font-size: 13.5px; line-height: 1.4;
            color: var(--ink-soft); transition: color .2s; }
.tl-toc a b { font-family: var(--font-display); font-weight: 400; font-size: 13px;
              letter-spacing: .06em; color: var(--gold); flex: none; transition: color .2s; }
.tl-toc a:hover, .tl-toc li.is-active a, .tl-toc li.is-active a b { color: var(--gold-deep); }
@media (max-width: 980px) { .tl-toc { display: none; } }

/* Выносная цитата - единственный центрированный блок статьи (Штанг: центр
   только коротким блокам с ручными переносами). Акцент строкой цвета. */
.tl-pull { margin: 0 auto; max-width: 820px; text-align: center; padding: 8px 0; }
.tl-pull::before { content: ""; display: block; width: 56px; height: 1px;
                   background: var(--gold); margin: 0 auto 26px; }
.tl-pull blockquote { margin: 0; font-family: var(--font-display);
                      font-size: clamp(20px, 2.1vw, 27px); line-height: 1.5; color: var(--tl-ink); }
.tl-pull .gold { color: var(--gold-deep); }
.tl-pull figcaption { margin-top: 18px; font-family: var(--font-body); font-size: 12px;
                      letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); }
@media (max-width: 640px) { .tl-pull blockquote br { display: none; } }

/* --- Полосы «текст + кадр» страницы процедуры (ритм боя, паттерн №1 каталога К1) --- */
.tl-pb { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 420px);
           gap: clamp(28px, 4vw, 72px); align-items: start; margin-top: 56px; }
.tl-pb:first-child { margin-top: 8px; }
.tl-pb--reverse { grid-template-columns: minmax(300px, 420px) minmax(0, 1fr); }
.tl-pb--reverse .tl-pb__text { order: 2; }
.tl-pb--reverse .tl-pb__media { order: 1; }
/* Кадр ЗАКРЕПЛЯЕТСЯ и едет вместе с прокруткой длинного текста - как карточка записи
   в рейле. Только десктоп: на телефоне колонки стопкой и закреплять нечего. */
@media (min-width: 861px) {
  .tl-pb__media { position: sticky; top: calc(var(--header-h, 72px) + 24px); }
  .tl-season__split { align-items: start; }
  .tl-season__media { position: sticky; top: calc(var(--header-h, 72px) + 24px); }
}
/* Кремовая лента второй полосы - карточной плоскостью, страница остаётся белой */
.tl-pb--cream { background: var(--cream); border-radius: 20px 100px 20px 20px;
                  padding: clamp(24px, 3.4vw, 48px); }
.tl-pb__text { max-width: 62ch; font-family: var(--font-body); font-size: 16px;
                 line-height: 1.7; color: var(--tl-ink); }
.tl-pb__text p { margin-top: 16px; }
.tl-pb__cta { margin-top: 24px; }
/* Подзаголовок-вопрос внутри полосы - ступень тише главы, Tenor без капса (как на бою) */
.tl-pb__sub { font-family: var(--font-display); font-size: 18px; line-height: 1.35;
                margin-top: 24px; color: var(--tl-ink); }
/* Перечисление с фирменными ромбами: контурный ромб вместо буллета */
.tl-dlist { list-style: none; padding: 0; margin: 16px 0 0; display: flex;
            flex-direction: column; gap: 10px; }
.tl-dlist li { position: relative; padding-left: 26px; }
.tl-dlist li::before { content: ""; position: absolute; left: 2px; top: .5em;
                       width: 7px; height: 7px; border: 1px solid var(--gold);
                       transform: rotate(45deg); }
/* Вехи «Через N: ...»: залитый ромб + нить между вехами */
.tl-timeline { list-style: none; padding: 0; margin: 16px 0 0; display: flex;
               flex-direction: column; gap: 14px; }
.tl-timeline li { position: relative; padding-left: 26px; }
.tl-timeline li::before { content: ""; position: absolute; left: 2px; top: .5em;
                          width: 7px; height: 7px; background: var(--gold);
                          transform: rotate(45deg); }
.tl-timeline li:not(:last-child)::after { content: ""; position: absolute; left: 6px;
                          top: calc(.5em + 14px); bottom: -14px; width: 1px;
                          background: var(--line-strong, #dccdbb); }
.tl-timeline b { font-weight: 600; }
/* Рамка кадра: радиус, обрезка и ПРОПОРЦИЯ на контейнере (канон обёртки picture,
   см. комментарий у .tl-tile) - снимок заполняет рамку и движется внутри (параллакс) */
.tl-pb__media--img { border-radius: 20px 100px 20px 20px; overflow: hidden; aspect-ratio: 3 / 4; }
/* Кадр главы не выше своего текста. Пропорция 3:4 задавала высоту сама по себе, и
   у короткой главы под текстом зияла пустая половина экрана (владелец 27.08.2026:
   «фото не обрезается - пустое место»). Теперь высоту диктует текстовая колонка,
   но не больше прежнего максимума 560 - на длинных главах вид не меняется,
   кадр по-прежнему кадрируется по границам и едет с прокруткой. */
@media (min-width: 901px) {
  .tl-pb { align-items: stretch; }
  .tl-pb__media--img { aspect-ratio: auto; height: 100%; min-height: 320px; max-height: 560px; }
  .tl-pb__media--img > picture { height: 100%; }
}
/* Горизонтальные исходники (16:9 стоп-кадры боя) в портретной рамке резались по глазам -
   таким полосам рамка 3:2 (флаг wide в procpage.json ставится кадрам с соотношением >=1.6). */
.tl-pb__media--wide { aspect-ratio: 3 / 2; }
.tl-pb__media--img > picture { display: block; width: 100%; height: 100%; }
.tl-pb__media--img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tl-pb--reverse .tl-pb__media--img { border-radius: 20px 20px 20px 100px; }
.tl-video--inband { width: 100%; max-width: 400px; }
/* Фасад с постером: кадр вместо фирменного градиента, скрим для читаемости кнопки */
.tl-video__facade--poster { background-size: cover; background-position: center top; }
.tl-video__facade--poster::before { content: ""; position: absolute; inset: 0;
    background: linear-gradient(to top, rgba(27,24,21,.44) 0%, rgba(27,24,21,.10) 40%, rgba(27,24,21,0) 70%); }
.tl-video__facade--poster .tl-video__play, .tl-video__facade--poster .tl-video__hint { position: relative; }
@media (max-width: 860px) {
  .tl-pb, .tl-pb--reverse { grid-template-columns: 1fr; }
  /* width: 100% + justify-self, а НЕ margin-inline: auto: авто-поля на грид-элементе
     переводят его ширину в «по содержимому», а окно с aspect-ratio ждёт ширину
     от родителя - взаимная блокировка схлопывала видео в 0px. */
  .tl-pb__media, .tl-pb--reverse .tl-pb__media { order: 1; width: 100%; max-width: 400px; justify-self: center; }
  .tl-pb__text, .tl-pb--reverse .tl-pb__text { order: 2; }
}

/* --- Сезонность: четыре песочные плашки 2x2 + текст с кадром + мессенджеры (по бою) --- */
.tl-season { margin-top: 56px; }
.tl-season__cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-top: 22px; }
.tl-season__card { background: var(--sand); border-radius: 20px; padding: 26px 28px;
                   font-family: var(--font-body); color: var(--tl-ink); }
.tl-season__card--cut { border-radius: 20px 20px 100px 20px; }
.tl-season__card b { display: block; font-weight: 600; font-size: 15px; margin-bottom: 8px; }
.tl-season__card p { margin: 0; font-size: 15px; line-height: 1.55; color: var(--ink-soft); }
.tl-season__split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 460px);
                    gap: clamp(28px, 4vw, 64px); align-items: center; margin-top: 36px; }
.tl-season__intro { font-family: var(--font-body); font-size: 16px; line-height: 1.6; color: var(--tl-ink); }
.tl-season__cta { margin-top: 18px; font-family: var(--font-body); font-weight: 600; color: var(--tl-ink); }
.tl-season__msg { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 18px; }
.tl-season__media { border-radius: 20px 20px 20px 100px; overflow: hidden; aspect-ratio: 3 / 2; }
.tl-season__media > picture { display: block; width: 100%; height: 100%; }
.tl-season__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 860px) {
  .tl-season__cards { grid-template-columns: 1fr; }
  .tl-season__split { grid-template-columns: 1fr; }
  .tl-season__media { max-width: 460px; }
}

/* Самохост-ролик в окне: чёрный фон на случай микрополей у кодека */
.tl-video__frame--file { object-fit: cover; background: #000; }

/* Пилюля услуги в окне записи: видно, НА ЧТО записываешься (Консьерж, п.1) */
.modal__service { display: inline-block; background: var(--sand); color: var(--tl-ink);
                  font-family: var(--font-body); font-size: 13.5px; font-weight: 600;
                  border-radius: 999px; padding: 7px 16px; margin: 2px 0 6px; }

/* Заголовок группы прайса («Женский прайс», «Лицо»...) - тихий капс с золотой линией */
.tl-rows__group { font-family: var(--font-body); font-size: 12.5px; font-weight: 600;
                  letter-spacing: .14em; text-transform: uppercase; color: var(--gold-deep);
                  margin: 28px 0 4px; display: flex; align-items: center; gap: 12px; }
.tl-rows__group::after { content: ""; width: 36px; height: 1px; background: var(--gold); }
.tl-rows__group:first-child { margin-top: 4px; }

/* Карточки показаний/противопоказаний на страницах процедур - ровные скругления,
   как на бою (словарь радиусов боя: карточки 18-30). Срез 100px был нашей выдумкой
   и съедал длинные списки в нижнем углу («текст выходит из плашки»). */
.tl-izd .tl-card, .tl-izd .tl-card--flip { border-radius: 20px; }

/* CTA-вставка боя («оставить заявку», «этот уход только у нас»): песочная капсула,
   срез справа-снизу - за кнопкой, текст всегда на прямой кромке */
.tl-ctab { background: var(--sand); border-radius: 20px 20px 100px 20px;
           padding: clamp(28px, 4vw, 46px) clamp(24px, 4vw, 52px);
           display: grid; grid-template-columns: minmax(0, 1fr) auto;
           gap: clamp(18px, 3vw, 40px); align-items: center; }
.tl-ctab__t { font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
              font-size: clamp(19px, 2vw, 26px); line-height: 1.3; color: var(--tl-ink);
              letter-spacing: .02em; max-width: 30ch; }
.tl-ctab__p { font-family: var(--font-body); font-size: 15px; line-height: 1.55;
              color: var(--ink-soft); margin-top: 10px; max-width: 56ch; }
.tl-ctab__btns { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
.tl-ctab__btns .tl-btn { text-align: center; }
@media (max-width: 720px) {
  .tl-ctab { grid-template-columns: 1fr; border-radius: 20px 20px 60px 20px; }
  .tl-ctab .tl-btn, .tl-ctab__btns { justify-self: start; }
  .tl-ctab__btns { align-items: flex-start; }
}

/* «Наши гарантии»: строки-ромбы + фото с боя в фирменной рамке */
.tl-guar { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 400px);
           gap: clamp(28px, 4vw, 72px); align-items: start; }
.tl-guar .tl-dlist { margin-top: 22px; max-width: 62ch; }
.tl-guar__cta { font-family: var(--font-body); font-size: 16px; line-height: 1.55;
                color: var(--tl-ink); max-width: 62ch; }
@media (max-width: 860px) {
  .tl-guar { grid-template-columns: 1fr; }
  .tl-guar .tl-pb__media { width: 100%; max-width: 400px; justify-self: center; }
}

/* Пары плашек боя внутри глав («Акт 1/Акт 2», критерии, шаги): песочные карточки,
   у последней фирменный срез - тот же словарь, что у сезонности биорева */
.tl-plates { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; margin-top: 20px; }
.tl-plates__card { background: var(--sand); border-radius: 20px; padding: 22px 24px;
                   font-family: var(--font-body); color: var(--tl-ink); }
.tl-plates__card--cut { border-radius: 20px 20px 100px 20px; }
.tl-plates__card b { display: block; font-weight: 600; font-size: 15px; margin-bottom: 8px; }
.tl-plates__card p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); }
.tl-plates__card p + p { margin-top: 6px; }
/* внутри узкой колонки полосы - одним столбцом */
.tl-pb__text .tl-plates { grid-template-columns: 1fr; }
/* примечание сразу после сетки плашек: без этого оно прилипало к нижней плашке
   и вставало по ширине текстовой колонки - читалось как оборванная седьмая плашка.
   Селектор длиннее нужного намеренно: правило ширины колонки
   (.tl-band--plain .tl-band__text > p) специфичнее короткого варианта */
.tl-plates + .tl-note--band { margin-top: 14px; }
.tl-band--plain .tl-band__text > .tl-plates + .tl-note--band { max-width: none; }
/* Мобильное схлопывание указано с запасом специфичности: правило полосы-без-кадра
   (.tl-band--plain ... repeat(2,1fr)) иначе перебивает его и плашки вылетают за экран. */
@media (max-width: 640px) {
  .tl-plates, .tl-band--plain .tl-band__text > .tl-plates { grid-template-columns: 1fr; }
}

/* ============ Страницы направлений: канон боя (эталон снят 2026-08-14) ============ */
/* Секции «специалисты», «вопросы», «отзывы» на бою стоят на тёплом фоне #f9f5f2,
   а не на белом - иначе песочные карточки не читаются как карточки. */
#specialisty.tl-sec, #voprosy.tl-sec, #otzyvy.tl-sec { background: var(--cream); }

/* Карточка врача: подпись глубже от края, мягче затемнение, кнопка ВНУТРИ карточки */
.tl-docc { position: relative; }
/* подпись стоит НАД кнопкой (кнопка занимает нижние 70px карточки) */
.tl-docc .tl-doc__cap { left: clamp(20px, 3vw, 48px); right: clamp(20px, 3vw, 48px); bottom: 92px; }
.tl-doc__n { font-size: clamp(16px, 1.5vw, 20px); line-height: 1.15; letter-spacing: 0; text-wrap: initial; }
/* Затемнение карточки В КАРУСЕЛИ - отдельным селектором, а не повтором `.tl-doc::after`:
   раньше это правило перебивало базовое (тот же селектор ниже по файлу), и подпись
   получала контраст 3,3:1 вместо 6+. Подпись тут стоит выше (bottom: 92px, над
   кнопкой), поэтому затемнение поднимается до 60% высоты кадра. */
.tl-docc .tl-doc::after { inset: 0;
  background: linear-gradient(to top, rgba(20,17,14,.90) 0%, rgba(20,17,14,.74) 38%,
                              rgba(20,17,14,.30) 62%, rgba(20,17,14,0) 84%); }
/* кнопка лежит на нижней кромке фото, уже карточки на 11px с каждой стороны (бой) */
.tl-docc__cta { position: absolute; left: 11px; right: 11px; bottom: 14px; z-index: 3;
                min-height: 56px; display: grid; place-items: center; border-radius: 30px; }
@media (max-width: 720px) { .tl-docc__cta { min-height: 50px; } }

/* Подводка над рядом мессенджеров в главе */
.tl-band__msglead { font-family: var(--font-body); font-size: 15px; line-height: 1.55;
                    color: var(--tl-ink); margin-top: 22px; }

/* Мессенджеры значками (правка клиники 17.08.2026: «только значки, без названий»).
   Ряд идёт строкой: подпись слева, значки справа; на узком экране переносится.
   Кликабельная зона 44x44 при значке 24 - меньше пальцем не попасть.
   Цвет через currentColor, поэтому один и тот же значок работает и на креме,
   и на тёмной плашке (модификатор --light). */
.tl-msgrow { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; margin-top: 0; margin-left: -8px; }
.tl-msgrow__label { font-family: var(--font-body); font-size: 15px; line-height: 1.45; color: var(--tl-ink); }
/* В подвале ряд идёт прямо под строкой «Мы на Яндекс.Картах» - без подписи он не должен
   висеть в стороне, поэтому отступ меньше и значки прижаты к левому краю колонки. */
.tl-foot .tl-msgrow { margin-top: 8px; gap: 2px; }
/* -8px гасит внутреннее поле кружка 44x44 вокруг значка 28x28: без компенсации ряд
   стоит с уступом относительно строк контактов над ним. */
.tl-msgrow__icons { display: inline-flex; align-items: center; gap: 2px; }
/* Селектор с тегом: в подвале и в шторке цвет ссылок задан правилами вида
   «.tl-foot a», они специфичнее одного класса и перекрашивали значки в тёмный. */
/* Значки в фирменных цветах площадок (владелец 26.08.2026: «сделай реальные иконки,
   как они есть»). Раньше они были монохромно-золотыми под палитру сайта, но узнаваемость
   мессенджера важнее: голубой круг Telegram и сине-фиолетовый знак MAX читаются мгновенно.
   Зона касания остаётся 44x44 - сам значок 28. */
.tl-msgrow a.tl-msgrow__ico { display: inline-grid; place-items: center; width: 44px; height: 44px;
                  border-radius: 50%; text-decoration: none; border: 0;
                  transition: transform .18s ease, opacity .18s ease; }
.tl-msgrow a.tl-msgrow__ico:hover { transform: translateY(-1px); opacity: .85; }
.tl-msgrow__svg { width: 28px; height: 28px; display: block; }
.tl-msgrow__word { font-size: 14px; color: currentColor; }   /* запасной вид: площадка без значка */
.tl-msgrow--light .tl-msgrow__label { color: rgba(255,255,255,.86); }
.tl-msgrow--light a.tl-msgrow__ico:hover { opacity: 1; }
@media (max-width: 720px) { .tl-msgrow { gap: 4px 10px; } }  /* зона касания остаётся 44x44 - меньше пальцем не попасть */

/* Вопросы-ответы: кадр в золотой рамке (бой), строки без тени, зазор 20 */
.tl-faq__media { border: 2px solid var(--gold); padding: 0; }
.tl-faq--cards { gap: 20px; }
.tl-faq--cards details { box-shadow: none; padding: 25px 30px; }
.tl-faq--cards summary { font-size: 16px; line-height: 1.35; color: #232323; }
.tl-faq--cards summary::after { color: #222; font-size: 28px; font-weight: 200; }

/* Отзывы: имя антиквой сверху карточки */
.tl-review__who { font-size: 18px; line-height: 1.17; }

/* Заголовок внутри плашки показаний - как на бою: Tenor 30px с двоеточием,
   вместо мелкого ярлыка-капса (на страницах направлений) */
.tl-card__h { font-family: var(--font-display); font-weight: 400; text-transform: uppercase;
              font-size: clamp(20px, 2vw, 30px); line-height: 1.17; color: var(--tl-ink);
              letter-spacing: 0; margin: 0 0 6px; }

/* ======== Канон боя: паспарту, выравнивание полос, подписи врачей (2026-08-14) ========
   1. Тонкий ЗОЛОТОЙ КАНТ вокруг каждого кадра и видео. На бою это не рамка, а подложка
      с золотым градиентом: обёртка 371x560 с радиусом 20/100/20/20, снимок внутри
      367x556 с радиусом на 2 меньше - разница в 2px и читается как кант. */
.tl-band__media, .tl-consult__media, .tl-faq__media,
.tl-pb__media--img, .tl-video--inband, .tl-season__media {
  background: linear-gradient(150deg, #c49b68 0%, #f3ddbc 48%, #c49b68 100%);
  padding: 2px;
  /* box-sizing обязателен: у грид-элементов эти 2px иначе прибавляются К ширине трека
     и полоса вылезает за экран (матрица поймала +4px на 4 страницах) */
  box-sizing: border-box; max-width: 100%;
}
.tl-band__media > picture, .tl-band__media img,
.tl-consult__media > picture, .tl-consult__media img,
.tl-faq__media > picture, .tl-faq__media img,
.tl-pb__media--img > picture, .tl-pb__media--img img,
.tl-season__media > picture, .tl-season__media img {
  border-radius: inherit;
}
.tl-faq__media { border: 0; }                      /* кант рисует подложка, отдельная рамка не нужна */
/* видео - не голый прямоугольник: те же скругления и кант, что у кадров */
.tl-video--inband { border-radius: 20px 100px 20px 20px; overflow: hidden; }
.tl-pb--reverse .tl-video--inband,
.tl-band--flip .tl-video--inband { border-radius: 100px 20px 20px 20px; }
.tl-video--inband .tl-video__facade { border-radius: inherit; }

/* 2. Полоса «текст + кадр»: верх и низ ровные. Кадр тянется на высоту текстовой
      колонки и кадрируется по границам (object-fit: cover), а не живёт своей высотой.
      Если текста много - кадр закрепляется и едет вместе с прокруткой (как на биорев). */
.tl-band__in { align-items: stretch; }
.tl-band__media { align-self: stretch; height: 100%; min-height: 320px; }
/* На широком экране высоту кадра задаёт текст, а не пропорция 366:545: иначе при
   короткой главе кадр вытягивал строку сетки и под текстом зияла пустота
   (владелец 27.08.2026: «фото не обрезается - пустое место»). Кадр кадрируется
   по границам, cover уже задан ниже. На телефоне пропорция остаётся - там кадр
   стоит над текстом и своей высоты не имеет. */
@media (min-width: 901px) { .tl-band__media { aspect-ratio: auto; } }
.tl-band__media img { width: 100%; height: 100%; object-fit: cover; }
@media (min-width: 900px) {
  .tl-band__media { position: sticky; top: calc(var(--header-h, 72px) + 24px);
                    max-height: calc(100vh - var(--header-h, 72px) - 48px); }
}
/* кнопка главы прижата к низу текстовой колонки - тогда низ текста и низ кадра сходятся */
.tl-band__text { display: flex; flex-direction: column; }
.tl-band__text > :last-child { margin-bottom: 0; }

/* 3. Показания: список идёт СВЕРХУ, а не центруется - иначе в одной плашке текст
      от края, в соседней с середины (фидбек владельца). */
.tl-ticks { margin-block: 0; }
.tl-ticks__lead + .tl-ticks { margin-block: 10px 0; }

/* 5. Врачи: подписи на одной высоте у всех карточек ряда - роль занимает две строки
      даже когда текст в одну (иначе ФИО «пляшет» по вертикали). */
/* Подписи карточек на одной высоте: правило было заскоплено на карусель, и на
   странице «Наша команда» ФИО плясали по вертикали (у кого должность в одну строку,
   у кого в две). Скоуп снят - в карусели значение то же. */
.tl-doc__r { min-height: 2.8em; }

/* Маркированный список внутри песочной плашки (бой: ul > li с точками).
   Точка золотая - фирменная, но именно точка, а не ромб: так на оригинале. */
.tl-plates__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
.tl-plates__list li { position: relative; padding-left: 20px; font-size: 14.5px;
                      line-height: 1.55; color: var(--ink-soft); }
.tl-plates__list li::before { content: ""; position: absolute; left: 4px; top: .62em;
                              width: 6px; height: 6px; border-radius: 50%;
                              background: var(--gold-deep); }

/* ================= Мобильная доводка (фидбек владельца 2026-08-14) ================= */
@media (max-width: 720px) {
  /* 1. Карусели - РОВНО ОДНА карточка на экран. Раньше вторая лезла в кадр
        обрезанной («пытаются влезть 2») - на телефоне это читается как поломка. */
  .tl-rail--3 > *, .tl-rail--4 > * { width: calc(100vw - 2 * var(--tl-pad, 20px)); max-width: 340px; }
  .tl-rail { scroll-padding-inline: var(--tl-pad, 20px); }

  /* 2. Видео целиком помещается в экран: вертикальный клип 9:16 при ширине 344
        давал 612px высоты и уезжал под нижнюю панель вместе с кнопкой паузы.
        Ограничиваем высотой видимой области за вычетом шапки и липкой панели. */
  /* высоту вертикального клипа держит пропорция 9/16, поэтому ограничиваем ИМЕННО
     высоту, а ширину считаем от неё - иначе окно 612px уезжает под липкую панель
     вместе с кнопкой паузы, и ролик «нельзя остановить» */
  .tl-video--inband.tl-video--vertical {
    height: min(58svh, 520px); width: auto; max-width: 100%;
    aspect-ratio: 9 / 16; margin-inline: auto;
  }
  .tl-video--inband video { width: 100%; height: 100%; object-fit: contain; background: #000; }

  /* 3. Портрет врача кадрируется выше - на 3:4 макушка подрезалась */
  .tl-doc img { object-position: 50% 10%; }
}

/* Доводка по фидбеку 2026-08-14 (вечер) */
/* FAQ: кадр тянется на высоту аккордеона - низ блока ровный (верх и так совпадал) */
.tl-faq-split { align-items: stretch; }
.tl-faq__media { aspect-ratio: auto; height: 100%; min-height: 240px; }
/* Подводка к мессенджерам - капсом, как на бою */
.tl-band__msglead { text-transform: uppercase; letter-spacing: .04em; font-size: 14px; }
/* Полоса с видео: паспарту и размер держит САМО видео-окно, обёртка прозрачная.
   Иначе рамка обёртки (min-height 320) и окно клипа (490) конфликтуют, и на телефоне
   вокруг ролика вылезали золотые поля - «видео обрезано». */
.tl-band__media--video { background: none; padding: 0; min-height: 0; height: auto;
                         aspect-ratio: auto; align-self: start; display: grid;
                         justify-items: center; overflow: visible; }
@media (min-width: 900px) { .tl-band__media--video { position: static; } }

/* Карточки вопросов не растягиваются по высоте колонки - они по содержимому,
   а кадр слева тянется под них (иначе внутри пилюль появлялась пустота). */
.tl-faq--cards { align-content: start; }
.tl-faq--cards details { height: fit-content; }

/* Высоту ряда задаёт АККОРДЕОН, кадр её заполняет: иначе портретный снимок
   растягивал блок на свою натуральную высоту (652px против 277px у вопросов).
   Снимок позиционируется абсолютно, поэтому в расчёт высоты строки не входит. */
.tl-faq__media { position: relative; height: 100%; min-height: 220px; }
.tl-faq__media > picture, .tl-faq__media > img { position: absolute; inset: 2px;
  width: calc(100% - 4px); height: calc(100% - 4px); }

/* Плеер садится ВНУТРЬ канта: position:absolute с inset:0 игнорирует padding обёртки,
   поэтому видео наезжало на золотую рамку и выглядело сдвинутым/обрезанным. */
.tl-video--inband video, .tl-video--inband .tl-video__frame {
  position: absolute; inset: 2px; width: calc(100% - 4px); height: calc(100% - 4px);
  object-fit: cover; border-radius: 18px 98px 18px 18px; background: #000;
}
.tl-pb--reverse .tl-video--inband video, .tl-band--flip .tl-video--inband video {
  border-radius: 98px 18px 18px 18px;
}

/* Ограничение ширины вертикального клипа - ГЛОБАЛЬНОЕ, а не только на телефоне:
   общее правило паспарту (max-width: 100%) перебивало базовое min(400px, 86vw),
   и на планшетных ширинах 721-899px окно раздувалось во всю колонку (726x1291). */
.tl-video--inband.tl-video--vertical { max-width: min(400px, 86vw); }

/* Старая рамка 1px у медиа-обёрток снимается: кант теперь рисует подложка-паспарту,
   а две линии подряд (border + паспарту) читались как «видео не в контейнере». */
.tl-band__media, .tl-band__media--video, .tl-consult__media, .tl-faq__media,
.tl-pb__media--img, .tl-season__media { border: 0; }

/* Видео в полосе ведёт себя КАК КАДР: занимает всю ширину своей колонки, а не стоит
   узким окном по центру (фидбек владельца: «должно быть по ширине текста/рамки»).
   На одноколоночной раскладке колонка широкая - ролик заполняет её и кадрируется
   по рамке (object-fit: cover), пропорция портретная 3:4, как у кадров полос. */
@media (max-width: 899px) {
  .tl-band__media--video { width: 100%; }
  /* Обёртке ролика пропорцию не навязываем: высоту задаёт само видео 9:16.
     Правило «.tl-band__media, .tl-band--flip .tl-band__media { aspect-ratio: 4/3 }»
     специфичнее одноклассового и держало обёртку на 263 px, тогда как ролик внутри
     занимает 622 px - он вылезал вниз на 374 px и ложился поверх заголовка главы и
     первых абзацев: на телефоне текст было физически не прочитать (найдено приёмкой
     02.09.2026 на /3d-diagnostika-kozhi/). Перечисляем оба селектора, чтобы обойти
     специфичность, а не поднимать её !important-ом. */
  .tl-band__media--video,
  .tl-band--flip .tl-band__media--video {
    aspect-ratio: auto; height: auto; min-height: 0;
  }
  /* Телефон: ролик во всю ширину колонки и в РОДНОЙ пропорции 9:16 - ничего не режем,
     он занимает почти весь экран, как рилс. Небольшой отступ сверху отделяет его
     от кнопки предыдущего блока. */
  .tl-video--inband.tl-video--vertical {
    max-width: none; width: 100%; height: auto; aspect-ratio: 9 / 16;
    max-height: none; margin-inline: 0; margin-top: 14px;
  }
  .tl-video--inband video { object-fit: cover; }
}

/* Планшет (721-899): во всю ширину колонки ролик 9:16 дал бы 1294px высоты -
   ограничиваем ширину, пропорция остаётся родной. */
@media (min-width: 721px) and (max-width: 899px) {
  .tl-video--inband.tl-video--vertical { max-width: 420px; }
}

/* Блок вопросов без кадра (страницы процедур, где кадра нет) - одна колонка */
.tl-faq-split--solo { grid-template-columns: minmax(0, 1fr); max-width: 860px; }

/* ===== Перепись боя (2026-08-15): пилюли-зоны, акционная строка прайса, лид врача ===== */

/* Карточки-пилюли боя: «Зоны применения контурной пластики», «Какие проблемы решает» */
.tl-pills { list-style: none; margin: 18px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 10px; }
.tl-pills li { background: var(--sand); border-radius: 100px; padding: 11px 20px;
  font-size: 14.5px; line-height: 1.35; color: var(--ink); }
@media (max-width: 640px) { .tl-pills li { font-size: 14px; padding: 10px 16px; } }

/* Акционная строка прайса (на бою это строка таблицы, а не сноска) */
.tl-rows__promo .tl-rows__label { display: inline-block; background: var(--gold);
  color: #fff; font-family: var(--font-body); font-size: 11px; letter-spacing: .08em;
  text-transform: uppercase; border-radius: 100px; padding: 4px 10px; margin-right: 10px;
  vertical-align: middle; font-weight: 600; }
.tl-rows__promo u s { color: var(--ink-soft); opacity: .7; margin-left: 8px;
  font-size: .86em; text-decoration: line-through; }

/* Глава БЕЗ кадра (перепись боя: «Зоны коррекции», «Как работает RSL», «Два акта»):
   текст держит меру, а плашки и пилюли идут во всю ширину блока, как на бою */
.tl-izd .tl-prose > .tl-plates,
.tl-izd .tl-prose > .tl-pills { max-width: none; width: 100%; }
.tl-izd .tl-prose { max-width: none; }
.tl-izd .tl-prose > p,
.tl-izd .tl-prose > h2,
.tl-izd .tl-prose > h3,
.tl-izd .tl-prose > .tl-prose__ch { max-width: 62ch; }
/* Список в главе без кадра занимает вторую половину ширины: строка списка короткая,
   и в одну колонку справа оставалась пустота во весь экран (замечание владельца
   26.08.2026 про страницу консультации трихолога). Абзацы по-прежнему держат меру
   чтения - их в две колонки ломать нельзя, глаз теряет строку.
   На узком экране колонка одна: правило включается только от 901 px. */
.tl-izd .tl-prose > ul:not(.tl-pills) { max-width: 62ch; }
@media (min-width: 901px) {
  /* Список размечен флексом (.tl-dlist), а многоколоночная вёрстка на флекс-контейнер
     не действует - поэтому раскладываем сеткой в две колонки. Пункты короткие, в одну
     колонку справа оставалось пустое поле во весь экран. */
  .tl-izd .tl-prose__ch > ul.tl-dlist,
  .tl-izd .tl-prose > ul.tl-dlist {
    /* display: block обязателен: список размечен флексом, а многоколоночная вёрстка
       на флекс-контейнер не действует. Сетку не берём - она раскладывает пункты
       построчно («змейкой»), а список читают сверху вниз по колонке. */
    max-width: none; display: block; columns: 2; column-gap: clamp(32px, 4vw, 64px);
  }
  .tl-izd .tl-prose__ch > ul.tl-dlist li,
  .tl-izd .tl-prose > ul.tl-dlist li { break-inside: avoid; margin-bottom: 10px; }
}

/* Биография врача по бою: разделы со списками во всю ширину, ниже узкая колонка
   закрывающих абзацев с белой кнопкой и видео-визитка 766x485 справа.
   Пропорции колонок взяты замером боя (374 и 766 при сетке 1200). */
/* Секция биографии несёт фирменный срез угла, а он требует поля сверху, иначе заголовок
   попадает в вырез. Пока над секцией заканчивался герой, поле в 170 px читалось как воздух
   между экранами. После переноса видео-визитки наверх между роликом и первым абзацем стало
   246 px пустоты (замечание владельца 26.08.2026) - срез уменьшаем, поле сокращаем вдвое. */
.tl-doc-bio.tl-sec--curve-r { border-radius: 0 120px 0 0; padding-top: clamp(40px, 4.4vw, 64px); }
.tl-doc-card + .tl-doc-bio { margin-top: 0; }
.tl-doc-bio__part + .tl-doc-bio__part { margin-top: clamp(24px, 3vw, 42px); }
/* Видео-визитка под героем: во всю меру страницы, пропорция ролика как на бою */
.tl-doc-card { margin-top: clamp(22px, 2.6vw, 36px); }
/* Ролики визиток сняты в 1280x720, а окно имело пропорцию 766x485 (1.58) - кадр
   обрезался по бокам («видео срезано», замечание владельца 26.08.2026). Ставим
   16:9 и отдаём всю меру контейнера: на 1512 это 1160x652 вместо 766x485. */
.tl-doc-card .tl-video--doc { max-width: 1160px; margin-inline: auto; }
/* Закрывающий текст с кнопкой: ролик уехал наверх, поэтому колонка одна */
.tl-doc-tail { display: grid; grid-template-columns: minmax(0, 1fr);
               gap: clamp(22px, 2.6vw, 46px); align-items: start;
               margin-top: clamp(28px, 3.4vw, 50px); }
.tl-doc-tail__text { max-width: 74ch; }
.tl-doc-tail__text p { font-family: var(--font-body); font-size: 15px; line-height: 1.62; color: var(--tl-ink); }
.tl-doc-tail__text p + p { margin-top: 16px; }
.tl-doc-tail__cta { margin-top: clamp(20px, 2.4vw, 34px); }
.tl-video--doc { width: 100%; aspect-ratio: 16 / 9; border-radius: 20px 100px 20px 20px; }
/* Пилюля «Смотреть визитку» стоит в нижнем левом углу кадра (на бою - подпись и круг
   play рядом), поэтому фасад выравнивает содержимое по левому нижнему углу, а не по центру. */
.tl-video__facade--pill { place-content: end start; justify-items: start;
                          padding: clamp(18px, 2.4vw, 30px); }
/* Двухслойный фон padding-box/border-box в Safari и части сборок Chromium рисовался
   как сплошная золотая заливка - обложка под пилюлей переставала просвечивать, а белый
   текст падал до 3,4:1. Оставляем один полупрозрачный фон и обычную золотую рамку. */
.tl-video__pill { z-index: 2; display: inline-flex; align-items: center; gap: 12px;
                  padding: 6px 6px 6px 22px; border-radius: 999px;
                  border: 2px solid var(--gold);
                  background: rgba(27,24,21,.55);
                  backdrop-filter: blur(4px); }
.tl-video__pilltext { font-family: var(--font-body); font-size: clamp(14px, 1.2vw, 18px);
                      font-weight: 500; color: #fff; white-space: nowrap; }
.tl-video__play--pill { width: 44px; box-shadow: none; }
@media (max-width: 860px) {
  .tl-doc-tail { grid-template-columns: 1fr; }
  .tl-video--doc { border-radius: 20px 60px 20px 20px; }
}

/* Глава-видео боя («Посмотрите, как проходит процедура»): текста нет - ролики идут
   рядом во всю ширину, а не жмутся в правую колонку с пустотой слева */
.tl-pb--video-only { grid-template-columns: minmax(0, 1fr); }
.tl-pb--video-only .tl-pb__media { display: flex; gap: 24px; justify-content: center;
  flex-wrap: wrap; }
.tl-pb--video-only .tl-video--inband { margin: 0; }
@media (max-width: 900px) {
  .tl-pb--video-only .tl-pb__media { flex-direction: column; align-items: center; }
}

/* Глава, у которой плашки идут во всю ширину: проза и кадр стоят РЯДОМ,
   плашки - под ними на всю колонку. Раньше кадр висел под текстом, и слева
   от него зияла пустота в пол-экрана (замечание владельца 15.08). */
/* Высоту пары задаёт ТЕКСТ, кадр её заполняет (канон свода, §3). Раньше кадр
   держал собственную пропорцию и сам растягивал ряд: где текста меньше - слева
   оставалось пустое поле до 342 px, где больше - кадр висел в углу, а под ним
   пустовала правая треть (приёмка 02.09.2026, plazmoterapija и smas-lifting). */
.tl-prose__split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
  gap: 40px; align-items: stretch; }
.tl-prose__col > p:first-child { margin-top: 0; }
/* Воздух вокруг пары «текст + кадр». Приёмка 02.09.2026: заголовок главы стоял
   вплотную к сплиту (0 px), а абзац после списка слипался с последним пунктом
   (0 px при 25 px между абзацами) - глава читалась как сплошная стена. */
.tl-prose__h + .tl-prose__split,
.tl-band__h + .tl-prose__split { margin-top: 18px; }
.tl-dlist + p, .tl-pills + p { margin-top: 22px; }
.tl-plates + .tl-msgrow { margin-top: 20px; }

/* Карточка услуги («Популярные услуги», «Идеально сочетать») кликается ЦЕЛИКОМ.
   Раньше ссылкой был только кадр: владелец 03.09.2026 жал на название процедуры и
   ничего не происходило («не переключается с процедур идеально сочетать»). Название
   теперь ссылка, а её псевдоэлемент растянут на всю карточку. Кнопка «Записаться»
   лежит выше по слою, поэтому она по-прежнему открывает запись, а не уводит на
   страницу. Перетаскивание ленты клик не запускает - это гасит обработчик в main.js. */
.tl-pop { position: relative; }
.tl-pop__t a { color: inherit; text-decoration: none; }
.tl-pop__t a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.tl-pop__t a:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.tl-pop .tl-btn, .tl-pop__img { position: relative; z-index: 2; }
/* Глава, ВЕСЬ текст которой - плашки или пилюли: они идут В колонку рядом с кадром,
   иначе слева от кадра зияла дыра в его высоту - 780 px на 1512 («в каждой услуге
   поплыли блоки», владелец 02.09.2026). Правила, привязанные к прямому потомку
   .tl-band__text / .tl-prose, до плашек внутри колонки не достают - повторяем нужное. */
.tl-prose__col--all > :first-child { margin-top: 0; }
@media (min-width: 901px) {
  /* три плашки в колонке 700 px: две в ряд, третья во всю ширину колонки - иначе
     последняя висит половинкой */
  .tl-prose__col--all > .tl-plates:has(> :nth-child(3):last-child) > :nth-child(3) { grid-column: 1 / -1; }
}
.tl-prose__fig { margin: 0; padding: 2px; box-sizing: border-box;
  /* липкость нужна только очень длинным главам: там кадр упирается в max-height и
     едет вместе с текстом, вместо того чтобы висеть в углу (ручной массаж: текст
     1557 px, кадр 860). В остальных случаях высоты равны и sticky не срабатывает. */
  position: sticky; top: 120px;
  border-radius: 20px 100px 20px 20px; overflow: hidden;
  /* пропорция приходит из данных переменной --fig-ar и работает только в
     одноколоночной раскладке (ниже): рядом с текстом высоту диктует текст */
  aspect-ratio: auto; align-self: stretch;
  /* height: 100% обязателен: без него картинка внутри (у неё height: 100%)
     разрешается в auto и вносит в расчёт ряда свою натуральную высоту - высоту
     пары снова задаёт снимок, а не текст (приёмка-2: пустота 274 px под текстом
     на ботулинотерапии и плазмотерапии). У соседнего .tl-band__media эта строка
     есть, и там пустоты нет. */
  height: 100%;
  min-height: 240px;   /* совсем короткий текст не должен схлопывать кадр в полоску */
  max-height: 860px;   /* и очень длинная глава не должна вытягивать его в столб */
  background: linear-gradient(135deg, var(--gold) 0%, #e6cfa8 45%, var(--gold) 100%); }
/* Широкий кадр (пропорция больше 1) в вертикальном слоте пришлось бы увеличить
   почти вдвое и срезать 46 % ширины - лицо и прибор уезжали за край, картинка мылила
   (приёмка-2, smas-lifting). Такой кадр держим в родной пропорции и ставим по центру
   ряда: остаток делится поровну сверху и снизу и не читается как дыра. */
.tl-prose__fig--wide { align-self: center; height: auto; aspect-ratio: var(--fig-ar);
                       max-height: 100%; }
/* Снимок позиционируем абсолютно - тот же приём, что у кадра в блоке вопросов
   (.tl-faq__media). Иначе картинка вносит в расчёт ряда свою натуральную высоту, и
   высоту пары опять задаёт она: height: 100% у картинки внутри растягивающегося
   кадра разрешается в auto, круг замыкается (приёмка-2: пустота 274 px под текстом
   осталась даже после height: 100% у самого кадра). Абсолютный снимок из расчёта
   выпадает - высоту ряда диктует текст, кадр её заполняет. */
.tl-prose__fig > picture, .tl-prose__fig > img {
  position: absolute; inset: 2px; width: calc(100% - 4px); height: calc(100% - 4px); }
.tl-prose__fig img { display: block; width: 100%; height: 100%; object-fit: cover;
  /* кадрируем чуть выше центра: у портретных снимков при обрезке уходила макушка */
  object-position: 50% 35%;
  border-radius: 18px 98px 18px 18px; }
@media (max-width: 900px) {
  .tl-prose__split { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  /* Одна колонка: кадр стоит отдельным блоком, и тут его пропорция снова главная.
     align-self обязательно возвращаем в start: со stretch высоту ряда пытается
     задать картинка (у неё height: 100%), выходит порочный круг - в WebKit кадр
     схлопывался в 15x8 px, а ворота видели вылет за экран (найдено 02.09.2026). */
  /* Пропорцию задаёт САМ снимок (у img проставлены width/height), а не поле ar из
     переписи: на ботулинотерапии там стояло 1.736 при реальных 0.667, кадр выходил
     полоской 350x202 и упаковка препарата целиком уезжала за край (приёмка-2). */
  .tl-prose__fig { position: static; aspect-ratio: auto;
                   align-self: start; width: 100%; height: auto;
                   min-height: 0; max-height: none; }
  .tl-prose__fig > picture, .tl-prose__fig > img { position: static; inset: auto;
                   width: 100%; height: auto; }
}


/* Одинокая карточка в ленте (у ручного массажа на бою один специалист): на телефоне
   она обязана занимать всю ширину - половинка читается как поломка (PAGE_RULES §12) */
@media (max-width: 640px) {
  .is-static .tl-rail > :only-child { grid-column: 1 / -1; }
}

/* Три плашки боя идут одним рядом (рекомендации ImmunoHealth) - но только БЕЗ кадров:
   карточка со своим кадром занимает всю ширину, иначе текст ломается по три слова */
@media (min-width: 901px) {
  .tl-izd .tl-prose > .tl-plates:has(> :nth-child(3):last-child):not(:has(.tl-plates__card--withimg)),
  .tl-band__text > .tl-plates:has(> :nth-child(3):last-child):not(:has(.tl-plates__card--withimg)) { grid-template-columns: repeat(3, 1fr); }
}
/* колонка грида не должна раздуваться под min-content длинных слов */
.tl-band__text, .tl-pb__text, .tl-plates > * { min-width: 0; }
.tl-plates { grid-auto-columns: minmax(0, 1fr); }

/* Карточка боя со своим кадром (виды массажа, новообразования, этапы трихолога).
   Кадр справа - только когда карточке хватает ширины: при ТРЁХ карточках в ряд колонка
   узкая, и снимок обязан вставать сверху, иначе он вылезает на соседнюю карточку. */
.tl-plates__card--withimg .tl-plates__media { padding: 2px; border-radius: 18px;
  box-sizing: border-box; overflow: hidden; margin-bottom: 14px;
  background: linear-gradient(135deg, var(--gold) 0%, #e6cfa8 45%, var(--gold) 100%); }
.tl-plates__card--withimg .tl-plates__media img { display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover; border-radius: 16px; }

@media (min-width: 761px) {
  .tl-plates:not(:has(> :nth-child(3))) .tl-plates__card--withimg,
  .tl-plates:has(> :nth-child(4)) .tl-plates__card--withimg {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 240px);
    gap: 20px; align-items: center; }
  .tl-plates:not(:has(> :nth-child(3))) .tl-plates__card--withimg .tl-plates__body,
  .tl-plates:has(> :nth-child(4)) .tl-plates__card--withimg .tl-plates__body { order: 1; }
  .tl-plates:not(:has(> :nth-child(3))) .tl-plates__card--withimg .tl-plates__media,
  .tl-plates:has(> :nth-child(4)) .tl-plates__card--withimg .tl-plates__media {
    order: 2; margin-bottom: 0; }
}


/* Одинокая плашка боя занимает всю ширину блока, а не половину сетки */
.tl-plates:has(> :only-child) { grid-template-columns: minmax(0, 1fr); }

/* Заголовок плашки боя - это H3 (на оригинале он тоже заголовок, а не жирная строка) */
.tl-plates__t { font-family: var(--font-body); font-weight: 600; font-size: 15px;
  line-height: 1.35; margin: 0 0 8px; color: var(--ink); text-transform: none; letter-spacing: 0; }


/* ===== Правки по сверке 15.08 ===== */

/* H1 не рвём словарным переносом ни на каком экране (на бою переносы по словам) */
.tl-page__t { hyphens: manual; }

/* Подпись плитки на телефоне. Словарный перенос рвал слова посреди корня
   («БОТУЛИНО-ТЕРАПИЯ», «КОРРЕК-ЦИЯ ГУБ») - на бою при 390 подпись набрана 10px и
   переносится ПО СЛОВАМ. Уменьшаем кегль вместо разрыва слов. */
@media (max-width: 430px) {
  /* left/right, а не padding: подпись позиционируется абсолютно, и padding не расширял
     строку - «БОТУЛИНОТЕРАПИЯ» не влезала в 129px и рвалась пополам. При 10px и
     отступах 12 доступно 141px, слово занимает ~112 - с запасом, как на бою. */
  .tl-tile__t { font-size: 10px; letter-spacing: .03em; left: 12px; right: 12px;
    overflow-wrap: break-word; hyphens: manual; text-wrap: balance; }
}

/* Лента ДО/ПОСЛЕ из двух пар не должна оставлять треть ряда пустой. Ширину задаёт
   КОЛОНКА (см. правило is-static ниже), а не сам элемент: правило по ширине било
   и по карточке одинокого врача - она ужималась до 216px. */

/* Глава-видео на телефоне: заголовок сверху, ролики под ним (как на бою) */
@media (max-width: 900px) {
  .tl-pb--video-only .tl-pb__text { order: 0; }
  .tl-pb--video-only .tl-pb__media { order: 1; }
}

/* Старая цена в строке прайса - зачёркнутая и приглушённая (как на бою) */
.tl-rows u s, .tl-rows--menu .pr s { color: var(--ink-soft); opacity: .65;
  font-size: .86em; margin-right: 6px; text-decoration: line-through; font-weight: 400; }

/* Кнопка внутри песочной плашки боя */
.tl-plates__cta { display: inline-flex; margin-top: 14px; font-size: 14px; padding: 12px 22px; }

/* Портрет врача в герое - с золотым кантом, как все кадры сайта (§3 свода) */
.tl-doc-hero__media { padding: 2px; box-sizing: border-box;
  background: linear-gradient(150deg, var(--gold) 0%, #f3ddbc 48%, var(--gold) 100%); }
.tl-doc-hero__media img { border-radius: 18px 98px 18px 18px; }

/* Глава биографии без ролика - одной колонкой */
.tl-pb--plain { grid-template-columns: minmax(0, 1fr); }


/* Кнопка внутри широкой главы (.tl-prose) - это кнопка, а не ссылка в тексте */
.tl-prose a.tl-btn, .tl-prose a.tl-plates__cta { text-decoration: none; color: inherit; }

/* Плашки боя со СВОИМ кадром идут по одной в ряд: иначе текст ломается по три слова */
.tl-plates:has(.tl-plates__card--withimg) { grid-template-columns: minmax(0, 1fr); }

/* Вводный абзац прайса боя («Коррекция морщин ботулотоксином в Москве по цене...») */
.tl-price-lead { max-width: 62ch; margin: 10px 0 22px; font-size: 15px; line-height: 1.65;
  color: var(--ink-soft); }

/* Лента ДО/ПОСЛЕ из двух пар в статичном режиме - две колонки, а не три */
.is-static .tl-rail--3:not(:has(> :nth-child(3))) { grid-template-columns: repeat(2, 1fr); }


/* ===== Правки по замечаниям владельца (15.08, вторая волна) ===== */

/* Одинокая плашка боя занимает ВСЮ ширину блока: раньше правило перебивалось
   более специфичным `.tl-band--plain .tl-band__text > .tl-plates` и половина
   ряда оставалась пустой (Волньюмер, «VOLNEWMER —») */
.tl-plates:has(> :only-child),
.tl-band--plain .tl-band__text > .tl-plates:has(> :only-child),
.tl-izd .tl-prose > .tl-plates:has(> :only-child) { grid-template-columns: minmax(0, 1fr); }

/* Плитки мозаики в одном ряду одной высоты: широкая была 285 против 275 у соседей,
   и ряд «прыгал» (замечание владельца про «блоки разных уровней»).

   Высоту ряда НЕ фиксируем числом. Было `grid-auto-rows: 275px`, и при квадратной
   пропорции плитка брала ширину от этой высоты: на 1024 px колонка 231, а плитка
   275 - соседи наезжали друг на друга, страница уезжала за экран (замер 25.08).
   Теперь высоту ряда задаёт сама квадратная плитка (aspect-ratio 1/1 от ширины
   колонки), а широкая растягивается по ряду - пропорции сходятся на любой ширине. */
.tl-tile--wide { height: 100%; aspect-ratio: auto; }
/* Кадр широкой плитки выводим из потока: иначе он САМ задаёт высоту ряда (замер:
   на 1024 ряд раздувался до 482 px, и соседние квадраты 231 висели с пустотой под
   ними). Теперь высоту ряда диктует квадратная плитка, а широкая тянется по ней. */
.tl-tile--wide > picture, .tl-tile--wide img { position: absolute; inset: 0; }
@media (max-width: 900px) { .tl-tile--wide { aspect-ratio: 2 / 1; } }
/* Широкая плитка тянется по ряду и своей высоты не имеет - а если квадратных
   плиток в ряду нет, задать её высоту становится некому, и плитки схлопывались
   в ноль: раздел «Лазерная эпиляция» показывал пустоту, у врачей пропадали две
   плитки из двадцати двух (замер 27.08.2026). Нижняя граница = высота квадратной
   плитки, посчитанная от ширины САМОЙ сетки (cqw), а не экрана - поэтому она
   верна и в узких колонках. Первая строка - запас для браузеров без cqw. */
.tl-tiles { container-type: inline-size; }
.tl-tile--wide { min-height: 150px; min-height: calc((100cqw - 3 * var(--tl-gap)) / 4); }
@media (max-width: 900px) {
  .tl-tile--wide { min-height: calc((100cqw - var(--tl-gap)) / 2); }
}

/* добор остатка последнего ряда: 4 колонки (широкий экран) */
@media (min-width: 901px) {
  .tl-tiles[data-cells="3"] > :last-child { grid-column: span 2; }
  .tl-tiles[data-cells="5"] > :last-child { grid-column: span 4; }
  .tl-tiles[data-cells="6"] > :last-child { grid-column: span 3; }
  .tl-tiles[data-cells="7"] > :last-child { grid-column: span 2; }
  .tl-tiles[data-cells="9"] > :last-child { grid-column: span 4; }
  .tl-tiles[data-cells="10"] > :last-child { grid-column: span 3; }
  .tl-tiles[data-cells="11"] > :last-child { grid-column: span 2; }
  .tl-tiles[data-cells="13"] > :last-child { grid-column: span 4; }
  .tl-tiles[data-cells="14"] > :last-child { grid-column: span 3; }
  .tl-tiles[data-cells="15"] > :last-child { grid-column: span 2; }
}
/* две колонки: при нечётном числе клеток последняя плитка занимает строку целиком */
@media (max-width: 900px) {
  .tl-tiles[data-cells="3"] > :last-child,
  .tl-tiles[data-cells="5"] > :last-child,
  .tl-tiles[data-cells="7"] > :last-child,
  .tl-tiles[data-cells="9"] > :last-child,
  .tl-tiles[data-cells="11"] > :last-child,
  .tl-tiles[data-cells="13"] > :last-child,
  .tl-tiles[data-cells="15"] > :last-child { grid-column: 1 / -1; }
}

/* Биография врача без ролика - в две колонки: текст держит меру, а справа
   больше не остаётся полупустого поля */
.tl-pb__text--2col { max-width: none; columns: 2; column-gap: 56px; }
.tl-pb__text--2col > h2 { column-span: all; }
.tl-pb__text--2col > p, .tl-pb__text--2col > ul, .tl-pb__text--2col > .tl-plates {
  break-inside: avoid; }
.tl-pb__text--2col > p:first-of-type { margin-top: 0; }
@media (max-width: 900px) { .tl-pb__text--2col { columns: 1; } }


/* Зоны касания на телефоне: замер на iPhone 13 показал ссылки высотой 16-22 px -
   телефон в шапке, «Читать весь отзыв», крошки, меню подвала. Норма 44 px. Растим
   отступами внутри строки, чтобы раскладка блоков не разъезжалась. */
@media (max-width: 720px) {
  .tl-review__more { display: inline-block; padding-block: 11px; }
  /* Крошкам зону касания даём высотой строки, а не padding с отрицательным margin:
     на узком экране крошки переносятся на две строки, и padding накладывал их
     друг на друга и на надстрочник страницы (замер на iPhone 13). */
  .tl-crumbs a { display: inline-flex; align-items: center; min-height: 40px; }
  .tl-crumbs { line-height: 1.1; }
  .tl-foot ul a, .tl-foot__contacts a { display: inline-block; padding-block: 12px; }
  .tl-foot ul { margin-block: -10px; }
  /* телефон и почта в блоке контактов - те же 44 px зоны касания
     (список размечен как .tl-cont, а не .tl-contacts__list) */
  .tl-cont a { display: inline-block; padding-block: 10px; }
  .tl-foot__legal a { display: inline-block; padding-block: 13px; }
}

/* <picture> - обёртка eleventy-img: без явной высоты кадр не заполняет рамку,
   и снизу видна полоса золотой подложки */
.tl-prose__fig picture, .tl-plates__media picture, .tl-pb__media picture,
.tl-band__media picture, .tl-consult__media picture { display: block; width: 100%; height: 100%; }


/* Одинокая (или парная) карточка врача не должна выглядеть сиротой в ряду на три:
   на бою она так и висит слева, у нас - крупнее и по центру блока */
.is-static .tl-rail--3:not(:has(> :nth-child(2))) { grid-template-columns: minmax(0, 470px);
  justify-content: center; }
.is-static .tl-rail--3:has(> :nth-child(2)):not(:has(> :nth-child(3))) {
  grid-template-columns: repeat(2, minmax(0, 470px)); justify-content: center; }
@media (max-width: 640px) {
  .is-static .tl-rail--3:not(:has(> :nth-child(2))),
  .is-static .tl-rail--3:has(> :nth-child(2)):not(:has(> :nth-child(3))) {
    grid-template-columns: minmax(0, 1fr); }
}


/* Подвал на телефоне: одна колонка (две ужимали текст до 3 слов в строке),
   и запас снизу под липкую панель записи */
@media (max-width: 640px) {
  .tl-foot__grid { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .tl-foot { padding-bottom: 104px; }
  .tl-foot__tagline, .tl-foot__addr { max-width: none; }
}

/* Философия клиники на главной: выносная строка со знаком-ромбом. На бою этот абзац
   подан отдельным пунктом курсивом, у нас читался рядовым абзацем (замечание 17.08). */
.tl-credo { margin: 26px 0; padding: 22px 26px 22px 24px; border-left: 2px solid var(--gold);
             background: linear-gradient(90deg, rgba(196,155,103,.10), rgba(196,155,103,0) 70%);
             display: grid; gap: 10px; }
/* знак и подпись - одной строкой, знак по центру строки, а не по первой строке цитаты */
.tl-credo__label { display: flex; align-items: center; gap: 12px; margin: 0;
                   font-family: var(--font-body); font-weight: 600; font-size: 12.5px;
                   letter-spacing: .14em; text-transform: uppercase; color: var(--gold-deep); }
.tl-credo__mark { width: 24px; height: 27px; color: var(--gold-deep); flex: none; }
.tl-credo blockquote { margin: 0; font-family: var(--font-display); font-size: clamp(17px, 1.7vw, 21px);
  line-height: 1.5; color: var(--ink); }
.tl-credo blockquote b { display: block; font-family: var(--font-body); font-weight: 600;
  font-size: 12.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--gold-deep);
  margin-bottom: 8px; }
@media (max-width: 640px) {
  .tl-credo { padding: 18px 18px 18px 16px; gap: 8px; }
  .tl-credo__mark { width: 20px; height: 22px; }
}

/* Текстовая ссылка в потоке абзаца («Познакомиться с командой»): золотой акцент и
   зона касания 44 px по высоте - мобильные ворота ловят всё, что ниже 40. */
.tl-link { display: inline-flex; align-items: center; min-height: 44px;
  font-family: var(--font-body); color: #75593c; text-decoration: none;
  border-bottom: 1px solid rgba(150,117,63,.45); transition: color .2s, border-color .2s; }
.tl-link:hover { color: var(--gold-deep); border-color: var(--gold-deep); }

/* Защита текстов от копирования - как на действующем сайте (просьба владельца
   26.08.2026). Поиску это не мешает: роботы читают HTML, а не выделение мышью.
   Что НЕ закрываем осознанно: телефон, почту, адрес и поля форм - иначе человек не
   сможет скопировать номер, чтобы позвонить с компьютера, или вставить свой телефон
   в заявку. Полностью «запретить» копирование нельзя - можно лишь убрать привычные
   способы, поэтому ценность защиты в том, чтобы текст не утащили мимоходом. */
body { -webkit-user-select: none; user-select: none; }
input, textarea, select,
.tl-cont a, .tl-foot__contacts a, .hdr__phone, .drawer__phone,
.tl-foot__addr, .tl-cont, [data-copyable] {
  -webkit-user-select: text; user-select: text;
}

/* Раздел «Полезное»: карточка статьи с кадром сверху и текстом под ним. Кадр в той же
   рамке, что кадры каталога, но пропорция шире - в Дзене обложки горизонтальные. */
/* Скругление у карточки фирменное - 100 px на одном углу. У обложек из Дзена под этим
   углом лежит текст, и срез «съедал» буквы («VOLFORME» вместо «VOLFORMER»). Поэтому
   верхние углы, где стоит кадр, скругляем обычным радиусом, а фирменный срез оставляем
   снизу - на песочной части карточки, где текста у края нет. */
.tl-card--article { padding: 0; overflow: hidden; border-radius: 20px 20px 20px 100px; }
.tl-card--article.tl-card--flip { border-radius: 20px 20px 100px 20px; }
.tl-card--article .tl-card__media { display: block; margin: 0; }
/* Обложки статей приходят из Дзена ровно 16:9 и несут на себе текст до самого края.
   object-fit: cover срезал у них правый край («VOLFORME» вместо «VOLFORMER»), поэтому
   показываем кадр целиком: пропорция контейнера и кадра совпадает, поля не появляются. */
.tl-card--article .tl-card__media img { display: block; width: 100%; height: auto;
  object-fit: contain; aspect-ratio: 16 / 9; }
.tl-card--article .tl-card__t,
.tl-card--article p { padding-inline: clamp(20px, 2.4vw, 30px); }
.tl-card--article .tl-card__t { margin-top: clamp(18px, 2vw, 24px); }
.tl-card--article .tl-card__more { padding: 0 clamp(20px, 2.4vw, 30px) clamp(22px, 2.4vw, 30px); }

/* Дата и автор: у карточки - над заголовком, на странице - под ним. Дзен показывает
   в ленте относительное «год назад», у нас точная дата из разметки статьи. */
.tl-card__date { font-family: var(--font-body); font-size: 13px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-mute); }
.tl-card--article .tl-card__date { padding-inline: clamp(20px, 2.4vw, 30px);
  margin-top: clamp(16px, 1.8vw, 22px); }
.tl-article__meta { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px;
  font-family: var(--font-body); font-size: 14px; color: var(--ink-mute); }

/* Тело статьи: кадры во всю меру текста, оговорка отделена воздухом */
.tl-article { max-width: 74ch; }
.tl-article__cover { margin-top: clamp(20px, 2.6vw, 34px); border-radius: 20px 100px 20px 20px;
  overflow: hidden; padding: 2px;
  background: linear-gradient(150deg, #c49b68 0%, #f3ddbc 48%, #c49b68 100%); }
.tl-article__cover img { display: block; width: 100%; height: 100%; object-fit: cover;
  aspect-ratio: 16 / 9; border-radius: 18px 98px 18px 18px; }
.tl-article__fig { margin: clamp(22px, 2.6vw, 34px) 0; }
.tl-article__fig img { display: block; width: 100%; height: auto; border-radius: 20px; }
.tl-article .tl-prose__h { margin-top: clamp(26px, 3vw, 40px); }
.tl-article__note { margin-top: clamp(26px, 3vw, 38px); max-width: 74ch; }

/* Страница «Наша команда»: карточки администраторов и руководства - тот же кадр с
   подписью, что у врачей, но без ссылки (своих страниц у них нет). */
.tl-doc--static { cursor: default; }

/* Блок «Добро пожаловать» с кадром команды и цифрами клиники (перепись боя). */
.tl-welcome { display: grid; grid-template-columns: minmax(0, 564fr) minmax(0, 596fr);
  gap: clamp(24px, 3vw, 52px); align-items: center; }
.tl-welcome__media { border-radius: 20px 100px 20px 20px; overflow: hidden; padding: 2px;
  background: linear-gradient(150deg, #c49b68 0%, #f3ddbc 48%, #c49b68 100%); }
.tl-welcome__media img { display: block; width: 100%; height: 100%; object-fit: cover;
  aspect-ratio: 564 / 511; border-radius: 18px 98px 18px 18px; }
.tl-welcome__text p { font-family: var(--font-body); font-size: clamp(14px, 1.3vw, 16px);
  line-height: 1.62; color: var(--tl-ink); }
.tl-welcome__text p + p { margin-top: 14px; }
.tl-welcome__sub { font-family: var(--font-display); font-size: clamp(17px, 1.7vw, 22px);
  line-height: 1.35; color: var(--tl-ink); margin-bottom: 18px; }
/* Цифры клиники: ряд из четырёх, на планшете - два по два, на телефоне столбцом */
.tl-figures { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(18px, 2.4vw, 34px); margin-top: clamp(30px, 3.6vw, 54px); }
.tl-figures__item { display: grid; gap: 8px; }
.tl-figures__v { font-family: var(--font-body); font-weight: 500; line-height: 1;
  font-size: clamp(34px, 4vw, 60px); color: var(--gold-deep); }
.tl-figures__c { font-family: var(--font-display); font-size: clamp(14px, 1.3vw, 18px);
  line-height: 1.4; color: var(--tl-ink); }
@media (max-width: 900px) {
  .tl-welcome { grid-template-columns: 1fr; }
  .tl-figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) { .tl-figures { grid-template-columns: 1fr; } }

/* Отзывы: пять золотых звёзд справа от имени - как на бою (клиника спросила, почему
   их нет; прежнее наше правило «звёзд не рисуем» расходилось с оригиналом) */
.tl-review__head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 10px; }
.tl-review__stars { color: var(--gold); letter-spacing: 2px; font-size: 14px; line-height: 1;
  flex: 0 0 auto; }
@media (max-width: 640px) { .tl-review__stars { font-size: 13px; } }
