/* ============================================================
   ДЕНТАЛ МЕД — вариант 2 «Стоматология по подписке»
   Палитра: графит / глубокая бирюза / светло-серый
   ============================================================ */

@font-face{font-family:'Inter';font-style:normal;font-weight:300 800;font-display:swap;
  src:url(../fonts/inter-cyrillic.woff2) format('woff2');
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;}
@font-face{font-family:'Inter';font-style:normal;font-weight:300 800;font-display:swap;
  src:url(../fonts/inter-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}

:root{
  --ink:#0A0A0A;
  --ink-2:#141518;
  --ink-3:#1E2024;
  --teal:#2E6C7E;
  --teal-deep:#1B4C59;
  --teal-lite:#5FA3B5;
  --grey:#CDCDCD;
  --grey-2:#8A8E92;
  --paper:#F1F0ED;
  --paper-2:#E3E1DC;
  --white:#fff;

  --header-h:76px;
  --bar-h:38px;

  --ease-menu:cubic-bezier(.6,.14,0,1);
  --ease-quint:cubic-bezier(.22,1,.36,1);
  --slide-ease:cubic-bezier(.24,.43,.15,.97);
  --ease-quad:cubic-bezier(.455,.03,.515,.955);

  --pad:clamp(20px,5vw,86px);
  --gap:clamp(28px,4vw,64px);

  /* ── ЕДИНАЯ СЕТКА КОНТЕНТА (LAYOUT-STANDARDS, модель 1.В: full-bleed + fluid gutter) ──
     Один max-width на весь сайт + плавный боковой отступ. Ступенчатых контейнеров нет.
     --edge — тот же отступ, но с учётом центрирования .wrap на сверхшироких экранах:
     до 1560+2*pad ведёт себя как --pad, дальше растёт вместе с полями .wrap,
     чтобы шапка, герой, пиннированный каталог и абсолютные подписи стояли на ОДНОЙ
     вертикали с текстом секций. Проценты считаются от ширины блока-контейнера
     (для fixed — от ICB), поэтому ширина скроллбара не вносит расхождения. */
  --grid-max:1560px;
  --grid-measure:80ch;
  --edge:max(var(--pad),calc((100% - var(--grid-max)) / 2 + var(--pad)));
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--ink);color:var(--white);
  font-family:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  font-size:17px;line-height:1.62;font-weight:400;
  -webkit-font-smoothing:antialiased;overflow-x:hidden;overflow-x:clip;
}
img,svg,video{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit}
ul{margin:0;padding:0;list-style:none}

/* --- Типографика --------------------------------------------------------- */
h1,h2,h3,h4{margin:0;font-weight:700;letter-spacing:-.03em;line-height:1.02;overflow-wrap:break-word}
/* Кегли ужаты по фидбэку 31.07 «заголовки ≤2 строк, лиды ≤3»: тот же
   дисплейный характер, но строк меньше на всех адаптивах. */
/* Фидбэк 06.08 «заголовки без пословной разбивки». text-wrap:balance
   выравнивает длину строк заголовка, поэтому последняя строка перестаёт
   быть одиноким словом («Посчитайте / свой год честно» → «Посчитайте свой /
   год честно»). Считается один раз при раскладке, на прокрутку не влияет. */
.d1,.d2,.d3{text-wrap:balance}
.d1{font-size:clamp(34px,6.6vw,104px)}
.d2{font-size:clamp(26px,3.7vw,56px);line-height:1.06}
.d3{font-size:clamp(22px,2.7vw,40px);line-height:1.1;letter-spacing:-.025em}
.d4{font-size:clamp(19px,1.8vw,27px);line-height:1.18;letter-spacing:-.02em}
p{margin:0 0 1.1em}
.lead{font-size:clamp(15.5px,1.28vw,19.5px);line-height:1.52;color:var(--grey)}
.small{font-size:14px;line-height:1.55;color:var(--grey-2)}
.tiny{font-size:12.5px;line-height:1.6;color:var(--grey-2)}
.over{
  font-size:12px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;
  color:var(--teal-lite);margin:0 0 20px;display:block;
}
.over.on-light{color:#2A6373}
.tealbg .over,.ctaband .over{color:#BFE3EC}
.tealbg .step .n{color:#9FD5E3}
.tealbg .acc-head:hover{color:#BFE3EC}
.tealbg .tlink,.ctaband .tlink{color:#BFE3EC;border-color:rgba(191,227,236,.45)}
em,.it{font-style:normal;color:var(--teal-lite)}
.mono-num{font-variant-numeric:tabular-nums}

/* --- Раскладка ----------------------------------------------------------- */
.wrap{width:100%;max-width:var(--grid-max);margin:0 auto;padding-left:var(--pad);padding-right:var(--pad)}
.sec{padding-block:clamp(72px,9vw,150px);position:relative}
.sec.tight{padding-block:clamp(52px,6vw,96px)}
[id],section[id],h2[id]{scroll-margin-top:calc(var(--header-h) + var(--bar-h) + 28px)}
.light{background:var(--paper);color:var(--ink)}
.light .lead{color:#41464A}
.light .small,.light .tiny{color:#5B6064}
.tealbg{background:var(--teal-deep);color:var(--white)}
.grid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--gap)}
.grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gap)}
.grid4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(18px,2vw,32px)}
.grid2>*,.grid3>*,.grid4>*{min-width:0}
.hr{height:1px;background:rgba(255,255,255,.14);border:0;margin:0}
.light .hr{background:rgba(10,10,10,.14)}
/* Длина строки (WCAG 1.4.8): лид не растягивается на всю ширину широкого контейнера */
.lead{max-width:62ch;text-wrap:pretty}
.bigcopy{max-width:34ch}
h1,h2,h3,h4{text-wrap:balance}

/* --- Видимый фокус для клавиатуры (единый) ------------------------------- */
:focus-visible{outline:2px solid var(--teal-lite);outline-offset:3px;border-radius:2px}
.light :focus-visible,.sh-l :focus-visible{outline-color:var(--teal)}
.btn:focus-visible{outline-offset:5px}

/* --- Кнопки (скошенный параллелограмм — мотив шестигранника) -------------- */
.btn{
  --skew:-14deg;
  position:relative;display:inline-flex;align-items:center;justify-content:center;
  gap:10px;padding:15px 34px;border:0;background:none;cursor:pointer;
  font-size:12.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--white);transition:color .2s;
}
.btn::before{
  content:'';position:absolute;inset:0;transform:skewX(var(--skew));
  border:1px solid rgba(255,255,255,.5);background:transparent;
  transition:background-color .2s,border-color .2s,transform .3s var(--ease-quad);
}
.btn span{position:relative;z-index:1}
.btn:hover::before{background:var(--white);border-color:var(--white);transform:skewX(var(--skew)) scale(1.03)}
.btn:hover{color:var(--ink)}
.btn:active::before{transition-duration:.1s}
.btn--fill::before{background:var(--teal);border-color:var(--teal)}
.btn--fill:hover::before{background:var(--teal-lite);border-color:var(--teal-lite)}
.btn--fill:hover{color:var(--ink)}
.btn--ink::before{border-color:rgba(10,10,10,.42)}
.btn--ink{color:var(--ink)}
.btn--ink:hover::before{background:var(--ink);border-color:var(--ink)}
.btn--ink:hover{color:var(--white)}
.btn--sm{padding:11px 24px;font-size:11.5px}

/* Текстовая ссылка-CTA со стрелкой */
.tlink{
  display:inline-flex;align-items:center;gap:12px;
  font-size:12.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--teal-lite);padding-bottom:6px;border-bottom:1px solid rgba(95,163,181,.4);
  transition:color .25s,border-color .25s;
}
.tlink svg{width:16px;height:16px;transition:transform .3s var(--ease-quad);flex:none}
.tlink:hover{color:var(--white);border-color:var(--white)}
.tlink:hover svg{transform:translate(4px,-4px)}
.light .tlink{color:var(--teal);border-color:rgba(46,108,126,.4)}
.light .tlink:hover{color:var(--ink);border-color:var(--ink)}

/* ============================================================
   ШАПКА
   ============================================================ */
/* ── ВЕРХНЯЯ ПАНЕЛЬ ОДНИМ ФИКСИРОВАННЫМ БЛОКОМ ───────────────────────────────
   Было: .addrbar (fixed top:0) и .hdr (fixed top:var(--bar-h)) — ДВА независимо
   позиционированных fixed-элемента, которые при скролле разъезжались каждый своим
   transition'ом. На iPad Safari (плавающая полупрозрачная тулбар-панель, свой
   ритм пересчёта visual viewport) шапка регулярно оставалась на top:38px, а
   адресная плашка уже уезжала — между верхом экрана и шапкой зияла щель шириной
   ровно --bar-h, сквозь которую просвечивал контент («шапка висит в воздухе»).
   Стало: одна обёртка .topbar на top:0 вплотную к вьюпорту (+ safe-area), а
   адресная плашка внутри неё СХЛОПЫВАЕТСЯ по высоте. Шапка физически не может
   оторваться от верха — щели неоткуда взяться. */
.topbar{
  position:fixed;top:0;left:0;right:0;z-index:120;
  padding-top:env(safe-area-inset-top,0px);
  margin:0;
  transition:transform .3s var(--ease-quad);
}
/* Уезжает ЦЕЛИКОМ одним transform'ом (composited, без layout): адресная плашка
   уходит за верхний край, шапка садится ровно на top:0. Разъехаться половинкам
   физически нечем — это и было причиной «щели» на iPad. */
.topbar.up{transform:translateY(calc(-1 * var(--bar-h)))}
.addrbar{
  position:relative;z-index:1;height:var(--bar-h);overflow:hidden;
  background:var(--teal);display:flex;align-items:center;justify-content:center;
  font-size:12.5px;font-weight:600;letter-spacing:.03em;color:#fff;
  padding-inline:16px;text-align:center;
  transition:opacity .25s var(--ease-quad);
}
.addrbar svg{width:13px;height:13px;margin-right:8px;flex:none}
.addrbar.hide{opacity:0}

/* ── ФОН ШАПКИ: ВСЕГДА СПЛОШНАЯ ЧЁРНАЯ ПЛАШКА (правка владельца 11.08) ──────
   БЫЛО: три состояния фона — прозрачное (вверху страницы), тёмное .is-stuck
   и СВЕТЛОЕ .on-light (над светлыми секциями), и все они переливались друг в
   друга анимацией `background-color .45s`. На macOS Safari у клиентки шапка
   регулярно оставалась «белёсой градиентной»: .topbar — fixed-элемент с
   собственным transform-переходом, то есть отдельный композитный слой, и
   WebKit не перерисовывал его после смены background-color на потомке. На
   экране застывал ПОЛУКАДР перехода прозрачный→светлый: сверху тёмное,
   снизу белое, поверх контента. У владельца на Windows/Chrome слой
   перерисовывался, поэтому баг не воспроизводился.
   СТАЛО: у шапки ОДИН непрозрачный фон во всех состояниях прокрутки и на
   всех страницах. Переливаться нечему — застыть на полукадре тоже нечему,
   и белая шапка над светлой секцией больше не появляется. */
.hdr{
  position:relative;z-index:2;height:var(--header-h);
  display:flex;align-items:center;justify-content:space-between;
  padding-inline:var(--edge);
  background:#0B0B0B;
  border-bottom:1px solid rgba(255,255,255,.12);
}
/* .up больше не сдвигает шапку — её место держит схлопывание .addrbar.
   Класс оставлен: на него завязаны стили состояния. */
.hdr.up{transform:none}
/* Классы состояния (.is-stuck / .on-light) фон больше НЕ меняют: плашка
   одна и та же. Правила оставлены пустыми намеренно — чтобы любой старый
   селектор, дописанный поверх, было видно в одном месте. */
.hdr.is-stuck{background:#0B0B0B;border-bottom-color:rgba(255,255,255,.12)}

.logo{display:flex;align-items:center;gap:14px;flex:none}
.logo-mark{width:46px;height:52px;flex:none}
.logo-mark path,.logo-mark line,.logo-mark polyline{stroke:#fff;stroke-width:1.6;fill:none;
  stroke-linecap:round;stroke-linejoin:round;transition:stroke .45s var(--ease-menu)}
.logo-word{font-size:23px;font-weight:700;letter-spacing:.16em;line-height:1;color:#fff;transition:color .45s}
.logo-sub{display:block;font-size:9.5px;font-weight:500;letter-spacing:.3em;color:var(--grey);margin-top:5px}

.hdr-right{display:flex;align-items:center;gap:6px}
/* Плашка кнопки — скошенный ::before, он выступает за бокс на height*tan(14°)/2
   (~6 px с каждой стороны). Без gap соседние плашки наезжали друг на друга на
   ~10 px — это и видно было в шапке. Минимум 16 px разводит их гарантированно. */
.hdr-actions{display:flex;align-items:center;gap:16px}
.hdr-actions .btn{padding-inline:26px}

.burger{width:46px;height:46px;margin-left:14px;background:none;border:0;cursor:pointer;
  display:flex;flex-direction:column;justify-content:center;gap:6px;padding:0 6px}
.burger i{display:block;height:1.6px;background:#fff;border-radius:2px;
  transition:transform .4s var(--ease-menu),opacity .25s,width .4s var(--ease-menu),background-color .45s}
.burger i:nth-child(1){width:100%}
.burger i:nth-child(2){width:72%;align-self:flex-end}
.burger i:nth-child(3){width:100%}
.burger:hover i:nth-child(2){width:100%}
body.nav-open .burger i:nth-child(1){transform:translateY(7.6px) rotate(45deg)}
body.nav-open .burger i:nth-child(2){opacity:0;width:0}
body.nav-open .burger i:nth-child(3){transform:translateY(-7.6px) rotate(-45deg)}
body.nav-open .burger i{background:#fff!important}

/* Оверлей меню */
.navov{
  position:fixed;inset:0;z-index:105;background:rgba(8,8,8,.97);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  opacity:0;visibility:hidden;transition:opacity .32s var(--ease-menu),visibility .32s;
  padding:calc(var(--header-h) + var(--bar-h)) var(--edge) 40px;overflow-y:auto;
}
body.nav-open .navov{opacity:1;visibility:visible}
.navov a{
  font-size:clamp(19px,2.4vw,30px);font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--grey);padding:9px 4px;transition:color .25s;
  opacity:0;transform:translateY(20px);
}
body.nav-open .navov a{opacity:1;transform:none;
  transition:opacity .4s var(--ease-quint),transform .5s var(--ease-quint),color .25s}
body.nav-open .navov a:nth-child(1){transition-delay:.06s}
body.nav-open .navov a:nth-child(2){transition-delay:.11s}
body.nav-open .navov a:nth-child(3){transition-delay:.16s}
body.nav-open .navov a:nth-child(4){transition-delay:.21s}
body.nav-open .navov a:nth-child(5){transition-delay:.26s}
body.nav-open .navov a:nth-child(6){transition-delay:.31s}
body.nav-open .navov .btn{transition-delay:.36s}
.navov a:hover{color:#fff}
.navov a.act{color:#fff}
.navov a.act::after{content:'';display:block;height:1px;background:var(--teal-lite);margin-top:6px}
/* Фидбэк 06.08 («Снимок 132911»): зелёная кнопка в меню была во всю ширину
   экрана и по кеглю спорила с пунктами навигации — читалась как баннер, а не
   как действие. Делаем её компактной: ширина по содержимому, свой кегль
   меньше пунктов меню, аккуратный верхний отступ. */
.navov .btn{margin-top:clamp(18px,2.6vw,30px);opacity:0;transform:translateY(20px);
  align-self:center;width:auto;max-width:min(66vw,262px);
  padding:10px 18px;font-size:10.5px;letter-spacing:.09em;line-height:1.35;text-align:center}
.navov .btn span{display:block}
body.nav-open .navov .btn{opacity:1;transform:none;transition:opacity .4s var(--ease-quint),transform .5s var(--ease-quint)}
/* Прокрутка под открытым меню. Раньше её глушил lenis.stop(); на тач-экране
   Lenis больше не запускается (см. app.js, ПЕРФ), поэтому лочим страницу
   штатным способом — иначе фон уезжал под оверлеем. */
body.nav-open{overflow:hidden}

/* ============================================================
   PAGE TRANSITION — маска-логотип
   ============================================================ */
#pt{position:fixed;inset:0;z-index:9999;pointer-events:none;display:grid;place-items:center;overflow:hidden}
#pt.on{pointer-events:all}
/* will-change поднимаем только на время перехода: слой 200vmax×200vmax,
   держать его в памяти постоянно — минус кадры на всей странице */
#pt.on .pt-mask{will-change:transform,opacity}
.pt-mask{
  position:absolute;left:50%;top:50%;width:200vmax;height:200vmax;margin:-100vmax 0 0 -100vmax;
  background:var(--ink);
  clip-path:polygon(25% 0,75% 0,100% 50%,75% 100%,25% 100%,0 50%);
}
.pt-logo{position:relative;z-index:2;width:min(240px,42vw)}
.pt-logo path,.pt-logo line,.pt-logo polyline{fill:none;stroke:#fff;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
.pt-logo .mid{stroke:var(--teal-lite)}

/* ============================================================
   HERO
   ============================================================ */
.hero{position:relative;min-height:100svh;padding-top:calc(var(--header-h) + var(--bar-h));
  display:flex;flex-direction:column;overflow:hidden}
.hero-bg{position:absolute;inset:-12% 0 -12%;z-index:0}
/* ПЕРФ 11.08: тут стоял filter:brightness(.34) saturate(.7) на картинке
   размером во весь экран, которую ещё и тянет параллакс (data-par) — то есть
   пиксельный фильтр пересчитывался на каждом кадре прокрутки героя.
   Затемнение и обесцвечивание ЗАПЕЧЕНЫ в сам файл interior-lounge.webp той же
   матрицей, что применял браузер (яркость 0.34 × saturate 0.7), поэтому кадр
   не изменился, а фильтра в отрисовке больше нет. Заодно файл похудел
   с 48 КБ до 13 КБ: тёмная картинка сжимается втрое лучше. */
.hero-bg img{width:100%;height:100%;object-fit:cover}
.hero-bg::after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(10,10,10,.72),rgba(10,10,10,.3) 45%,rgba(10,10,10,.9))}
/* --hero-pad: одна переменная вместо четырёх сторон padding — раскрытие
   инсет-рамки до full-bleed скрабится записью ОДНОГО свойства (см. app.js,
   heroFrame). На телефоне это заметно дешевле, чем анимация shorthand.
   inherits:false (см. @property ниже) — чтобы запись переменной не
   инвалидировала стиль всего содержимого героя, а только сам .hero-inner. */
@property --hero-pad{syntax:'<length>';inherits:false;initial-value:0px}
.hero-inner{--hero-pad:3.5vw;position:relative;z-index:2;flex:1;display:flex;
  padding:var(--hero-pad);padding-top:calc(var(--hero-pad) * .58)}
.hero-frame{
  position:relative;flex:1;border:1px solid rgba(255,255,255,.6);overflow:hidden;
  display:flex;align-items:flex-end;min-height:62vh;
}
.hero-frame img,.hero-frame video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.hero-frame::after{content:'';position:absolute;inset:0;
  background:linear-gradient(100deg,rgba(6,6,6,.86) 0%,rgba(6,6,6,.5) 44%,rgba(6,6,6,.14) 78%)}
/* 900px не хватало: заголовок героя ломался на 3 строки вместо 2 */
.hero-copy{position:relative;z-index:3;padding:clamp(24px,4vw,64px);max-width:min(1060px,94%)}
.hero-eyebrow{position:absolute;top:clamp(16px,2vw,30px);right:clamp(18px,2.6vw,40px);z-index:4;margin:0;
  font-size:clamp(10px,.92vw,13px);font-weight:600;letter-spacing:.22em;text-transform:uppercase;
  color:rgba(255,255,255,.85);text-align:right;max-width:60%;text-shadow:0 1px 14px rgba(0,0,0,.7)}
.hero h1{margin:0 0 26px}
.hero .d1{font-size:clamp(32px,5.3vw,78px)}
.hero h1 .ln{display:block;overflow:hidden}
.hero h1 .ln>span{display:block}
.hero-facts{display:flex;flex-wrap:wrap;gap:clamp(16px,2.4vw,40px);margin-top:8px}
.hero-facts div{font-size:13.5px;color:var(--grey);max-width:230px;line-height:1.45}
.hero-facts b{display:block;font-size:clamp(22px,2.4vw,34px);font-weight:700;color:#fff;
  letter-spacing:-.02em;line-height:1;margin-bottom:7px}
.hero-cta{display:flex;flex-wrap:wrap;gap:18px;margin-top:clamp(24px,3vw,40px)}

/* Полоса доверия */
.trust{border-top:1px solid rgba(255,255,255,.12);border-bottom:1px solid rgba(255,255,255,.12)}
.trust ul{display:grid;grid-template-columns:repeat(4,minmax(0,1fr))}
.trust li{min-width:0}
.trust li{padding:clamp(24px,3vw,44px) clamp(14px,2vw,32px);border-left:1px solid rgba(255,255,255,.12)}
.trust li:first-child{border-left:0}
.trust b{display:block;font-size:clamp(26px,3.2vw,46px);font-weight:700;letter-spacing:-.03em;line-height:1;margin-bottom:12px}
.trust li>span{font-size:13.5px;color:var(--grey-2);line-height:1.45;display:block}
.trust b span{font:inherit;color:inherit;display:inline;letter-spacing:inherit}

/* ============================================================
   ★ СТОПКА ЗАКРЕПЛЁННЫХ КАРТОЧЕК
   ============================================================ */
.stack{position:relative;background:var(--ink);isolation:isolate}
/* ФИКС 06.08 (кадры IMG_8674 «текст первого слайда просвечивает за вторым»).
   Карточка обязана быть ПОЛНОСТЬЮ непрозрачной: свой фон, свой контекст
   наложения и z-index по порядку (его проставляет app.js). Раньше фон был
   только у карточки, а её половины (.sc-media / .sc-body) полагались на
   него — во время наезда, когда уходящая карточка ещё запиннена и
   отмасштабирована, сквозь неё читался текст предыдущей.
   ПЕРФ: постоянный will-change:transform на КАЖДОЙ карточке держал по
   полноэкранному слою в памяти; теперь его поднимает JS только на время
   наезда (stickyCards, onToggle). */
[sticky-card]{
  position:relative;min-height:100svh;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  background:var(--ink);border-top:1px solid rgba(255,255,255,.12);
  isolation:isolate;backface-visibility:hidden;
}
/* ПЕРФ 06.08. Скраб пишет --after-opacity в карточку КАЖДЫЙ кадр наезда.
   По умолчанию любая --переменная НАСЛЕДУЕМАЯ, поэтому одна запись
   инвалидировала стиль всего поддерева карточки (заголовок, абзацы, список,
   картинка) — сотни узлов на кадр. @property с inherits:false ограничивает
   инвалидацию самой карточкой: меняется только её ::after. */
@property --after-opacity{syntax:'<number>';inherits:false;initial-value:0}
[sticky-card]::after{
  content:'';position:absolute;inset:0;background:#080808;
  opacity:var(--after-opacity,0);pointer-events:none;z-index:5;
}
/* ПРАВКА ВЛАДЕЛЬЦА 06.08 (кадр frames-1715). Карточки с классом .rev
   (перевёрнутые «текст слева / фото справа») вырастали ВЫШЕ экрана —
   1168 px против 900: у них строка грида не была задана, и высоту диктовала
   картинка. Карточка выше вьюпорта физически НЕ МОЖЕТ накрыть предыдущую
   целиком — отсюда полоса прошлого кадра над въезжающим.
   Фиксируем ровно один экран и одну строку: теперь каждая карточка кроет
   предыдущую край в край, а стопка считается без остатка. */
@media (min-width:861px){
  [sticky-card]{height:100svh;grid-template-rows:100%;overflow:hidden}
}
.sc-media{position:relative;overflow:hidden;background:var(--ink);z-index:1}
/* ПЕРФ 11.08 (замер: RasterTask = 6,3 с из 10,5 с работы главного потока за
   прогон прокрутки — растеризация была узким местом, а не JS).
   Было: filter:brightness(.72) на полноэкранной картинке. Пиксельный фильтр
   пересчитывается при КАЖДОЙ перерисовке слоя, а карточки ещё и пинятся.
   Стало: чёрный слой с opacity .28 — МАТЕМАТИЧЕСКИ ТОТ ЖЕ результат
   (C·0,72 = C·(1−0,28) для непрозрачного фона), но это заливка одним цветом,
   которую композитор кладёт поверх без пересчёта пикселей картинки.
   Внешний вид не изменился ни на тон. */
.sc-media img{width:100%;height:100%;object-fit:cover}
.sc-media::before{content:'';position:absolute;inset:0;background:#000;opacity:.28;
  z-index:1;pointer-events:none}
.sc-media h3{
  position:absolute;left:clamp(22px,3vw,52px);bottom:clamp(22px,3vw,52px);right:clamp(22px,3vw,52px);
  z-index:2;text-shadow:0 2px 30px rgba(0,0,0,.6)
}
.sc-body{
  display:flex;flex-direction:column;justify-content:center;gap:22px;
  padding:clamp(30px,4.4vw,86px);background:var(--ink-2);position:relative;z-index:1;
}
/* Перевёрнутая карточка (текст слева / фото справа).
   КОРЕНЬ БАГА 06.08 (кадр frames-1715 «под новой карточкой виден предыдущий
   кадр»): модификатор назывался `.rev` — ровно как класс КАРТОЧКИ ОТЗЫВА
   (`.rev{display:flex;border;padding}`, см. блок «Отзывы»). Карточка стопки
   получала чужой display:flex и разваливалась в две строки высотой 1168 px
   вместо 900 — то есть физически не могла накрыть предыдущую целиком, и над
   въезжающим кадром торчала полоса прошлого. Модификатор переименован в
   `.sc-rev` (префикс блока), коллизия снята. */
[sticky-card].sc-rev .sc-media{order:2}
[sticky-card].sc-rev .sc-body{order:1}
.sc-proof{
  display:inline-flex;align-items:baseline;gap:12px;padding:12px 18px;
  border-left:2px solid var(--teal-lite);background:rgba(46,108,126,.14);
  font-size:14px;color:var(--grey);align-self:flex-start;
}
.sc-proof b{color:#fff;font-weight:600;white-space:nowrap}
.sc-idx{font-size:12px;letter-spacing:.2em;color:var(--grey-2);font-weight:600}

/* ============================================================
   Заливка текста по символам
   ============================================================ */
/* will-change:color бесполезен (color не композитится), но плодил слой
   на КАЖДЫЙ символ — сотни слоёв на секцию. Убрано.
   ПЕРФ 06.08: сама заливка «серый → бирюзовый → цвет текста» уехала из JS
   в CSS. JS теперь только вешает классы на новые символы (0–3 за кадр).
   Раньше на каждый кадр прокрутки шёл forEach по всем 300–500 символам с
   gsap.set(color) плюс персональный setTimeout — основная просадка на ПК.

   ДВА РАЗНЫХ КЛАССА — не прихоть, а замер. Если вешать анимацию прямо на
   .lit, она остаётся на символе навсегда: к концу абзаца в документе висит
   650 «завершённых» анимаций, и движок стилей обходит их каждый кадр
   (recalc-style за прогон вырос 0,45 → 0,80 с). Поэтому .lit — только
   конечный цвет, а вспышку несёт короткоживущий .flash, который снимает
   общий rAF-сборщик в app.js: одновременно «горит» 3–10 символов. */
/* ПЕРФ 12.08 (вторая волна). Разрезанный на символы абзац — это 150–350 узлов
   внутри одного <p>, а на index таких абзацев пять: 938 лишних узлов при 1558
   узлах всей страницы. Пока абзац не изолирован, КАЖДОЕ навешивание .lit/.flash
   помечает грязным целое поддерево документа, и движок стилей на каждом кадре
   прокрутки обходит его целиком — замер показал recalc-style 1,07 с за прогон
   против 0,44 с у страницы без разрезания.
   contain говорит браузеру, что изменения внутри абзаца наружу не выходят:
   пересчёт стиля, раскладка и краска замыкаются на самом <p>.
   Почему это безопасно именно здесь: под [animated-copy] лежат только <p> с
   текстом (см. разметку — .lead и .bigcopy), внутри нет ни position:fixed,
   ни абсолютного позиционирования, ни теней/обводок, вылезающих за границы —
   вспышка меняет ТОЛЬКО color. Поэтому paint-отсечение ничего не обрезает, а
   анимация остаётся ровно та же. Замер: длинные кадры за прогон 74 → 56,
   p90 кадра 167 → 133 мс. */
[animated-copy]{contain:layout style paint}
[animated-copy] .char{color:#CDCDCD}
.light [animated-copy] .char{color:#B4B7BA}
[animated-copy] .char.lit{color:inherit}
[animated-copy] .char.flash{animation:copyflash .42s var(--ease-quad)}
@keyframes copyflash{
  0%{color:#5FA3B5}
  100%{color:inherit}
}
@media (prefers-reduced-motion:reduce){
  [animated-copy] .char{color:inherit}
  [animated-copy] .char.flash{animation:none}
}
.bigcopy{font-size:clamp(23px,2.9vw,44px);line-height:1.34;font-weight:500;letter-spacing:-.02em}

/* Дышащая клякса */
.blob{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
/* ПЕРФ 11.08: blur(38px) на слое до 1100 px — самая дорогая растеризация на
   странице. Без своего композитного слоя размытие пересчитывалось всякий раз,
   когда мимо проезжала прокрутка (браузер перерисовывает плитки фона секции).
   will-change:filter выносит кляксу в отдельный слой: она растеризуется один
   раз, а при прокрутке только СДВИГАЕТСЯ композитором. Морфинг контура
   (десктоп, каждый 3-й кадр) работает как работал — вид не изменился. */
.blob svg{position:absolute;width:min(1100px,120%);height:auto;opacity:.38;filter:blur(38px);
  will-change:transform;transform:translateZ(0)}
/* ЗАМЕР 11.08: пробовали поднять кляксу в отдельный композитный слой через
   will-change:filter. Растеризация падала вчетверо, НО кадры становились хуже:
   стоимость переезжала в компоновку слоя во весь экран. Тогда промоушен сняли.

   ЗАМЕР 12.08 (вторая волна) — ПЕРЕСМОТРЕНО, и вот почему это не противоречие.
   will-change:filter обещает браузеру, что МЕНЯТЬСЯ БУДЕТ САМ ФИЛЬТР, поэтому
   слой пересобирается заново — размытие считается снова и снова. Здесь же
   фильтр постоянный, а меняется только положение кляксы относительно экрана.
   will-change:transform говорит ровно это: «двигаться будет, размываться —
   нет». Blur(38/26px) растеризуется ОДИН раз, дальше композитор просто возит
   готовую текстуру, и прокрутка её не трогает.
   Замер на телефоне (390×844, CPU ×4, прогон всей страницы): медиана кадра
   33,4 → 16,8 мс (то есть 30 к/с → 60), p90 166,6 → 66,7 мс, кадров дольше
   50 мс 74 → 35, длинных задач 8072 → 2997 мс. Вид не изменился: та же клякса,
   то же размытие, тот же морфинг на десктопе. */
/* ПЕРФ 06.08: на телефоне клякса остаётся, но не дышит (app.js), а размытие
   ужато — растеризация слоя 1100 px с blur(38px) на мобильном GPU стоит
   заметно дороже, чем выглядит. Визуально разница в статике не читается. */
@media (max-width:900px),(hover:none){
  .blob svg{width:min(720px,110%);filter:blur(26px);opacity:.34}
}
/* ПЕРФ 12.08 (вторая волна). Это НЕ промоушен кляксы в отдельный слой — его мы
   уже отвергли замером выше (растр падал вчетверо, а кадры становились хуже).
   Здесь другое: contain сужает область, которую браузер обязан считать
   испорченной. Раньше любая перерисовка внутри секции объявляла недействительной
   всю её площадь вместе с размытой кляксой во всю ширину страницы, и работа
   собиралась в один длинный кадр. С contain она дробится на независимые куски.
   .blob и так был overflow:hidden, а .sec и так position:relative — поэтому ни
   область отсечения, ни содержащий блок не сдвигаются, и вид не меняется
   (проверено попиксельно: 180 снимков, 6 страниц × 2 локали × 5 вьюпортов ×
   3 позиции прокрутки — расхождений нет).
   ЗАМЕР 12.08, медиана 3 прогонов, прокрутка 9000 px, 1440×900:
     только пережатое медиа   avg 19.0  p90 33.3  p99 50.0  кадров >50 мс: 1
     + contain на кляксе      avg 18.3  p90 16.8  p99 50.0  кадров >50 мс: 1
   Растеризация при этом чуть выросла (3430 -> 3698 мс за прогон), но она
   раздроблена и больше не собирается в длинные кадры, а человек чувствует
   именно кадры, а не суммарные миллисекунды растра.

   ПОЧЕМУ ТОЛЬКО КЛЯКСА, А НЕ СЕКЦИИ. Замер с `.sec{contain:layout paint}` был
   ещё лучше — avg 17.5, p90 16.7, p99 33.4, длинных кадров 0, — но он НЕ взят
   осознанно. На index.html секции не просто идут стопкой: ScrollTrigger пиннит
   `.sec.light.overlapped` через position:fixed, а `.sec.overlapper` наезжает
   на неё сверху (см. overlaps() в app.js), плюс рядом лежит стопка
   [sticky-card] с таким же пином. contain:paint меняет для секции и контракт
   отсечения краски, и роль содержащего блока для потомков с position:fixed —
   то есть трогает ровно ту механику, на которой держится наезд секций.
   Дёшево проверить это нечем: попиксельный тест снимается с
   prefers-reduced-motion, а и overlaps(), и stickyCards() при reduce вообще
   не запускаются — тест был бы зелёным независимо от того, поехало на живом
   десктопе или нет. Менять p99 с 50 на 33 мс и один длинный кадр на ноль
   такой ценой не стоит. У .blob подобных потомков нет (внутри только
   декоративный svg, и элемент и так overflow:hidden), поэтому contain на нём
   безопасен и даёт основной выигрыш — p90 с 33 мс до 17. */
.blob{contain:paint}

.blob.b-r svg{right:-14%;top:-16%}
.blob.b-l svg{left:-18%;bottom:-22%}
.sec>.wrap{position:relative;z-index:2}

/* Иконочные доказательства */
.proofs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gap);margin-top:clamp(40px,5vw,80px)}
.proof{min-width:0}
.proof{border-top:1px solid rgba(255,255,255,.18);padding-top:26px}
.light .proof{border-top-color:rgba(10,10,10,.18)}
.proof .ic{width:38px;height:38px;margin-bottom:20px}
.proof .ic path,.proof .ic circle,.proof .ic line,.proof .ic rect,.proof .ic polyline{
  fill:none;stroke:var(--teal-lite);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
.light .proof .ic path,.light .proof .ic circle,.light .proof .ic line,
.light .proof .ic rect,.light .proof .ic polyline{stroke:var(--teal)}
.proof h4{margin-bottom:10px}
.proof p{margin:0;font-size:15px;color:var(--grey)}
.light .proof p{color:#4A4E52}

/* ============================================================
   ТАРИФЫ / ПОДПИСКА
   ============================================================ */
.plans{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(20px,2.4vw,34px)}
.plan{min-width:0}
.plan{display:flex;flex-direction:column;border:1px solid rgba(255,255,255,.18);
  transition:transform .3s var(--ease-quint),border-color .3s}
.plan:hover{transform:scale(1.012);border-color:rgba(95,163,181,.6)}
.plan-head{background:var(--teal);padding:clamp(26px,3vw,44px);min-height:210px}
.plan--pro .plan-head{background:var(--teal-deep)}
.plan-head h3{margin-bottom:14px}
.plan-head p{margin:0;font-size:15px;color:rgba(255,255,255,.9)}
.plan-tag{display:inline-block;margin-bottom:16px;padding:5px 12px;border:1px solid rgba(255,255,255,.55);
  font-size:10.5px;font-weight:600;letter-spacing:.16em;text-transform:uppercase}
.plan-body{flex:1;display:flex;flex-direction:column;background:var(--ink-2);padding:clamp(26px,3vw,44px)}
.plan-body ul{margin:0 0 34px;display:flex;flex-direction:column;gap:13px}
.plan-body li{position:relative;padding-left:30px;font-size:15.5px;color:var(--grey);line-height:1.5}
.plan-body li svg{position:absolute;left:0;top:4px;width:17px;height:17px}
.plan-body li svg path{fill:none;stroke:var(--teal-lite);stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.plan-body li b{color:#fff;font-weight:600}
.plan-price{margin-top:auto}
.plan-price .pv{font-size:clamp(30px,3.6vw,52px);font-weight:700;letter-spacing:-.03em;line-height:1.06}
.plan-price .py{font-size:15px;color:var(--grey-2);margin-top:8px}
.plan-price .btn{margin-top:24px}

.note{font-size:12.5px;color:var(--grey-2);line-height:1.6;margin-top:26px}

/* ============================================================
   ЦИФРЫ НА ДУГЕ
   ============================================================ */
/* ============================================================
   ЦИФРЫ НА ДУГЕ — «челюсть»
   ------------------------------------------------------------
   Фидбэк 06.08 (фото 13-24-14): раньше шесть одинаковых кругов стояли
   ровным рядом, а линия дуги шла сама по себе и пересекала их наискось —
   связи между линией и кругами не читалось.
   ПРАВКА 06.08 (референс-схема ревьюера): дуга была прогнута НЕ в ту
   сторону — края опускались ниже центра, и вместо «улыбки» получался свод.
   Линию убрали совсем по прямому требованию владельца.
   Стало: симметричная ДУГА-УЛЫБКА, как зубной ряд. Диаметры зеркальны
   (центральная пара самая крупная, крайняя самая мелкая), центры кружков
   лежат на одной параболе прогибом ВНИЗ, концы приподняты.
   Нормируем позицию колонки u = ±1, ±.6, ±.2 и берём глубину f = 1 - u²:
   края 0, средние .64, центральные .96. Сдвиг сверху доводим до общего
   центра: margin-top = f·drop + (Dmax - D)/2, тогда центр = .48·Dmax + f·drop
   и от диаметра не зависит — пары стоят строго на одной высоте.
   Проценты в width/margin-top считаются от ширины колонки, значит вся
   конструкция масштабируется вместе с сеткой и не требует пересчёта в JS.
   ============================================================ */
.arcwrap{position:relative;padding-top:clamp(30px,4vw,60px)}
.bubbles{position:relative;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));
  gap:0;align-items:start;justify-items:center}
/* ── ЦЕНТРОВКА СВЯЗКИ «ЧИСЛО + ПОДПИСЬ» В КРУГЕ (правка владельца 12.08, ред. 2)
   БЫЛО (ред. 1 того же дня): по центру круга ставилось само ЧИСЛО, а подпись
   выводилась из потока (position:absolute) и подвешивалась под ним. При подписи
   в 2–3 строки связка целиком уезжала вниз: сверху воздуха оставалось заметно
   больше, чем снизу, круг выглядел «сползшим». Владелец забраковал.
   СТАЛО: круг — flex-КОЛОНКА с центровкой по обеим осям, число и подпись стоят
   в потоке и центрируются КАК ЕДИНАЯ ГРУППА. Никаких absolute-смещений: воздух
   сверху и снизу равен при любом числе строк подписи. Расстояние число↔подпись
   фиксированное (gap:.32em ≈ 5 px) и от длины подписи не зависит. */
.bubble{--numfs:calc(clamp(19px,2.35vw,38px) * var(--bk,1));
  position:relative;z-index:1;
  width:var(--bw,86%);aspect-ratio:1;
  margin-top:calc(var(--f,0) * var(--drop,0px) + (96% - var(--bw,86%)) / 2);
  border-radius:50%;border:1px solid rgba(255,255,255,.2);
  background:rgba(46,108,126,.16);display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:.32em;
  text-align:center;padding:clamp(6px,.7vw,12px)}
/* Пары «зубов» от центра к краю.
   ВАЖНО — nth-of-TYPE, а не nth-child: первым ребёнком .bubbles лежит <svg>
   с дугой, поэтому nth-child сдвигал бы всю нумерацию на единицу (крайний
   правый кружок оставался без правила и выпадал из дуги — так и было
   до фикса). nth-of-type считает только <div>-кружки. */
.bubbles{--drop:clamp(32px,4.6vw,78px)}
.bubble:nth-of-type(3),.bubble:nth-of-type(4){--bw:96%;--f:.96}
.bubble:nth-of-type(2),.bubble:nth-of-type(5){--bw:83%;--f:.64}
.bubble:nth-of-type(1),.bubble:nth-of-type(6){--bw:70%;--f:0}
/* Кегль тоже убывает от центра к краю — иначе в мелком круге число
   упирается в кромку. Базовый размер один, множитель на пару. */
.bubble b{font-size:var(--numfs);
  font-weight:700;letter-spacing:-.03em;line-height:1;max-width:80%}
/* Ширины в долях диаметра: круг вмещает квадрат со стороной 0,707·D, поэтому
   78 % — предел, при котором двухстрочная подпись не выходит за окружность. */
.bubble>span{display:block;
  font-size:clamp(9.5px,.8vw,11.5px);
  color:var(--grey-2);line-height:1.25;max-width:78%}
.bubble:nth-of-type(2),.bubble:nth-of-type(5){--bk:.9}
.bubble:nth-of-type(1),.bubble:nth-of-type(6){--bk:.8}
.bubble b span{font:inherit;color:inherit;letter-spacing:inherit}
/* Заливка кружка НЕПРОЗРАЧНАЯ (тот же тон, что давало rgba(46,108,126,.1)
   поверх бумаги — #DEE3E2). Так дуга не просвечивает сквозь цифры: линия
   входит в кружок и выходит из него, кружки «сидят» на дуге, как зубы. */
.light .bubble{border-color:rgba(46,108,126,.42);background:#DEE3E2;color:var(--ink)}
.light .bubble b{color:var(--ink)}
.light .bubble>span{color:#4A4E52}

/* ============================================================
   ТЕХНОЛОГИИ — карусель
   ============================================================ */
.tech{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:var(--gap);align-items:stretch}
/* ГОТЧА: aspect-ratio + align-items:stretch = ширина считается ОТ высоты строки грида,
   и .tech-stage вылезал за свою колонку на ~200 px, накрывая список технологий.
   На десктопе высоту задаёт min-height, пропорция включается только в стопке. */
.tech-stage{position:relative;overflow:hidden;background:var(--ink-2);
  min-height:clamp(300px,26vw,470px);min-width:0}
.tech-stage img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transform:scale(1.06);transition:opacity .6s ease,transform .6s ease}
.tech-stage img.act{opacity:1;transform:scale(1)}
.tech-side{display:flex;flex-direction:column;justify-content:space-between;gap:26px;min-width:0}
.tech-list li{border-top:1px solid rgba(255,255,255,.14);}
.tech-list button{display:block;width:100%;text-align:left;background:none;border:0;cursor:pointer;
  padding:15px 0;font-size:clamp(15px,1.35vw,20px);font-weight:500;letter-spacing:-.01em;
  color:var(--grey-2);transition:color .45s var(--ease-menu),padding .45s var(--ease-menu)}
.tech-list button:hover{color:var(--grey)}
.tech-list li.act button{color:#fff;font-weight:600;padding-left:16px}
.tech-benefit{border-left:2px solid var(--teal-lite);padding-left:18px;min-height:96px}
.tech-benefit p{margin:0;color:var(--grey)}
.tech-count{font-size:13px;letter-spacing:.16em;color:var(--grey-2);display:flex;align-items:baseline;gap:2px}
.tech-count .n{color:#fff;font-weight:600;display:inline-block;overflow:hidden;height:1.2em}
.tech-count .n i{display:block;font-style:normal}
/* Карусель на светлой секции: без этого блока активный пункт был БЕЛЫМ на бумаге */
.light .tech-list li{border-top-color:rgba(10,10,10,.16)}
.light .tech-list button{color:#5B6064}
.light .tech-list button:hover{color:#26292C}
.light .tech-list li.act button{color:var(--ink)}
.light .tech-benefit{border-left-color:var(--teal)}
.light .tech-benefit p{color:#41464A}
.light .tech-count{color:#5B6064}
.light .tech-count .n{color:var(--ink)}

/* --- Scrollytelling-аккордеон (06.08) --------------------------------------
   Описание выгоды теперь раскрывается ПОД своим пунктом, а активный пункт
   переключается сам по мере прокрутки секции (см. app.js, techCarousel).
   Раскрытие идёт grid-template-rows 0fr→1fr — это один переход на смену
   пункта, без покадрового JS и без пересчёта высот руками. Панели строит JS
   из data-benefit, поэтому разметку RU/EN трогать не пришлось; без JS
   остаётся прежний общий блок .tech-benefit. */
.tech.has-panels .tech-benefit{display:none}
.tech.has-panels .tech-side{justify-content:flex-start;gap:18px}
.tech-panel{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .55s var(--ease-menu),opacity .35s ease;opacity:0}
.tech-list li.act .tech-panel{grid-template-rows:1fr;opacity:1}
.tech-panel>div{overflow:hidden;min-height:0}
.tech-panel p{margin:0 0 16px;padding-left:16px;border-left:2px solid var(--teal-lite);
  color:var(--grey);max-width:56ch}
.light .tech-panel p{border-left-color:var(--teal);color:#41464A}
@media (prefers-reduced-motion:reduce){.tech-panel{transition:none}}

/* ============================================================
   ★ ПИННИРОВАННЫЙ КАТАЛОГ (services)
   ============================================================ */
.cat{position:relative;height:100svh;overflow:hidden;background:var(--ink)}
.cat-inner{position:absolute;inset:0;display:grid;
  grid-template-columns:minmax(210px,20%) minmax(0,1fr);gap:clamp(20px,3vw,60px);
  padding:calc(var(--header-h) + var(--bar-h) + 3vh) var(--edge) 5vh}
.cat-nav{display:flex;flex-direction:column;justify-content:center;gap:14px;border-right:1px solid rgba(255,255,255,.14);padding-right:clamp(14px,2vw,34px)}
.cat-nav button{background:none;border:0;text-align:left;cursor:pointer;padding:6px 0;
  font-size:clamp(13px,1.1vw,16px);font-weight:500;color:rgba(205,205,205,.4);
  transition:color .4s ease;line-height:1.3}
.cat-nav button.act{color:#fff;font-weight:600}
.cat-nav button:hover{color:var(--grey)}
.cat-stage{position:relative;overflow:hidden}
/* ПЕРФ 06.08: из смены слайдов убран filter:blur(6px→0). Размытие слайда
   во весь экран пересчитывается растеризатором КАЖДЫЙ кадр все 0,9 с
   перехода, и так на каждое переключение внутри запиннутого каталога —
   один из самых заметных источников рывков на ПК. Ощущение перехода даёт
   та же связка opacity + сдвиг по X, но обе величины композитятся на GPU. */
.cat-slide{position:absolute;inset:0;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.92fr);
  gap:clamp(20px,3vw,54px);align-content:center;opacity:0;pointer-events:none;
  transform:translateX(min(8%,44px));visibility:hidden;
  transition:opacity .9s var(--slide-ease),transform .9s var(--slide-ease),
             visibility 0s .9s}
.cat-slide.act{opacity:1;transform:none;pointer-events:auto;visibility:visible;
  transition:opacity .9s var(--slide-ease),transform .9s var(--slide-ease),
             visibility 0s 0s}
.cat-slide.out{opacity:0;transform:translateX(max(-8%,-44px))}
.cat-l{display:flex;flex-direction:column;justify-content:center;gap:20px;min-width:0}
.cat-l h3{font-size:clamp(30px,4.4vw,72px);line-height:1}
.cat-l h3 .ln{display:block;overflow:hidden}
.cat-r{display:flex;flex-direction:column;justify-content:center;gap:10px;min-width:0}
.cat-r ul{display:flex;flex-direction:column;gap:2px}
.cat-r li a{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  padding:11px 0;border-bottom:1px solid rgba(255,255,255,.12);transition:padding .3s var(--ease-quint),color .3s}
.cat-r li a:hover{padding-left:8px;color:var(--teal-lite)}
.cat-r li span:first-child{font-size:clamp(13.5px,1.15vw,17px)}
.cat-r li .pr{font-size:13px;color:var(--grey-2);white-space:nowrap;font-variant-numeric:tabular-nums}
.cat-prog{position:absolute;left:var(--edge);bottom:2.4vh;right:var(--edge);height:1px;background:rgba(255,255,255,.16)}
.cat-prog i{display:block;height:100%;background:var(--teal-lite);width:25%;transition:transform .6s var(--slide-ease);transform-origin:left}
.cat-hint{position:absolute;right:var(--edge);bottom:calc(2.4vh + 16px);font-size:11.5px;letter-spacing:.16em;color:var(--grey-2);text-transform:uppercase}
/* СТРЕЛКИ СЛАЙДЕРА (правка владельца 06.08 — «как на dental-med-1»).
   Правый верхний угол сцены: там нет ни заголовка слайда, ни списка цен.
   На телефоне уезжают вниз, к полосе прогресса, и получают 44 px тап-цели. */
.cat-arrows{position:absolute;z-index:7;display:flex;gap:10px;right:var(--edge);top:clamp(74px,9vh,120px)}
.cat-arrow{width:46px;height:46px;flex:none;padding:0;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;color:#fff;
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.28);
  transition:background-color .3s,border-color .3s,color .3s,transform .2s}
.cat-arrow svg{width:20px;height:20px}
.cat-arrow:hover{background:var(--teal-lite);border-color:var(--teal-lite);color:var(--ink)}
.cat-arrow:active{transform:scale(.93)}
.cat-arrow:focus-visible{outline:2px solid var(--teal-lite);outline-offset:3px}
@media (max-width:860px){
  .cat-arrows{top:auto;bottom:calc(2.4vh + 34px);right:var(--edge);gap:12px}
  .cat-arrow{width:44px;height:44px}
  .cat-hint{display:none}
}

/* ============================================================
   КЛКТ (technology) — снимок слева, текст справа, градиент на стыке
   ------------------------------------------------------------
   Фидбэк 06.08 (фото 13-24-49, 13-25-10, 13-25-12): полноэкранный
   scroll-zoom убран. Кадр в центре чёрного поля читался как «вертикальная
   фотка с телефона», текст лежал ПОВЕРХ снимка и с обеих сторон оставались
   пустые чёрные прямоугольники.
   Стало (вариант ревьюера): снимок занимает левую половину целиком,
   заголовок — справа сверху, текст под ним, а стык двух половин размыт
   градиентом, поэтому «рамки фотографии» не видно и текст НИКОГДА не
   заходит на изображение.
   ============================================================ */
.cbctsec{position:relative;display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);
  background:var(--ink);overflow:hidden;min-height:min(76svh,760px)}
.cbct-media{position:relative;margin:0;overflow:hidden;min-height:clamp(320px,42vw,760px)}
/* Снимок кабинета почти белый (обновлён 06.08). Лёгкое приглушение нужно,
   чтобы он не выжигал тёмную страницу; текста поверх него на десктопе нет. */
/* ПРАВКА ВЛАДЕЛЬЦА 06.08: «блок слишком тёмный, томографа не видно».
   Причина была не в яркости кадра, а в ГЕОМЕТРИИ: аппарат стоит у ПРАВОГО
   края снимка — ровно там, где скрим уходил в сплошной --ink (.82 на 86 %),
   и оборудование съедалось чернотой.
   Решение из двух шагов, оба безопасны для контраста: кадр ОТЗЕРКАЛЕН
   (scaleX(-1)) — томограф уезжает влево, в светлую, ничем не закрытую часть
   и попадает в мобильный кроп; а правый скрим ослаблен и оставлен ТОЛЬКО
   как растушёвка стыка с тёмной колонкой. Текст на десктопе и на телефоне
   лежит на собственной подложке --ink, а не на снимке, поэтому ослабление
   скрима контраст текста не трогает вообще. */
.cbct-media img{width:100%;height:100%;object-fit:cover;transform:scaleX(-1);filter:none}
.cbct-media::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(90deg,rgba(10,10,10,.14),rgba(10,10,10,0) 16%,rgba(10,10,10,0) 62%,rgba(10,10,10,.5) 90%,var(--ink) 100%),
    linear-gradient(180deg,rgba(10,10,10,.3),rgba(10,10,10,0) 22%)}
.cbct-copy{position:relative;z-index:2;display:flex;flex-direction:column;align-items:flex-start;
  gap:clamp(12px,1.4vw,20px);
  padding:calc(var(--header-h) + var(--bar-h) + clamp(24px,3.4vw,64px)) var(--edge) clamp(34px,4.4vw,72px) clamp(24px,3.2vw,60px)}
.cbct-copy .over{margin:0}
/* Заголовку отдаём ВСЮ ширину колонки: .cbct-copy — flex с
   align-items:flex-start, поэтому по умолчанию заголовок ужимался по
   содержимому (595 px из 713) и длинный английский вариант уходил в три
   строки. width:100% + pretty вместо balance — обе локали в двух строках. */
.cbct-copy h2{max-width:none;width:100%;text-wrap:pretty;font-size:clamp(24px,3.3vw,48px)}
.cbct-copy .lead{margin:0;max-width:46ch}
.cbct-fact{display:flex;flex-direction:column;gap:6px;margin:clamp(6px,1vw,14px) 0 0;
  border-left:2px solid var(--teal-lite);padding-left:18px;max-width:38ch}
.cbct-fact b{font-size:clamp(24px,2.6vw,38px);font-weight:700;letter-spacing:-.03em;line-height:1;color:#fff}
.cbct-fact span{font-size:14px;line-height:1.5;color:var(--grey-2)}

/* ============================================================
   Наезд-перекрытие T1
   ============================================================ */
/* ПЕРФ 06.08: will-change снят из CSS — его поднимает app.js (overlaps,
   onToggle) ровно на время наезда. Блюр уходящей секции заменён на
   opacity+scale: filter:blur() на секцию во весь экран пересчитывался
   растеризатором каждый кадр и давал самые тяжёлые кадры страницы. */
.overlapper{position:relative;z-index:3;background:var(--ink)}
.overlapped{position:relative;z-index:1}

/* ============================================================
   Аккордеон
   ============================================================ */
.acc-item{border-top:1px solid rgba(255,255,255,.16)}
.acc-item:last-child{border-bottom:1px solid rgba(255,255,255,.16)}
.light .acc-item{border-top-color:rgba(10,10,10,.16)}
.light .acc-item:last-child{border-bottom-color:rgba(10,10,10,.16)}
.acc-head{display:flex;width:100%;align-items:center;justify-content:space-between;gap:22px;
  background:none;border:0;cursor:pointer;text-align:left;padding:24px 0;
  font-size:clamp(16px,1.5vw,22px);font-weight:600;letter-spacing:-.015em;transition:color .25s}
.acc-head:hover{color:var(--teal-lite)}
.light .acc-head:hover{color:var(--teal)}
.acc-ic{flex:none;width:26px;height:26px;position:relative}
.acc-ic::before,.acc-ic::after{content:'';position:absolute;left:50%;top:50%;background:currentColor;
  transform:translate(-50%,-50%);transition:transform .4s var(--ease-quint),opacity .3s}
.acc-ic::before{width:15px;height:1.5px}
.acc-ic::after{width:1.5px;height:15px}
.acc-item.open .acc-ic::after{transform:translate(-50%,-50%) rotate(90deg);opacity:0}
.acc-panel{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .45s var(--ease-quint),opacity .35s ease}
.acc-panel>div{overflow:hidden;min-height:0}
.acc-item.open .acc-panel{grid-template-rows:1fr}
.acc-panel .in{padding-bottom:28px;max-width:78ch;color:var(--grey)}
.light .acc-panel .in{color:#4A4E52}
.acc-panel .in p:last-child{margin-bottom:0}

/* ============================================================
   Врачи — текст за вырезанными фигурами
   ============================================================ */
/* ФИКС 06.08 (фото 13-26-53 «заголовок пропал» и 13-31-00 на телефоне).
   Было: ряд портретов лежал absolute с z-index:2 ПОВЕРХ заголовка (z-index:1)
   и на многих ширинах закрывал слово целиком — эффект «текст за фигурами»
   на практике читался как пропавший заголовок, а на 390 px портреты резали
   слово пополам. Стало: заголовок и ряд разнесены по вертикали в обычном
   потоке, заголовок лежит ВЫШЕ по стеку (z-index:3) — перекрыть его больше
   нечем ни на одной ширине. */
/* ── ЗАГЛАВНЫЙ ЭКРАН «КОМАНДА» (правка владельца 12.08) ────────────────────
   БЫЛО: min(78svh,780px) + justify-content:flex-end + overflow:hidden. Ряд
   портретов прижимался к нижней кромке блока, и подписи под фотографиями
   (СОКОЛОВ, ВЕРЕЩАГИНА, …) РЕЗАЛИСЬ границей секции пополам — на скане
   первого экрана 1440x900 буквы обрезаны ровно по линии стыка.
   СТАЛО: блок на весь экран (полосы следующей секции под ним больше нет)
   плюс нижний отступ, который гарантированно вмещает подписи. */
.teamhero{position:relative;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:flex-end;
  min-height:100vh;min-height:100svh;
  padding-top:calc(var(--header-h) + var(--bar-h) + clamp(26px,5vw,78px));
  padding-bottom:clamp(34px,5vw,86px);
  background:radial-gradient(ellipse at 50% 62%,rgba(46,108,126,.4),var(--ink) 62%)}
.teamhero h2{position:relative;z-index:3;text-align:center;font-size:clamp(40px,9vw,164px);
  letter-spacing:-.045em;line-height:.94;margin:0 0 clamp(22px,3.2vw,54px);
  padding-inline:var(--edge);max-width:100%;text-wrap:balance}
.teamrow{position:relative;z-index:2;width:100%;display:flex;justify-content:center;
  align-items:flex-end;gap:clamp(4px,1.4vw,26px);padding-inline:var(--edge)}
.teamrow figure{margin:0;width:clamp(110px,15vw,250px)}
.teamrow img{width:100%;height:auto;
  -webkit-mask-image:linear-gradient(180deg,#000 76%,transparent 99%);
  mask-image:linear-gradient(180deg,#000 76%,transparent 99%)}
.teamrow figcaption{position:relative;z-index:3;margin-top:-8%;text-align:center;
  font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--grey)}

.doccard{display:grid;grid-template-columns:minmax(0,.72fr) minmax(0,1fr);gap:clamp(20px,3vw,54px);
  align-items:start;padding-block:clamp(34px,4.4vw,72px);border-top:1px solid rgba(255,255,255,.14)}
.doccard .ph{position:relative;overflow:hidden;aspect-ratio:4/5;background:var(--ink-2)}
.doccard .ph img{width:100%;height:100%;object-fit:cover;transition:transform .8s var(--ease-quint)}
.doccard:hover .ph img{transform:scale(1.04)}
.doccard .meta{font-size:12.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--teal-lite);margin-bottom:14px}
.doccard .slogan{font-style:italic;color:var(--grey);font-size:clamp(17px,1.6vw,23px);
  border-left:2px solid var(--teal-lite);padding-left:18px;margin:20px 0 26px;line-height:1.45}
.docfacts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;margin:24px 0}
.docfacts>div{min-width:0}
.docfacts div b{display:block;font-size:clamp(21px,2vw,30px);font-weight:700;letter-spacing:-.02em;line-height:1}
.docfacts div>span{font-size:12.5px;color:var(--grey-2);display:block;margin-top:7px;line-height:1.35}
.docfacts b span{font:inherit;color:inherit;display:inline;letter-spacing:inherit}

/* ============================================================
   Отзывы
   ============================================================ */
.revs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(20px,2.4vw,34px)}
.rev{border:1px solid rgba(255,255,255,.16);padding:clamp(24px,2.6vw,38px);display:flex;
  flex-direction:column;gap:16px;transition:border-color .3s,background-color .3s}
.rev:hover{border-color:rgba(95,163,181,.65);background:rgba(46,108,126,.08)}
.rev h3{font-size:clamp(18px,1.6vw,24px);line-height:1.24;letter-spacing:-.02em}
.rev p{margin:0;font-size:15px;color:var(--grey)}
.rev .src{margin-top:auto;padding-top:14px;border-top:1px solid rgba(255,255,255,.14);
  font-size:12.5px;letter-spacing:.08em;color:var(--grey-2);display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap}
.rev .who{color:#fff;letter-spacing:.14em;text-transform:uppercase;font-weight:600}
.stars{display:inline-flex;gap:3px}
.stars svg{width:13px;height:13px;fill:var(--teal-lite)}
/* Отзывы на светлой секции: без этого текст был серым #CDCDCD на бумаге (контраст 1.4) */
.light .rev{border-color:rgba(10,10,10,.18)}
.light .rev:hover{border-color:rgba(46,108,126,.7);background:rgba(46,108,126,.06)}
.light .rev p{color:#41464A}
.light .rev .src{border-top-color:rgba(10,10,10,.14);color:#5B6064}
.light .rev .who{color:var(--ink)}
.light .stars svg{fill:var(--teal)}

/* ============================================================
   Галерея до/после
   ============================================================ */
.filters{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:clamp(28px,3vw,46px)}
.filters button{background:none;border:1px solid rgba(255,255,255,.28);color:var(--grey);
  padding:9px 20px;font-size:12.5px;letter-spacing:.1em;text-transform:uppercase;cursor:pointer;
  transition:all .3s var(--ease-quint)}
.filters button:hover{border-color:#fff;color:#fff}
.filters button.act{background:#fff;border-color:#fff;color:var(--ink);font-weight:600}
.cases{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(20px,2.4vw,34px)}
.case{border:1px solid rgba(255,255,255,.16);overflow:hidden;display:flex;flex-direction:column;
  transition:opacity .4s,transform .4s,border-color .3s}
.case:hover{border-color:rgba(95,163,181,.5)}
.case.hid{display:none}
.ba{position:relative;aspect-ratio:16/11;background:var(--ink-2);overflow:hidden;
  cursor:ew-resize;touch-action:none;user-select:none;-webkit-user-select:none}
/* ВАЖНО: слои .before/.after обязаны быть position:absolute + inset:0.
   Со static-потоком их высота = 0 (единственный ребёнок — абсолютный <svg>),
   а clip-path:inset() считается от border-box — при нулевой высоте область
   отсечения вырождается и ОБА слоя пропадают. Именно из-за этого сравнение
   «до / после» выглядело пустым прямоугольником и не реагировало на ползунок. */
.ba .before,.ba .after{position:absolute;inset:0}
.ba svg,.ba img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  display:block;pointer-events:none;-webkit-user-drag:none;user-select:none}
.ba .after{clip-path:inset(0 0 0 var(--x,50%))}
.ba .before{clip-path:inset(0 calc(100% - var(--x,50%)) 0 0)}
/* will-change поднимаем только на время перетаскивания (класс ставит app.js) */
.ba.drag .before,.ba.drag .after{will-change:clip-path}
.ba .hnd{position:absolute;top:0;bottom:0;left:var(--x,50%);width:2px;
  background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.35);
  transform:translateX(-1px);pointer-events:none;z-index:3}
/* ПЕРФ 06.08: backdrop-filter снят — на странице до 12 галерей «до/после»,
   то есть до 12 постоянных размывающих слоёв ради 2 px блюра под ручкой. */
.ba .hnd::after{content:'';position:absolute;top:50%;left:50%;width:44px;height:44px;
  transform:translate(-50%,-50%);border:1px solid #fff;border-radius:50%;
  background:rgba(10,10,10,.72)}
.ba .hnd::before{content:'';position:absolute;top:50%;left:50%;width:26px;height:12px;z-index:1;
  transform:translate(-50%,-50%);
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='12' fill='none' stroke='%23ffffff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 2 2 6l4 4M20 2l4 4-4 4'/%3E%3C/svg%3E") center/26px 12px no-repeat}
.ba:focus-visible{outline:2px solid var(--teal-lite);outline-offset:-2px}
.ba:focus-visible .hnd::after{border-color:var(--teal-lite);border-width:2px}
.ba .lb{position:absolute;top:12px;z-index:4;font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;
  color:#fff;background:rgba(10,10,10,.72);padding:4px 10px;pointer-events:none}
.ba .lb-b{left:12px}
.ba .lb-a{right:12px}
.ba-hint{position:absolute;left:50%;bottom:12px;z-index:4;transform:translateX(-50%);
  font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;
  color:rgba(255,255,255,.9);background:rgba(10,10,10,.6);padding:4px 12px;
  pointer-events:none;transition:opacity .3s}
.ba.touched .ba-hint{opacity:0}
.case-body{padding:22px}
.case-body h4{margin-bottom:8px}
.case-body .small{margin:0}
.case-tags{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}
.case-tags span{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--teal-lite);
  border:1px solid rgba(95,163,181,.4);padding:4px 10px}

/* ============================================================
   Прайс
   ============================================================ */
.price-tbl{width:100%;border-collapse:collapse}
.price-tbl th{text-align:left;font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--grey-2);font-weight:600;padding:0 0 16px;border-bottom:1px solid rgba(255,255,255,.2)}
.light .price-tbl th{border-bottom-color:rgba(10,10,10,.2);color:#55595D}
.price-tbl td{padding:17px 0;border-bottom:1px solid rgba(255,255,255,.1);vertical-align:top;font-size:15.5px}
.light .price-tbl td{border-bottom-color:rgba(10,10,10,.1)}
.price-tbl td:last-child,.price-tbl th:last-child{text-align:right;white-space:nowrap;
  font-variant-numeric:tabular-nums;font-weight:600}
.price-tbl td .small{margin:5px 0 0}
.price-tbl th+th,.price-tbl td+td{padding-left:20px}

.tblscroll{width:100%}
@media (max-width:900px){
  .tblscroll--wide{overflow-x:auto;-webkit-overflow-scrolling:touch;
    scrollbar-color:rgba(255,255,255,.4) transparent}
  .tblscroll--wide .price-tbl{min-width:520px}
  /* Двухколоночные таблицы: цена переносится под название */
  .tblscroll:not(.tblscroll--wide) .price-tbl td:last-child{white-space:normal}
  .tblscroll:not(.tblscroll--wide) .price-tbl td+td{padding-left:14px;width:32%}
}

/* Финансовые крючки */
.fin{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(20px,2.4vw,34px)}
.fincard{min-width:0}
.fincard{border:1px solid rgba(255,255,255,.18);padding:clamp(24px,2.6vw,38px)}
.light .fincard{border-color:rgba(10,10,10,.18)}
.fincard b{display:block;font-size:clamp(28px,3vw,44px);font-weight:700;letter-spacing:-.03em;
  line-height:1;margin-bottom:14px;color:var(--teal-lite)}
.light .fincard b{color:var(--teal)}

/* ============================================================
   Шаги протокола
   ============================================================ */
.steps{counter-reset:st}
.step{display:grid;grid-template-columns:minmax(90px,10%) minmax(0,1fr) minmax(0,1fr);gap:clamp(18px,3vw,54px);
  padding-block:clamp(28px,3.4vw,54px);border-top:1px solid rgba(255,255,255,.14);align-items:start}
.light .step{border-top-color:rgba(10,10,10,.14)}
.step .n{font-size:clamp(22px,2.4vw,34px);font-weight:700;color:var(--teal-lite);letter-spacing:-.02em;line-height:1}
.light .step .n{color:var(--teal)}
.step p{margin:0}

/* ============================================================
   Формы
   ============================================================ */
/* ГОТЧА: repeat(2,1fr) = minmax(auto,1fr); min-content у input[type=date]/select
   раздвигал колонки шире контейнера — форма вылезала на 106 px в диапазоне 901–1180 px. */
.form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}
.field{display:flex;flex-direction:column;gap:8px;min-width:0}
.field.full{grid-column:1/-1}
.field label{font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--grey-2);font-weight:600}
.light .field label{color:#55595D}
/* ── НАТИВНЫЕ КОНТРОЛЫ: ГАСИМ СИСТЕМНУЮ ОТРИСОВКУ (фидбэк клиентки 11.08) ────
   На macOS Safari <select> и текстовые поля с appearance:auto рисует САМА
   система: на тёмной форме появлялся белый прямоугольник со стрелочками
   (скрин 23-27-07), а раскрытый список был белым по белому — пунктов не
   видно (скрин 23-28-19). На Windows/Chrome тот же код выглядел нормально,
   поэтому у владельца баг не воспроизводился.
   Лечим тремя вещами сразу:
   1) appearance:none — снимает системный виджет и его белый фон/рамку;
   2) своя стрелка фоновой SVG-картинкой + место под неё в padding-right;
   3) color-scheme:dark — красит ВЫПАДАЮЩИЙ СПИСОК (его рисует ОС, стилями
      его не достать) в тёмную схему; плюс явные цвета на <option> для тех
      движков, где список красится по option.
   На светлой секции (калькулятор) — то же, но color-scheme:light. */
.field input,.field textarea,.field select{
  width:100%;min-width:0;max-width:100%;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.22);color:#fff;
  padding:14px 16px;font-size:16px;transition:border-color .25s,background-color .25s;border-radius:0}
/* appearance:none — всем полям КРОМЕ флажка/радио: у флажка согласия
   (.field.consent input) снятие системной отрисовки убрало бы саму галочку. */
.field input:not([type=checkbox]):not([type=radio]),.field textarea,.field select{
  -webkit-appearance:none;appearance:none}
.field input,.field textarea,.field select,form[data-form],#calc{color-scheme:dark}
.field select{
  padding-right:46px;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1.5 7 7.5l6-6' fill='none' stroke='%23CDCDCD' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 16px center;background-size:14px 9px}
.field select::-ms-expand{display:none}
.field select option{background:#111213;color:#fff}
.light .field input,.light .field textarea,.light .field select{
  background:rgba(255,255,255,.7);border-color:rgba(10,10,10,.22);color:var(--ink)}
.light .field input,.light .field textarea,.light .field select,.light #calc{color-scheme:light}
.light .field select{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1.5 7 7.5l6-6' fill='none' stroke='%230A0A0A' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 16px center;background-size:14px 9px}
.light .field select option{background:#fff;color:var(--ink)}
/* Календарь/спиннеры у полей даты и чисел рисует ОС — на тёмной форме это
   белый значок. Поле даты у нас текстовое с маской, значку взяться неоткуда,
   но правило страхует и type=date/number, если их когда-нибудь вернут. */
.field input[type=date]::-webkit-calendar-picker-indicator,
.field input::-webkit-inner-spin-button,
.field input::-webkit-outer-spin-button{filter:invert(1) opacity(.6)}
.light .field input[type=date]::-webkit-calendar-picker-indicator,
.light .field input::-webkit-inner-spin-button,
.light .field input::-webkit-outer-spin-button{filter:none}
.field input:focus,.field textarea:focus,.field select:focus{outline:none;border-color:var(--teal-lite);
  background:rgba(46,108,126,.12)}
.field input:focus-visible,.field textarea:focus-visible,.field select:focus-visible{
  outline:2px solid var(--teal-lite);outline-offset:1px}
.light .field input:focus,.light .field textarea:focus,.light .field select:focus{
  border-color:var(--teal);background:rgba(46,108,126,.1)}
.field textarea{resize:vertical;min-height:112px}
.field .err{font-size:12.5px;color:#F0A0A0;min-height:0}
.light .field .err{color:#B3261E}
.field .fhint{font-size:12px;color:var(--grey-2);letter-spacing:.01em}
.light .field .fhint{color:#55595D}
.field.bad .fhint{color:#F0A0A0}
.light .field.bad .fhint{color:#B3261E}
.field.bad input,.field.bad textarea,.field.bad select{border-color:#F0A0A0}
.light .field.bad input,.light .field.bad textarea,.light .field.bad select{border-color:#B3261E}
/* Ползунки калькулятора: без своих стилей нативный range получал padding/рамку поля */
.field input[type=range]{
  -webkit-appearance:none;appearance:none;background:transparent;border:0;padding:10px 0;height:auto}
.field input[type=range]:focus{background:transparent}
.field input[type=range]::-webkit-slider-runnable-track{
  height:3px;background:rgba(10,10,10,.22);border-radius:2px}
.field input[type=range]::-moz-range-track{height:3px;background:rgba(10,10,10,.22);border-radius:2px}
.field input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:22px;height:22px;margin-top:-9.5px;border-radius:50%;
  background:var(--teal);border:2px solid #fff;box-shadow:0 1px 5px rgba(0,0,0,.28);cursor:pointer}
.field input[type=range]::-moz-range-thumb{
  width:18px;height:18px;border-radius:50%;background:var(--teal);border:2px solid #fff;cursor:pointer}
.slots{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:10px}
.slot{background:none;border:1px solid rgba(255,255,255,.24);color:var(--grey);padding:12px 6px;
  font-size:14px;cursor:pointer;transition:all .25s var(--ease-quint);font-variant-numeric:tabular-nums}
.light .slot{border-color:rgba(10,10,10,.24);color:#4A4E52}
.slot:hover{border-color:#fff;color:#fff}
.light .slot:hover{border-color:var(--ink);color:var(--ink)}
.slot.act{background:var(--teal);border-color:var(--teal);color:#fff;font-weight:600}
.slot[disabled]{opacity:.32;cursor:not-allowed;text-decoration:line-through}
/* flex-direction обязателен: элемент несёт сразу .field и .consent, а .field
   выше по файлу задаёт column — без этой строки чекбокс согласия вставал
   НАД текстом, а не рядом с ним (проверено на всех ширинах). */
.consent{display:flex;flex-direction:row;gap:12px;align-items:flex-start;font-size:12.5px;color:var(--grey-2);line-height:1.5}
.consent input{width:19px;height:19px;flex:none;margin-top:2px;accent-color:var(--teal)}
/* Согласие 152-ФЗ обязательно, но текста ошибки у него не было: блок .consent
   не содержал своего .err, и пользователь видел лишь то, что форма «молчит».
   .err кладём на отдельную строку flex-обёртки. */
.consent{flex-wrap:wrap}
.consent .err{flex-basis:100%;margin-left:31px}
.consent.bad input{outline:2px solid #F0A0A0;outline-offset:2px}
.light .consent.bad input{outline-color:#B3261E}
.consent a{text-decoration:underline}
.formok{display:none;border:1px solid var(--teal-lite);background:rgba(46,108,126,.14);
  padding:22px 24px;gap:14px;align-items:flex-start}
.formok.on{display:flex}
.formok svg{width:24px;height:24px;flex:none;margin-top:2px}
.formok svg path{fill:none;stroke:var(--teal-lite);stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

/* ============================================================
   ЗАГЛАВНЫЙ ЭКРАН «светлая половина + снимок»
   ------------------------------------------------------------
   Фидбэк 06.08 (фото 15-49-54): «на заглавных экранах текст не должен
   заходить на картинку — разнести». Раньше заголовок лежал тремя
   абсолютными слоями ПОВЕРХ обеих половин и резался ровно по границе:
   правая половина букв уходила белым на тёмный снимок и читалась как
   обрубок. Теперь вся типографика — обычный поток внутри светлой
   колонки, снимок — отдельная колонка, стык растушёван градиентом.
   Побочный выигрыш: длину строки определяет ширина колонки, поэтому и
   RU, и более длинный EN держатся в двух строках без «по слову на строку».
   ============================================================ */
/* ── ЗАГЛАВНЫЙ ЭКРАН ЗАНИМАЕТ ЭКРАН ЦЕЛИКОМ (правка владельца 12.08) ───────
   БЫЛО: min(94svh,940px) — при вьюпорте 900 px блок получал 846 px, и под ним
   на первом экране торчала ЧЁРНАЯ ПОЛОСА следующей секции высотой ~55 px:
   и светлая колонка, и снимок обрывались резкой линией. Ровно то, на что
   жаловался владелец («блоки с фоном обрываются резкой полосой»).
   СТАЛО: 100 svh — полосы нет ни на одной высоте окна. Потолок в пикселях
   снят: именно он и делал полосу тем шире, чем выше окно. */
.splithero{position:relative;min-height:100vh;min-height:100svh;display:grid;
  grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr);overflow:hidden;background:var(--ink)}
.splithero .sh-l{position:relative;z-index:2;background:var(--paper);color:var(--ink);
  display:flex;flex-direction:column;justify-content:center;gap:clamp(14px,1.9vw,30px);
  padding:calc(var(--header-h) + var(--bar-h) + clamp(22px,3vw,52px))
          clamp(20px,2.6vw,48px) clamp(28px,3.4vw,58px) var(--edge)}
/* Скрим под шапкой. Верхняя панель на первом экране прозрачная и набрана
   белым, а левая половина заглавного экрана — светлая бумага: логотип
   «ДЕНТАЛ МЕД» вставал белым по светлому и практически не читался.
   Затемняем ровно полосу высотой шапки, к контенту гардиент сходит на нет —
   ниже начинается обычная светлая колонка. */
.splithero .sh-l::before{content:'';position:absolute;left:0;right:0;top:0;z-index:1;
  height:calc(var(--header-h) + var(--bar-h) + clamp(14px,2vw,28px));pointer-events:none;
  background:linear-gradient(180deg,rgba(10,10,10,.86),rgba(10,10,10,.5) 62%,rgba(10,10,10,0))}
.splithero .sh-l>*{position:relative;z-index:2}
.splithero .sh-r{background:var(--ink);position:relative;overflow:hidden}
.splithero .sh-r img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:.62;filter:saturate(.85)}
/* растушёвка стыка: «шва» между бумагой и кадром не видно */
.splithero .sh-r::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,var(--paper) 0,rgba(241,240,237,.55) 4%,rgba(241,240,237,0) 17%,
    rgba(10,10,10,0) 62%,rgba(10,10,10,.45) 100%)}
/* ── НИЗ СНИМКА НЕ РУБИТСЯ О ЧЁРНУЮ СЕКЦИЮ (правка владельца 12.08) ────────
   Автоскан стыков: под правой половиной заглавного экрана кадр яркостью 163
   обрывался в --ink (яркость 12) одной строкой. Кадр уводим в цвет следующей
   секции — снимок «уходит в тень», линии стыка нет.
   Только десктопная раскладка (>900): в стопке .sh-r лежит НАД светлой
   колонкой, и затемнение низа дало бы чёрную полосу посреди первого экрана.
   Левая половина — бумажная панель, её ровная кромка это архитектура блока,
   а не срез фона, поэтому её не трогаем. */
/* ред. 2 (12.08, фидбэк «немного градиента, а не длинный шлейф»): полоса
   сокращена со 150 px (≈14 vh на 1080) до ≤7 vh, тень собрана у самой кромки —
   снимок «доезжает» вниз почти целиком, стык остаётся мягким. */
@media (min-width:901px){
  .splithero .sh-r::before{content:'';position:absolute;left:0;right:0;bottom:-2px;
    height:clamp(46px,7vh,96px);z-index:2;pointer-events:none;
    background:linear-gradient(180deg,rgba(10,10,10,0),rgba(10,10,10,.22) 54%,rgba(10,10,10,.7) 82%,var(--ink))}
}
.sh-side{max-width:44ch}
.sh-side .over{margin-bottom:12px}
.sh-side .lead{font-size:clamp(15.5px,1.1vw,18.5px);color:#4A4E52;margin:0}
.sh-title{margin:0}
.sh-title h1{font-size:clamp(32px,4.3vw,72px);line-height:1.03;letter-spacing:-.035em;
  color:var(--ink);max-width:15ch;text-wrap:balance}
.sh-under{max-width:52ch;color:var(--ink)}
.sh-under .lead{color:#3C4144;margin-bottom:0}
.sh-under .hero-cta{margin-top:clamp(18px,2.2vw,30px)}

/* ============================================================
   CTA-полоса + подвал
   ============================================================ */
.ctaband{background:var(--teal-deep);position:relative;overflow:hidden}
.ctaband .in{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:var(--gap);align-items:center}
.ctaband .in>*{min-width:0}
/* gap ≥16px: скошенные ::before кнопок выступают ~6px с каждой стороны */
.ctaband .btns{display:flex;flex-wrap:wrap;gap:18px}
.ctaband .tel{font-size:clamp(24px,2.6vw,40px);font-weight:700;letter-spacing:-.02em;display:inline-block;margin-bottom:8px}

.foot{background:var(--ink);border-top:1px solid rgba(255,255,255,.14);padding-block:clamp(50px,6vw,86px)}
.foot-top{display:grid;grid-template-columns:minmax(0,1.2fr) repeat(3,minmax(0,1fr));gap:var(--gap);
  padding-bottom:clamp(36px,4vw,60px)}
.foot-top>*{min-width:0}
.foot h4{font-size:11.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--grey-2);
  font-weight:600;margin-bottom:20px}
.foot li{margin-bottom:11px}
.foot li a{font-size:15px;color:var(--grey);transition:color .25s}
.foot li a:hover{color:#fff}
.foot-brand .logo{margin-bottom:22px}
.foot-bot{border-top:1px solid rgba(255,255,255,.14);padding-top:26px;display:flex;
  justify-content:space-between;gap:22px;flex-wrap:wrap}
.foot-bot .small{margin:0;max-width:60ch}
.disclaim{border:1px solid rgba(255,255,255,.14);padding:18px 22px;margin-top:26px}

/* ============================================================
   Утилиты появления
   ============================================================ */
.rv{opacity:0;transform:translateY(22px)}
.rv-line{display:block;overflow:hidden}
.cursor{position:fixed;top:0;left:0;width:26px;height:26px;border:1px solid rgba(255,255,255,.6);
  border-radius:50%;z-index:9998;pointer-events:none;transform:translate(-50%,-50%);
  transition:width .3s var(--ease-quint),height .3s var(--ease-quint),background-color .3s,border-color .3s;
  mix-blend-mode:difference}
.cursor.big{width:56px;height:56px;background:rgba(255,255,255,.14)}
@media (hover:none){.cursor{display:none}}

/* ============================================================
   Микрокопирайт под кнопками · подсказки · пустые состояния
   ============================================================ */
.hero-micro{margin:16px 0 0;max-width:56ch;color:rgba(255,255,255,.66)}
.light .hero-micro{color:#5B6064}
.sh-under .hero-micro,.sh-micro{color:#4E5357}
.cases-empty{margin-top:24px}
.scrollhint{display:none;margin:26px 0 0;color:var(--grey-2)}
@media (max-width:900px){.scrollhint{display:block}}
/* край прокручиваемой таблицы: видимая подсказка, что справа есть ещё колонка */
.tblscroll--wide{position:relative}
.tblscroll--wide::after{content:'';position:absolute;top:0;right:0;bottom:0;width:42px;
  pointer-events:none;background:linear-gradient(90deg,rgba(10,10,10,0),rgba(10,10,10,.92))}
.light .tblscroll--wide::after{background:linear-gradient(90deg,rgba(241,240,237,0),rgba(241,240,237,.95))}
@media (min-width:901px){.tblscroll--wide::after{display:none}}
.tblscroll--wide:focus-visible{outline:2px solid var(--teal-lite);outline-offset:4px}
.plan-price .btn+.tiny{color:var(--grey-2)}

/* ============================================================
   Стыки секций — мягкий переход вместо резкого обрыва фона
   ============================================================ */
/* ред. 2 (12.08): полоса сокращена со 110 px (≈10 vh на 1080) до ≤6 vh, и
   затемнение теперь сходит на нет к 55 % — на светлой секции вместо серой
   ленты в палец шириной остаётся тонкая деликатная тень у самой границы. */
.sec.light,.sec.tealbg{position:relative;isolation:isolate}
.sec.light::before,.sec.light::after,
.sec.tealbg::before,.sec.tealbg::after{
  content:'';position:absolute;left:0;right:0;height:clamp(34px,4.5vh,64px);
  pointer-events:none;z-index:-1}
.sec.light::before{top:0;background:linear-gradient(180deg,rgba(10,10,10,.12),rgba(10,10,10,.03) 55%,rgba(10,10,10,0))}
.sec.light::after{bottom:0;background:linear-gradient(0deg,rgba(10,10,10,.12),rgba(10,10,10,.03) 55%,rgba(10,10,10,0))}
.sec.tealbg::before{top:0;background:linear-gradient(180deg,rgba(10,10,10,.26),rgba(10,10,10,.07) 55%,rgba(10,10,10,0))}
.sec.tealbg::after{bottom:0;background:linear-gradient(0deg,rgba(10,10,10,.26),rgba(10,10,10,.07) 55%,rgba(10,10,10,0))}
/* тонкая линия ровно на границе — держит ритм и убирает «шов» */
.sec.light+.sec:not(.light),.sec:not(.light)+.sec.light,
.sec+.ctaband,.stack+.sec,.cat+.sec{border-top:1px solid rgba(255,255,255,.07)}
.sec:not(.light)+.sec.light{border-top-color:rgba(10,10,10,.1)}
.trust+.stack{border-top:0}

/* ============================================================
   Адаптив
   ============================================================ */
@media (max-width:1180px){
  .foot-top{grid-template-columns:1fr 1fr}
  .revs,.cases,.proofs,.fin{grid-template-columns:repeat(2,minmax(0,1fr))}
  .tech-stage{aspect-ratio:16/10;min-height:0}
  .tech{grid-template-columns:1fr}
  /* Кнопок в шапке две: «Позвонить» + длинный CTA «Записаться на бесплатную
     консультацию». Раньше кнопок было ТРИ и здесь пряталась средняя, вторичная;
     после её удаления nth-child(2) — это САМ CTA, прятать его нельзя.
     Вместо этого поджимаем обе кнопки, чтобы длинный текст не наехал на лого. */
  .hdr-actions{gap:10px}
  .hdr-actions .btn{padding-inline:14px;font-size:11px;letter-spacing:.07em}
}
@media (max-width:900px){
  :root{--header-h:64px}
  .grid2,.grid3,.grid4,.plans,.revs,.cases,.proofs,.fin,.form{grid-template-columns:minmax(0,1fr)}
  .trust ul{grid-template-columns:1fr 1fr}
  .trust li:nth-child(3){border-left:0}
  .trust li{border-top:1px solid rgba(255,255,255,.12)}
  .trust li:nth-child(-n+2){border-top:0}
  /* Стопка закреплённых карточек: карточка обязана быть РОВНО в экран.
     При min-height:auto она набирала 871 px при 844 svh — пока карточка
     запинена (pinSpacing:false), лишние 27 px просто срезались снизу,
     и «плашка-доказательство» уезжала за кадр. */
  [sticky-card]{grid-template-columns:minmax(0,1fr);grid-template-rows:42svh minmax(0,1fr);
    min-height:100svh;height:100svh}
  [sticky-card] .sc-media{min-height:0;order:1!important}
  [sticky-card] .sc-body{order:2!important;gap:14px;overflow:hidden;
    padding:clamp(20px,5vw,34px) var(--pad) clamp(22px,5vw,34px)}
  [sticky-card] .sc-body .lead{font-size:15.5px;line-height:1.45;margin:0}
  [sticky-card] .sc-media h3{font-size:clamp(24px,6.4vw,34px)}
  .doccard{grid-template-columns:1fr}
  .doccard .ph{aspect-ratio:4/3}
  /* ── ЗАГЛАВНЫЙ ЭКРАН на телефоне ─────────────────────────────────────
        Снимок сверху отдельной полосой, весь текст под ним на бумаге — так
        текст физически не может наехать на изображение (фидбэк 06.08).
        Стык растушёван по вертикали, «шва» не видно. */
  .splithero{grid-template-columns:minmax(0,1fr);
    grid-template-rows:clamp(200px,32svh,300px) auto;min-height:0}
  .splithero .sh-r{order:1;min-height:0}
  .splithero .sh-r img{opacity:.72}
  .splithero .sh-r::after{background:linear-gradient(180deg,
    rgba(10,10,10,.5),rgba(10,10,10,0) 38%,rgba(241,240,237,0) 60%,var(--paper) 100%)}
  /* На телефоне светлая колонка уезжает ПОД снимок, а шапка висит над
     снимком — он и так тёмный. Скрим шапки здесь только затемнял бы начало
     текста, поэтому его снимаем. */
  .splithero .sh-l::before{display:none}
  .splithero .sh-l{order:2;min-height:0;justify-content:flex-start;
    gap:clamp(12px,3.4vw,20px);
    padding:clamp(20px,5.6vw,32px) var(--pad) clamp(28px,7vw,40px)}
  .sh-side,.sh-under{max-width:none}
  .sh-side .over{margin-bottom:8px}
  .sh-title h1{font-size:clamp(27px,7.8vw,42px);max-width:none;line-height:1.06}
  .sh-under .hero-cta{margin-top:16px}
  /* ── Дуга на телефоне ───────────────────────────────────────────────
     Одна парабола через шесть кружков живёт только в ОДНУ строку. На
     телефоне их две (3+3), поэтому линию гасим, а «челюсть» собираем
     построчно: центральный кружок ряда крупнее боковых и стоит выше.
     Гасим ИМЕННО opacity, а не display:none — для скрытого узла
     getTotalLength() отдаёт 0, и рисование обводки ломается. */
  .bubbles{grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(10px,2.4vw,18px) 0;margin-top:0;--drop:0px}
  .bubble:nth-of-type(n){--bw:80%;--f:0;--bk:.9}
  .bubble:nth-of-type(2),.bubble:nth-of-type(5){--bw:94%;--f:0;--bk:1}
  .ctaband .in{grid-template-columns:1fr}
  .step{grid-template-columns:1fr;gap:14px}
  /* ── ПИННИРОВАННЫЙ КАТАЛОГ живёт и на телефоне ──────────────────────
     Раньше секция здесь «расплющивалась» в обычную стопку (height:auto,
     все слайды opacity:1), а JS при этом продолжал её пинить на 2000 px —
     получался мёртвый экран без единого изменения картинки.
     Теперь сцена та же: 100svh, snap по слайдам, — меняются ПАРАМЕТРЫ:
     одна колонка, компактный кегль, а переход идёт opacity+translate БЕЗ
     blur (размытие полноэкранного слоя на телефоне стоит кадров). */
  .cat{height:100svh;overflow:hidden}
  /* каталог держит тот же боковой отступ, что и .wrap */
  .cat-inner{position:absolute;inset:0;grid-template-columns:minmax(0,1fr);
    padding:calc(var(--header-h) + var(--bar-h) + 8px) var(--edge) 52px;gap:0}
  .cat-nav{display:none}
  .cat-stage{position:relative;height:auto;overflow:hidden}
  .cat-slide{position:absolute;inset:0;grid-template-columns:minmax(0,1fr);
    gap:0;align-content:start;transform:translateX(16px);filter:none;
    transition:opacity .5s var(--slide-ease),transform .5s var(--slide-ease),
               visibility 0s .5s}
  .cat-slide.act{filter:none;
    transition:opacity .5s var(--slide-ease),transform .5s var(--slide-ease),
               visibility 0s 0s}
  .cat-slide.out{transform:translateX(-16px);filter:none}
  .cat-slide .over{margin-bottom:9px}
  .cat-l{gap:9px}
  .cat-l h3{font-size:clamp(24px,6.6vw,32px)}
  .cat-l .lead{font-size:14px;line-height:1.4;max-width:none;margin:0;
    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
  .cat-l .tlink{padding-top:8px;padding-bottom:8px;align-self:flex-start}
  .cat-r{margin-top:10px;gap:0}
  .cat-r li a{padding:12px 0;gap:12px}
  .cat-r li span:first-child{font-size:12.4px;line-height:1.28}
  .cat-r li .pr{font-size:11.5px}
  .cat-r>.small{display:none}
  .cat-prog{left:var(--edge);right:var(--edge);bottom:14px}
  .cat-hint{right:var(--edge);bottom:24px;font-size:10px;letter-spacing:.12em}

  /* ── КЛКТ на телефоне ────────────────────────────────────────────────
     Фидбэк 06.08: мобильный вид этой секции (фото 13-30-35) отмечен как
     «хорошо» — снимок во весь экран, текст внизу на плотной подложке.
     Сохраняем ровно его: обе половины ложатся в одну ячейку сетки,
     градиент снизу становится плотнее, чтобы контраст текста держался
     на любом кадре снимка. */
  .cbctsec{grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto;min-height:0}
  /* Снимок отдельной полосой сверху, текст под ним на тёмной подложке.
     Верх полосы затемнён под шапку, низ уходит в фон страницы — это та
     самая «градиент-подложка», только текст на неё не наезжает: обновлённый
     снимок кабинета почти белый, и белые буквы поверх него не читались бы
     ни при каком скриме. */
  .cbct-media{min-height:min(46svh,380px);aspect-ratio:16/10}
  /* на телефоне текст стоит ПОД снимком, на своей подложке --ink, поэтому
     тут скрим нужен только под шапкой сверху и как растушёвка вниз. Верх
     ослаблен с .5 до .34: иначе отзеркаленный томограф в левой части кадра
     снова уходил в темноту (правка владельца 06.08). */
  .cbct-media::after{background:linear-gradient(180deg,
    rgba(10,10,10,.34),rgba(10,10,10,0) 26%,rgba(10,10,10,0) 56%,rgba(10,10,10,.5) 84%,var(--ink) 100%)}
  .cbct-copy{justify-content:flex-start;gap:10px;margin-top:calc(-1 * clamp(16px,5vw,30px));
    padding:0 var(--pad) clamp(30px,8vw,48px)}
  .cbct-copy h2{font-size:clamp(26px,7vw,38px);max-width:none}
  .cbct-copy .lead{font-size:14.5px;line-height:1.45;max-width:none}
  .cbct-fact{max-width:none;padding-left:14px}
  .cbct-fact b{font-size:clamp(21px,6vw,28px)}
  .cbct-fact span{font-size:13px}
  .teamhero{min-height:66svh}
  .teamrow figure{width:min(20.5vw,118px)}
  .teamrow figure:nth-child(n+5){display:none}
  /* Подпись шире своей фигуры (80 px на 390) — фамилии наезжали друг на
     друга и лежали прямо на снимке. Уменьшенный кегль и нулевой трекинг
     держат каждую в своей колонке, а подпись съезжает С фотографии вниз:
     между рядом портретов и фамилиями появляется воздух (фидбэк 06.08
     «тексты с врачами на мобиле разъезжаются»). */
  .teamrow{gap:clamp(7px,2.6vw,26px)}
  .teamrow figcaption{font-size:9px;letter-spacing:0;margin-top:2px;
    line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* задаём именно ПЕРЕМЕННУЮ: перекрыв здесь сам padding, мы бы отключили
     раскрытие рамки — heroFrame() скрабит --hero-pad, а не padding. */
  .hero-inner{--hero-pad:14px;padding-top:var(--hero-pad)}
  .hero-frame{flex-direction:column;min-height:76svh}
  .hero-eyebrow{position:absolute;top:14px;left:16px;right:16px;text-align:left;max-width:none;
    font-size:9.5px;letter-spacing:.16em}
  .hero-copy{max-width:100%;padding:56px 18px 22px}
  .hero .d1{font-size:clamp(26px,7.4vw,38px)}
  .hero-facts{gap:14px}
  .hero-facts div{max-width:none;font-size:12.5px}
  .hero-cta .btn{padding-inline:24px}
  .foot-top{grid-template-columns:1fr}
}
@media (max-width:430px){
  /* 2-line-guard (фидбэк 06.08 «заголовки RU и EN — в 1–2 строки»).
     Кегль подобран по САМОМУ ДЛИННОМУ варианту из двух языков: английские
     заголовки на 15–20 % длиннее русских, и раньше «Treatment planned around
     your own biometrics» уходило в три строки там, где русский укладывался
     в две. Меряли на 390 и 360 px, обе локали. */
  /* Заголовку отдаём ещё ~10 px ширины (боковой отступ блока копии) и чуть
     плотнее трекинг — этого хватает, чтобы длинная английская строка
     «Treatment planned around» встала целиком и заголовок остался в двух
     строках БЕЗ дальнейшего уменьшения кегля. */
  .hero-copy{padding-inline:13px}
  .hero .d1{font-size:clamp(22px,6.25vw,30px);line-height:1.08;letter-spacing:-.042em}
  .splithero .sh-title h1{font-size:clamp(26px,7.4vw,38px)}
  .hero-cta .btn,.sh-under .btn{flex:1 1 100%;min-width:0}
  .hero-facts div{font-size:12px}
}
@media (max-width:560px){
  .docfacts{grid-template-columns:repeat(2,minmax(0,1fr))}
  .docfacts>div:last-child{grid-column:1/-1}
  .trust ul{grid-template-columns:1fr}
  .trust li{border-left:0;border-top:1px solid rgba(255,255,255,.12)}
  .trust li:first-child{border-top:0}
  /* 2 колонки — «челюсть» вырождается, кружки становятся равными */
  .bubbles{grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(10px,3vw,16px) clamp(8px,2.6vw,14px);--drop:0px}
  .bubble:nth-of-type(n){--bw:92%;--f:0;--bk:1}
  .logo-word{font-size:19px;letter-spacing:.12em}
  .logo-mark{width:38px;height:44px}
  .addrbar{font-size:11px}
}

/* ============================================================
   ФИКСЫ АДАПТИВА (построчный аудит 2026-07-28)
   Порядок медиазапросов внутри блока: 900 → 560 → 430,
   чтобы более узкий брейкпоинт всегда выигрывал в каскаде.
   ============================================================ */

@media (max-width:900px){
  /* 1. Кнопки шапки вставали ВПЛОТНУЮ к логотипу: замер @768 давал
        logoRight=293 и actLeft=293, а скошенный ::before кнопки выступает
        ещё на ~5 px и наезжал на слово «ДЕНТАЛ МЕД». Порог был 560 px —
        поднимаем до 900: на планшете действия живут в бургер-меню. */
  .hdr-actions{display:none}

  /* 2. teamhero (Врачи) на телефоне. Фидбэк 06.08 (фото 13-31-00): портреты
        резали слово OUR TEAM пополам и заголовок не читался. Наложения
        больше нет — заголовок сверху, ряд портретов под ним, между ними
        честный отступ. Кегль подобран так, чтобы и «КОМАНДА», и «OUR TEAM»
        стояли в ОДНУ строку на 360 px. */
  .teamhero{min-height:0;justify-content:flex-start;
    padding-top:calc(var(--header-h) + var(--bar-h) + clamp(22px,6vw,52px));
    padding-bottom:0}
  .teamhero h2{margin-bottom:clamp(16px,4.6vw,30px);font-size:clamp(38px,12vw,74px);
    line-height:1;padding-inline:var(--pad)}

  /* 3. Сравнительная таблица тарифов, 561–900: последняя колонка была
        прижата к правому краю и её гасил градиент-подсказка, хотя прокрутки
        нет (замер @768: scrollW=691 = clientW). Снимаем nowrap и min-width —
        таблица переносит текст и помещается целиком. Градиент и текстовая
        подсказка теперь включаются классом .can-scroll, который ставит JS
        по факту scrollWidth > clientWidth. */
  .tblscroll--wide .price-tbl{min-width:0}
  .tblscroll--wide .price-tbl td,
  .tblscroll--wide .price-tbl th{white-space:normal}
  .tblscroll--wide::after{display:none}
  .tblscroll--wide.can-scroll::after{display:block}
  .scrollhint{display:none}
  .scrollhint.can-scroll{display:block}

  /* 4. Тап-цели. Самостоятельные CTA-ссылки .tlink были 27 px, пункты
        подвала — 19 px, телефон/почта — 17–21 px. Инлайновые ссылки внутри
        абзаца не трогаем (для них порог 40 px не действует). */
  .tlink{padding-top:12px;padding-bottom:12px}
  .foot li{margin-bottom:0}
  .foot li a{display:inline-block;padding-block:11px;line-height:1.25}
  a[href^="tel:"]:not(.btn):not(.tel),
  a[href^="mailto:"]:not(.btn){display:inline-block;padding-block:12px}
}

@media (max-width:560px){
  /* 2-line-guard для «внутренних» заглавных экранов (Технологии, Контакты,
     Услуги): их h1 берёт общий .d1 с нижней границей 34 px, и «Технологии,
     которые видно в результате» / «Technology you can see in the result»
     разъезжались на ТРИ строки. Кегль ниже — обе локали в две строки. */
  .wrap>h1.d1{font-size:clamp(26px,7.1vw,31px);line-height:1.06}
  /* тот же гард для страницы «Врачи»: её h1 набран классом .d2 */
  .wrap>h1.d2{font-size:clamp(20px,5.8vw,26px);line-height:1.07}

  /* 5. Плашка-доказательство в закреплённых карточках: подпись и текст
        стояли в строку, и на телефоне текстовая колонка сжималась
        до ~180 px (четыре строки на два слова). Ставим в столбик.
        На планшете строка помещается — там не трогаем. */
  .sc-proof{flex-direction:column;align-items:flex-start;gap:6px}

  /* 6. Плашка адреса: строка ломалась на две (spanH=35.6 при высоте полосы
        38 px) и упиралась в края. Хвост про метро скрываем — остаётся
        одна строка; он продублирован на странице контактов. */
  .addrbar{line-height:1.3}
  .addrbar .ab-metro{display:none}

  /* 7. Сравнительная таблица тарифов на телефоне: три колонки в 350 px не
        помещались (замер @390: scrollW=520 при clientW=350) — колонка
        «Расширенный» полностью уезжала за экран, а вторая обрезалась
        по букве. Разворачиваем строку в карточку: услуга сверху, под ней
        два тарифа с подписями из data-c. */
  .tblscroll--wide{overflow:visible}
  .tblscroll--wide::after{display:none!important}
  .tblscroll--wide .price-tbl,
  .tblscroll--wide .price-tbl tbody,
  .tblscroll--wide .price-tbl tr,
  .tblscroll--wide .price-tbl td{display:block;width:auto}
  .tblscroll--wide .price-tbl thead{display:none}
  .tblscroll--wide .price-tbl tr{padding:16px 0;border-bottom:1px solid rgba(255,255,255,.1)}
  .tblscroll--wide .price-tbl tr:last-child{border-bottom:0}
  .tblscroll--wide .price-tbl td{padding:0;border:0;text-align:left;white-space:normal}
  .tblscroll--wide .price-tbl td:first-child{font-size:16px;font-weight:600;margin-bottom:10px}
  .tblscroll--wide .price-tbl td+td{
    display:flex;align-items:baseline;justify-content:space-between;gap:14px;
    padding:7px 0 0;font-size:14.5px;font-weight:400;color:var(--grey);text-align:right}
  .tblscroll--wide .price-tbl td+td::before{
    content:attr(data-c);flex:none;text-align:left;
    font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--grey-2)}
  .light .tblscroll--wide .price-tbl tr{border-bottom-color:rgba(10,10,10,.1)}
  .light .tblscroll--wide .price-tbl td+td{color:#41464A}
  .light .tblscroll--wide .price-tbl td+td::before{color:#55595D}
}

/* 9. Заголовок направления в пиннированном каталоге разбит на жёсткие
       строки (<span class="ln">), поэтому длинное слово не может уехать
       на следующую строку и рвалось посреди («восстановлени / е» на
       1280×800 и 1024). Кегль подобран так, чтобы самое длинное слово
       («восстановление», 14 знаков) помещалось в колонку; hyphens —
       страховка для будущих правок текста. */
@media (min-width:901px){
  /* hyphens:manual — слова НЕ рвутся переносом (фидбэк 31.07: «без обрыва
     слов»). Кегль и так подобран под самое длинное слово раздела. */
  .cat-l h3{font-size:clamp(28px,3.6vw,60px);hyphens:manual}
}

/* 9b. НИЗКИЙ портретный экран (360×640, 375×667). В одну колонку восемь
       строк прайса + заголовок + лид не помещаются: сцена 478 px, контенту
       нужно 663–677, и хвост списка срезало overflow'ом сцены.
       Список разворачиваем в ДВА столбца по четыре строки — эффект и весь
       контент остаются, меняется только раскладка внутри слайда. */
@media (max-width:900px) and (max-height:760px){
  /* Верхний клиренс сцены считался как шапка + плашка адреса (64+38).
     Но к моменту, когда каталог доходит до пина (y≈1000), плашка уже
     уехала вверх (.addrbar.hide) — 38 px резервировались впустую.
     Освободившаяся высота уходит строкам прайса: тап-цель снова 40 px. */
  .cat-inner{padding-top:calc(var(--header-h) + 10px);padding-bottom:36px}
  .cat-slide .over{margin-bottom:5px}
  .cat-l{gap:5px}
  .cat-l h3{font-size:clamp(21px,5.6vw,26px)}
  .cat-l .lead{font-size:12.5px;-webkit-line-clamp:1}
  .cat-l .tlink{padding-top:4px;padding-bottom:4px;font-size:11.5px}
  .cat-l{gap:7px}
  .cat-r{margin-top:4px}
  /* кегль подобран так, чтобы длинные названия («Профессиональная гигиена
     с индексной оценкой») ложились В ОДНУ строку: тогда на строку хватает
     13 px паддинга и тап-цель остаётся 40 px даже на 640 px высоты. */
  .cat-r li a{padding:11px 0;gap:8px}
  .cat-r li span:first-child{font-size:11px;line-height:1.22}
  .cat-r li .pr{font-size:10.5px}
}

/* 9c. 360×640 — самый низкий портрет из матрицы: не хватало ровно 6 px
       на двух слайдах из четырёх. Строка прайса теряет 1 px паддинга
       сверху и снизу (38 px вместо 40) — это дешевле, чем прятать лид
       или срезать хвост списка. */
@media (max-width:900px) and (max-height:660px){
  .cat-r li a{padding:10px 0}
}

/* 10. Ландшафтный телефон (844×390, 932×430). Высоты для полноэкранной
       сцены мало, но эффект остаётся — меняется РАСКЛАДКА внутри сцены:
       слайд каталога снова в две колонки (ширины хватает), список услуг
       в два столбца по 4 строки, кегль и вертикальные отступы сжаты.
       Раньше здесь секции «расплющивались» в поток, и пин из JS работал
       вхолостую — экран замирал на 2000 px прокрутки.
       Блок идёт ПОСЛЕ мобильного, поэтому выигрывает и на 844×390. */
@media (max-height:620px){
  .cat{height:100svh;overflow:hidden}
  .cat-inner{position:absolute;inset:0;grid-template-columns:minmax(0,1fr);
    padding:calc(var(--header-h) + 6px) var(--edge) 30px;
    gap:clamp(14px,2.4vw,40px)}
  .cat-nav{display:none}
  .cat-stage{position:relative;height:auto;overflow:hidden}
  .cat-slide{position:absolute;inset:0;align-content:center;
    grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);gap:clamp(16px,2.6vw,44px)}
  .cat-slide .over{margin-bottom:6px}
  .cat-l{gap:8px}
  .cat-l h3{font-size:clamp(21px,3.2vw,32px)}
  .cat-l .lead{font-size:13px;line-height:1.36;max-width:none;margin:0;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .cat-l .tlink{padding-top:6px;padding-bottom:6px;align-self:flex-start}
  .cat-r{margin-top:0}
  .cat-r ul{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 clamp(14px,2vw,28px)}
  .cat-r li a{padding:11px 0;gap:10px}
  .cat-r li span:first-child{font-size:11.6px;line-height:1.24}
  .cat-r li .pr{font-size:10.6px}
  .cat-r>.small{display:none}
  .cat-prog{bottom:12px;left:var(--edge);right:var(--edge)}
  .cat-hint{bottom:22px;right:var(--edge);font-size:9.5px}

  /* КЛКТ в альбоме: ширины хватает, поэтому две колонки остаются —
     сжимаются только вертикальные отступы и кегль. */
  .cbctsec{grid-template-columns:minmax(0,1fr) minmax(0,1fr);min-height:100svh}
  .cbct-media{grid-area:auto;min-height:0}
  .cbct-copy{grid-area:auto;justify-content:center;gap:10px;
    padding:calc(var(--header-h) + 10px) var(--edge) 24px clamp(18px,2.6vw,40px)}
  .cbct-copy h2{font-size:clamp(22px,3.4vw,34px);max-width:16ch}
  .cbct-copy .lead{font-size:13.5px;line-height:1.4;max-width:44ch}
  .cbct-fact b{font-size:clamp(20px,2.4vw,28px)}
  .cbct-fact span{font-size:12.5px}

  /* Стопка карточек в альбоме: медиа слева, текст справа — иначе на 390 px
     высоты и снимок, и абзац сжимаются до нечитаемых полосок. */
  [sticky-card]{grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:minmax(0,1fr);
    min-height:100svh;height:100svh}
  [sticky-card] .sc-media{order:1!important}
  [sticky-card] .sc-body{order:2!important;gap:10px;padding:clamp(16px,3vw,34px)}
  [sticky-card] .sc-body .lead{font-size:14px;line-height:1.4}
  [sticky-card] .sc-media h3{font-size:clamp(20px,3vw,32px)}

  /* Заглавный экран в альбоме: две колонки остаются (ширины хватает),
     весь текст — в светлой половине, снимок — в правой. Сжимаются только
     кегль и вертикальные отступы. */
  .splithero{grid-template-columns:minmax(0,1.04fr) minmax(0,.96fr);
    grid-template-rows:minmax(0,1fr);min-height:max(560px,100svh)}
  /* В альбоме колонки снова рядом и шапка накрывает светлую — скрим нужен. */
  .splithero .sh-l::before{display:block}
  .splithero .sh-l{order:0;justify-content:center;gap:clamp(8px,1.4vw,16px);
    padding:calc(var(--header-h) + 10px) clamp(16px,2.2vw,34px) 18px var(--pad)}
  .splithero .sh-r{order:0;min-height:0}
  .sh-title h1{font-size:clamp(24px,3.6vw,44px);max-width:16ch}
  .sh-side{max-width:none}
  .sh-side .lead{font-size:13.5px;line-height:1.4}
  .sh-under{max-width:none;color:var(--ink)}
  .sh-under .lead{font-size:14px;color:#3C4144}
  .sh-under .hero-cta{margin-top:12px}
  .sh-under .hero-micro,.sh-under .sh-micro{color:#4E5357}
  .sh-under .btn--ink{color:var(--ink)}
  .sh-under .btn--ink::before{border-color:rgba(10,10,10,.42)}

  .teamhero{min-height:0;justify-content:flex-start;
    padding-top:calc(var(--header-h) + var(--bar-h) + 8px);padding-bottom:0}
  .teamhero h2{margin-bottom:clamp(10px,1.8vw,22px);font-size:clamp(34px,6.6vw,86px)}
  .teamrow figure{width:min(11vw,110px)}
  .teamrow figure:nth-child(n+7){display:none}
}


/* 8. Закрытая панель аккордеона: содержимое оставалось «видимым» для
      геометрии и налезало на следующий заголовок, а скринридер читал
      скрытый текст. Прячем по-настоящему, задержка = длительности
      раскрытия, чтобы текст не пропадал в момент закрытия. */
.acc-panel>div{visibility:hidden;transition:visibility 0s .45s}
.acc-item.open .acc-panel>div{visibility:visible;transition:visibility 0s 0s}

/* 10b. Экстремально низкий экран (844×390 — телефон в альбоме). Лид
        уступает место списку: без этого хвост прайса срезался на 30+ px.
        Заголовок, ссылка-CTA и все восемь строк остаются на месте. */
@media (max-height:460px){
  .cat-l h3{font-size:clamp(18px,3vw,26px)}
  .cat-l .lead{display:none}
  .cat-l .tlink{padding-top:4px;padding-bottom:4px;font-size:11px}
  .cat-r li a{padding:6px 0}
  .cat-r li span:first-child{font-size:10.5px;line-height:1.22}
  .cat-r li .pr{font-size:10px}
}

/* ============================================================
   ТАЧ: замена кастомного курсора — состояния НАЖАТИЯ
   ------------------------------------------------------------
   Единственный эффект без прямого аналога на телефоне — кольцо,
   которое ездит за курсором и раздувается над интерактивным.
   Взамен: (1) гасим «залипающий» :hover — на тач он остаётся
   после тапа и элемент выглядит вечно активным; (2) даём тот же
   отклик на :active, пока палец на элементе. Класс .is-touch
   ставит app.js (cursor()), медиазапрос — страховка.
   ============================================================ */
html{-webkit-tap-highlight-color:rgba(95,163,181,.16)}
@media (hover:none){
  /* 1. Снимаем hover-состояния */
  .btn:hover::before{background:transparent;border-color:rgba(255,255,255,.5);
    transform:skewX(var(--skew))}
  .btn:hover{color:var(--white)}
  .btn--fill:hover::before{background:var(--teal);border-color:var(--teal)}
  .btn--ink:hover{color:var(--ink)}
  .btn--ink:hover::before{background:transparent;border-color:rgba(10,10,10,.42)}
  .tlink:hover{color:var(--teal-lite);border-color:rgba(95,163,181,.4)}
  .light .tlink:hover{color:var(--teal);border-color:rgba(46,108,126,.4)}
  .tlink:hover svg{transform:none}
  .plan:hover{transform:none;border-color:rgba(255,255,255,.18)}
  .rev:hover{border-color:rgba(255,255,255,.16);background:transparent}
  .light .rev:hover{border-color:rgba(10,10,10,.18);background:transparent}
  .case:hover{border-color:rgba(255,255,255,.16)}
  .doccard:hover .ph img{transform:none}
  .cat-r li a:hover{padding-left:0;color:inherit}
  .filters button:hover{border-color:rgba(255,255,255,.28);color:var(--grey)}
  .tech-list button:hover{color:var(--grey-2)}
  .light .tech-list button:hover{color:#5B6064}
  .slot:hover{border-color:rgba(255,255,255,.24);color:var(--grey)}
  .light .slot:hover{border-color:rgba(10,10,10,.24);color:#4A4E52}
  .foot li a:hover,.navov a:hover{color:var(--grey)}
  .acc-head:hover{color:inherit}
  .burger:hover i:nth-child(2){width:72%}
  .cat-nav button:hover{color:rgba(205,205,205,.4)}

  /* 2. Отклик на нажатие — то, что на десктопе показывает курсор */
  .btn:active::before{background:rgba(255,255,255,.92);border-color:#fff;
    transform:skewX(var(--skew)) scale(.985)}
  .btn:active{color:var(--ink)}
  .btn--fill:active::before{background:var(--teal-lite);border-color:var(--teal-lite)}
  .btn--ink:active::before{background:var(--ink);border-color:var(--ink)}
  .btn--ink:active{color:#fff}
  .tlink:active{color:#fff;border-color:#fff}
  .light .tlink:active{color:var(--ink);border-color:var(--ink)}
  .tlink:active svg{transform:translate(4px,-4px)}
  .plan:active,.rev:active,.case:active,.fincard:active{border-color:rgba(95,163,181,.7)}
  .cat-r li a:active{color:var(--teal-lite);padding-left:8px}
  .filters button:active{border-color:#fff;color:#fff}
  .slot:active{border-color:#fff;color:#fff}
  .light .slot:active{border-color:var(--ink);color:var(--ink)}
  .acc-head:active{color:var(--teal-lite)}
  .light .acc-head:active{color:var(--teal)}
  .tech-list button:active{color:#fff}
  .light .tech-list button:active{color:var(--ink)}
  .foot li a:active,.navov a:active{color:#fff}
  .doccard .ph:active img{transform:scale(1.04)}
  /* ползунок «до/после» — палец заменяет курсор ew-resize */
  .ba:active .hnd::after{border-color:var(--teal-lite);background:rgba(10,10,10,.78)}
}
body.is-touch .btn::before{transition-duration:.18s}
body.is-touch .ba{cursor:default}

/* ============================================================
   prefers-reduced-motion
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  .rv{opacity:1!important;transform:none!important}
  .cursor{display:none}
}

/* ============================================================
   EN-масштаб дисплейных заголовков (правка 06.08, приёмка «1–2 строки»)
   Английские формулировки на 10–18 % длиннее русских, и на 1440 три
   заголовка уходили в 3 строки при том же кегле: «Equipment that /
   changes how an / appointment goes» и две карточки отзывов. Русский
   масштаб НЕ трогаем — он в 2 строки укладывается. Снижение 5–9 %.
   ============================================================ */
html[lang="en"] .d2{font-size:clamp(26px,3.5vw,53px)}
html[lang="en"] .rev h3{font-size:clamp(18px,1.44vw,22px)}

/* ==========================================================================
   ФИДБЭК ВЛАДЕЛЬЦА 12.08 — МОБИЛЬНЫЕ ФИКСЫ
   ========================================================================== */

/* --- Фильтры «до/после»: сетка 2×2 вместо ряда 1+2+1 ----------------------
   БЫЛО: .filters — flex с переносом, ширина кнопки по надписи. На 390 px
   четыре разных по длине подписи вставали 1 + 2 + 1: «ВСЕ СИТУАЦИИ» одна,
   «ОБЩАЯ И ГИГИЕНА» с «ЭСТЕТИКА» парой, «ВОССТАНОВЛЕНИЕ» одна — рваная
   лесенка. СТАЛО: две ровные колонки, два ряда, кнопки одной ширины. */
@media (max-width:600px){
  .filters{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .filters button{width:100%;padding:10px 8px;font-size:11px;letter-spacing:.06em;
    text-align:center;line-height:1.25;min-height:44px}
}

/* --- Главные CTA на телефоне — во всю ширину контейнера -------------------
   Тот же калибр, что на dental-med-1: одиночная кнопка не «висит» у левого
   края, а занимает ширину блока. Исключение — .btn--sm: это компактные
   кнопки верхней панели (телефон + запись), они живут в строке шапки.
   ::before скошен на -14deg и выступает за коробку на ~h/2·tg14° ≈ 6 px с
   каждой стороны — поэтому кнопке даём поле, чтобы параллелограмм не
   упирался в кромку экрана. */
@media (max-width:600px){
  .btn:not(.btn--sm){width:calc(100% - 14px);max-width:calc(100% - 14px);margin-inline:7px}
  .btns{display:flex;flex-direction:column;align-items:stretch;gap:14px}
  .hero-cta,.ctaband .btns{align-items:stretch}
  /* ПОДПИСЬ КНОПКИ — В ОДНУ СТРОКУ (фидбэк владельца 12.08).
     Верхний регистр с трекингом .14em раздувает длинные подписи: «Talk through
     my numbers — free» требовало 346 px при кнопке 321 и ломалось надвое.
     На телефоне ужимаем кегль, трекинг и боковые поля — самая длинная подпись
     обеих локалей укладывается в строку даже на 360 px.
     Кегль текучий: RU-подпись «Записаться на бесплатную консультацию» (36
     знаков) — самая длинная на сайте, при 11,5 px ей нужно 315 px из 321 и
     поля кнопки съедались в ноль. clamp даёт 10 px на 360 и 11,5 px от 420. */
  .btn:not(.btn--sm){font-size:clamp(10px,2.75vw,11.5px);letter-spacing:.03em;
    padding-inline:16px;white-space:nowrap}
}

/* --- CTA НА БИРЮЗОВОЙ ПЛАШКЕ НЕ СЛИВАЕТСЯ С ФОНОМ ------------------------
   ФИДБЭК ВЛАДЕЛЬЦА 12.08 («кнопка не должна сливаться с фоном»).
   БЫЛО: заливка .btn--fill — var(--teal) #2E6C7E, а сама плашка .ctaband /
   .tealbg — var(--teal-deep) #1B4C59. Контраст фигуры к фону 1,6:1 — кнопка
   читалась как чуть более светлое пятно, а не как кнопка (скриншоты 21/22).
   СТАЛО: на бирюзовых плашках заливка — var(--teal-lite) #5FA3B5 (уже штатный
   акцентный тон сайта: он же на ховере) + тёмный текст. Контраст фигуры 3,5:1,
   текста 7,5:1. Вторичная кнопка получает более плотную белую рамку. */
.ctaband .btn--fill::before,.tealbg .btn--fill::before{
  background:var(--teal-lite);border-color:var(--teal-lite)}
.ctaband .btn--fill,.tealbg .btn--fill{color:var(--ink)}
.ctaband .btn--fill:hover::before,.tealbg .btn--fill:hover::before{
  background:var(--white);border-color:var(--white)}
.ctaband .btn--fill:hover,.tealbg .btn--fill:hover{color:var(--ink)}
.ctaband .btn:not(.btn--fill)::before,.tealbg .btn:not(.btn--fill)::before{
  border-color:rgba(255,255,255,.8)}

/* --- Цена в двухколоночной таблице — всегда одной строкой (аудит 12.08) -----
   БЫЛО: на <=900 px последняя колонка получала white-space:normal и жёсткую
   ширину 32 %. В RU самая длинная сумма («от 14 000 ₽») в 112 px ещё влезала,
   а в EN «from $11,500» — уже нет и рвалась на две строки («from» отдельно,
   сумма отдельно). Правка владельца «суммы одной строкой» на локали EN не
   держалась.
   СТАЛО: колонка снова nowrap и сжимается по содержимому (width:1% — таблица
   отдаёт ей ровно необходимое), остаток ширины забирает колонка с названием.
   Кегль чуть уменьшен, чтобы самая длинная сумма гарантированно вставала в
   строку и на 360 px. */
@media (max-width:900px){
  .tblscroll:not(.tblscroll--wide) .price-tbl td:last-child,
  .tblscroll:not(.tblscroll--wide) .price-tbl th:last-child{white-space:nowrap}
  .tblscroll:not(.tblscroll--wide) .price-tbl td+td,
  .tblscroll:not(.tblscroll--wide) .price-tbl th+th{padding-left:14px;width:1%}
}
@media (max-width:430px){
  .tblscroll:not(.tblscroll--wide) .price-tbl td+td{font-size:14px}
}

/* ==================== Правки по фидбэку владельца 13.08.2026 ==================== */

/* (фото 22) ПРОЗРАЧНАЯ КНОПКА НЕ ЧИТАЛАСЬ.
   Вторая кнопка первого экрана — «призрак»: только рамка rgba(255,255,255,.5)
   поверх фотографии. На светлом участке снимка (планшет в руках, свитер)
   подпись сливалась с фоном — владелец писал об этом второй раз. Даём ей
   собственную НЕПРОЗРАЧНУЮ подложку в цвет чернил и рамку в полную силу:
   форма-параллелограмм и поведение при наведении не меняются. */
.btn:not(.btn--fill):not(.btn--ink)::before{
  background:rgba(10,10,10,.72);
  border-color:rgba(255,255,255,.85);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
}
.btn:not(.btn--fill):not(.btn--ink){text-shadow:0 1px 6px rgba(0,0,0,.45)}
.btn:not(.btn--fill):not(.btn--ink):hover::before{
  background:var(--white);border-color:var(--white);backdrop-filter:none;-webkit-backdrop-filter:none;
}
.btn:not(.btn--fill):not(.btn--ink):hover{text-shadow:none}

/* (фото 23, 24, 25, 26) ТЕКСТОВЫЕ ССЫЛКИ-CTA В КАРТОЧКАХ СТОПКИ — К ПРАВОМУ
   КРАЮ. «Наши врачи», «Как мы лечим», «Что даёт подписка», «Оборудование»
   стояли у левой кромки, справа пустовала вся ширина карточки. На телефоне
   прижимаем их вправо — единый приём со всеми правками этой пачки. */
@media (max-width:900px){
  [sticky-card] .sc-body > .tlink{align-self:flex-end}
}

/* (фото 31) ЗАГЛАВНЫЙ ЭКРАН: СНИМОК УХОДИЛ ПОД ШАПКУ.
   На телефоне полоса снимка — clamp(200px,32svh,300px), а сверху её накрывает
   фиксированная шапка с адресной плашкой (~94 px). От кадра оставалась узкая
   лента, «картинку не видно». Добавляем к полосе высоту шапки — снимок
   опускается ниже неё и виден целиком. */
@media (max-width:900px){
  .splithero{
    grid-template-rows:calc(clamp(200px,32svh,300px) + var(--header-h) + var(--bar-h)) auto;
  }
  .splithero .sh-r img{object-position:center 42%}
}

/* (скрин 04:51, membership.html) ГРЯЗНЫЙ ГОРИЗОНТАЛЬНЫЙ ГРАДИЕНТ НА СТЫКЕ.
   Растушёвка .sh-r::after заливала левые 17 % снимка цветом бумаги — на
   ноутбучной и настольной ширине это читалось как грязное пятно поверх
   фотографии (владелец: «уёбищный градиент»). На десктопе убираем совсем:
   бумажная колонка и кадр стыкуются чистой вертикальной кромкой. Мобильная
   версия ::after (вертикальная растушёвка стопки) остаётся — там она
   действительно прячет шов. */
@media (min-width:901px){
  .splithero .sh-r::after{display:none}
}

/* ════════════════════════════════════════════════════════════════════════════
   ЗАКОН ВЛАДЕЛЬЦА 13.08: ФОТО-БЛОК НА ТЕЛЕФОНЕ = ПОЛНЫЙ ЭКРАН
   Дословно: «если я говорю сделать блоки больше — сделай БОЛЬШЕ, чтобы ОДИН
   БЛОК закрывал площадь экрана телефона — одна прокрутка колеса».

   ЧТО БЫЛО (замер 390×844, 13.08):
     .splithero (membership) — полоса снимка 372 px. Правка от 06.08 добавила
        к ряду высоту шапки, но кадр всё равно остался лентой: владелец на
        фото 1 обвёл ровно её и провёл линию по нижней кромке шапки —
        «картинку срезает меню».
     .cbctsec (technology) — снимок КЛКТ 380 px при секции 676 px (80 %).

   ЧТО СТАЛО:
     • .splithero: ряд снимка = 100 svh ПЛЮС высота фиксированной шапки и
       адресной плашки. Шапка накрывает свои ~94 px, а НИЖЕ неё остаётся
       ровно один экран фотографии — кадр не срезан и занимает телефон
       целиком. Текстовая колонка идёт следующим рядом, ничего не обрезано.
     • .cbct-media: пропорция 16/10 снимается, высота — ровно экран.

   svh (а не vh/dvh): выдвинутые панели мобильного браузера кадр не режут,
   высота не скачет при скролле. Первой строкой — vh-фолбэк.
   Границы: max-width:900px + portrait. Десктоп (≥901) и альбомный телефон
   не затронуты — там продолжают работать прежние правила.
   ════════════════════════════════════════════════════════════════════════ */
@media (max-width:900px) and (orientation:portrait){
  .splithero{
    grid-template-rows:calc(100vh + var(--header-h) + var(--bar-h)) auto;
    grid-template-rows:calc(100svh + var(--header-h) + var(--bar-h)) auto;
  }
  /* Кадр высокий — центр композиции держим чуть выше геометрического, иначе
     при cover в портрете диван уезжает за нижнюю кромку. */
  .splithero .sh-r img{object-position:center 46%}

  .cbctsec{min-height:100vh;min-height:100svh}
  .cbct-media{aspect-ratio:auto;min-height:100vh;min-height:100svh}
  /* ТОМОГРАФ ОБЯЗАН ОСТАТЬСЯ В КАДРЕ (владелец писал об этом дважды, 06.08).
     Чем выше кадр при ширине 390 px, тем УЖЕ вырезаемая полоса: при 380 px
     высоты cover показывал 56 % ширины снимка и аппарат попадал в кроп сам,
     а при 844 px остаётся 25 % — и центр по умолчанию (object-position:50%)
     вырезал пустую стену со столом. Аппарат стоит на ~60-79 % ширины
     оригинала, поэтому точку привязки сдвигаем вправо: окно кропа встаёт на
     0.58-0.83 и берёт томограф целиком. scaleX(-1) из базового правила
     работает ПОСЛЕ кропа — он только зеркалит уже выбранный участок. */
  .cbct-media img{object-position:78% 50%}
}
