/* Компонентные стили ядра фабрики: лёгкий CSS, системные шрифты, ноль внешних
   зависимостей. Правится ТОЛЬКО в ядре — копия, разошедшаяся с ядром, роняет гейт B. */
/* Палитра и радиус проекта живут в отдельном файле tokens.css — он генерируется
   из design/tokens.project.json выбранного арт-направления и подключается ПЕРЕД
   этим файлом. Здесь цветов нет намеренно: меняя направление, мы меняем один
   сгенерированный файл, а не компонентные стили. Шкалы фабрики — в
   ядро/дизайн/tokens.base.json. */
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font:16px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Arial,sans-serif;color:var(--ink);background:var(--surface)}
img{max-width:100%;height:auto;display:block}
a{color:var(--brand);text-decoration:none}
a:hover{color:var(--brand-d)}
.wrap{max-width:1080px;margin:0 auto;padding:0 20px}

/* header */
header{position:sticky;top:0;z-index:50;background:color-mix(in srgb, var(--surface) 95%, transparent);backdrop-filter:blur(6px);border-bottom:1px solid var(--line)}
.nav{display:flex;align-items:center;gap:14px;min-height:60px}
.logo{font-weight:800;font-size:18px;color:var(--ink);letter-spacing:.02em;white-space:nowrap;flex:0 0 auto}
.logo em{color:var(--brand);font-style:normal}
/* меню в одну строку: при нехватке места прокручивается вбок, а не ломает шапку */
.nav nav{display:flex;gap:12px;font-size:14px;margin-left:auto;align-items:center;
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;flex:1 1 auto;justify-content:flex-start}
/* когда меню влезает — прижато вправо auto-отступом ПЕРВОГО пункта; когда не влезает —
   auto схлопывается в 0 и лента скроллится от левого края, НЕ заезжая под логотип.
   (Старый justify-content:flex-end прятал начало меню под логотип без шанса доскроллить.) */
.nav nav > a:first-child{margin-left:auto}
/* промежуточные ширины: меню из 10 пунктов + сердечко + CTA не влезает при 14px —
   плавно сжимаем, чтобы до бургер-порога (900px) всё помещалось без обрезки EN */
@media(max-width:1320px){.nav nav{font-size:14px;gap:10px}}
@media(max-width:1160px){
  .nav nav{font-size:13px;gap:8px}
  .nav nav a{padding:12px 1px}
  .nav > .btn{padding:10px 13px;font-size:14px}
  .logo{font-size:17px}
  .nav{gap:10px}
}
.nav nav::-webkit-scrollbar{display:none}
.nav nav a{color:var(--ink);padding:12px 2px;display:inline-flex;align-items:center;min-height:44px;white-space:nowrap}
.nav > .btn{flex:0 0 auto;white-space:nowrap}
/* узкие экраны: логотип и CTA компактнее, меню — горизонтальная лента */
@media(max-width:1100px){
  .nav nav{font-size:13px;gap:10px;justify-content:flex-start}
  .nav nav > a:first-child{margin-left:0}
  .nav > .btn{padding:10px 14px;font-size:14px}
  .logo{font-size:16px}
}
.nav nav a[aria-current]{color:var(--brand);font-weight:600}
/* доступность: удобные тач-таргеты (≥44px) в футере и подписях */
footer .cols a{display:inline-block;padding:11px 0;min-height:44px}   /* тач-цель 44 px (аудит KUARTZ 22.09.2026) */
footer .fine a{padding:4px 0;display:inline-block}
.skip{position:absolute;left:-9999px;top:0;background:var(--brand);color:var(--surface);padding:10px 16px;border-radius:0 0 10px 0;z-index:100}
.skip:focus{left:0}
:where(a,button,input,select,summary):focus-visible{outline:3px solid var(--brand);outline-offset:2px;border-radius:4px}
.btn{display:inline-block;background:var(--brand);color:var(--surface)!important;padding:12px 22px;border-radius:12px;font-weight:600;border:0;cursor:pointer;font-size:15px;position:relative;overflow:hidden}
.btn:hover{background:var(--brand-d)}
/* блик: световая полоса пробегает по кнопке раз в ~4 секунды */
.btn::before{content:"";position:absolute;top:0;left:-80%;width:45%;height:100%;
  background:linear-gradient(115deg,transparent 0%,rgba(255,255,255,.5) 50%,transparent 100%);
  transform:skewX(-25deg) translateX(0);animation:btnShine 4s ease-in-out infinite;pointer-events:none}
@keyframes btnShine{
  0%{transform:skewX(-25deg) translateX(0)}
  22%{transform:skewX(-25deg) translateX(540%)}
  100%{transform:skewX(-25deg) translateX(540%)}
}
@media (prefers-reduced-motion: reduce){.btn::before{animation:none}}
.btn-wa{background:var(--wa)}
.btn-wa:hover{background:color-mix(in srgb,var(--wa) 88%,black)}
.btn-o{background:transparent;color:var(--brand)!important;border:1.5px solid var(--brand)}
.btn-o:hover{background:var(--bg)}
/* Telegram-синий — как в круглом виджете связи (contact-widget.js). */
.btn-tg{background:var(--tg)}
.btn-tg:hover{background:color-mix(in srgb,var(--tg) 88%,white)}
/* Пара кнопок-мессенджеров вместо формы заявки: во всю ширину, стопкой. */
.lead-btns{display:grid;gap:10px;margin:14px 0 0}
.lead-btns .btn{text-align:center;padding:14px 18px;font-size:16px}
.nav .btn{padding:8px 16px;font-size:14px}

/* hero */
.hero{background:linear-gradient(160deg,color-mix(in srgb,var(--brand) 72%,black) 0%,var(--brand) 55%,color-mix(in srgb,var(--brand) 76%,white) 100%);color:var(--surface);padding:56px 0 48px}
.hero h1{font-size:clamp(28px,4.5vw,44px);line-height:1.15;margin-bottom:14px}
.hero .sub{font-size:18px;color:color-mix(in srgb,var(--surface) 88%,var(--brand));max-width:640px}
/* Фото на герое. Ядро по умолчанию красит герой градиентом бренда — этого
   хватает, пока у проекта нет своего кадра. Если кадр есть, он ставится
   инлайновым background-image, а поверх ложится затемнение: без него белый
   заголовок на светлом рендере не читается, а проверять контраст на каждой
   фотографии никто не будет. */
.hero[style*="background-image"]{background-size:cover;background-position:center;position:relative}
.hero[style*="background-image"]::before{content:"";position:absolute;inset:0;
  background:linear-gradient(105deg,rgba(0,0,0,.72) 0%,rgba(0,0,0,.55) 45%,rgba(0,0,0,.18) 100%)}
.hero[style*="background-image"] > .wrap{position:relative;z-index:1}
.hero[style*="background-image"] .sub{color:rgba(255,255,255,.92)}
/* Тот же фото-герой, но кадр — настоящий <img>, а не CSS-фон. Так правильно:
   Google берёт превью для выдачи из картинок в HTML и не видит фон из стилей
   (SEO-ПРАВИЛА-ВИДИМОСТИ.md, правило 3). Разметка:
     <section class="hero hero-photo"><img class="hero-bg" fetchpriority="high" …>
       <div class="wrap">…</div></section>
   Вариант с background-image оставлен для сайтов, ещё не переведённых. */
.hero-photo{position:relative;overflow:hidden;background:#111}
.hero-photo > .hero-bg{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;z-index:0}
.hero-photo::before{content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(105deg,rgba(0,0,0,.72) 0%,rgba(0,0,0,.55) 45%,rgba(0,0,0,.18) 100%)}
.hero-photo > .wrap{position:relative;z-index:2}
.hero-photo .sub{color:rgba(255,255,255,.92)}

/* Чипы доверия на герое: разрешение, экспертиза, награда. Это факты уровня A,
   а не украшение, поэтому они стоят выше заголовка — их читают раньше цены. */
.badges{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 16px}
.chip{display:inline-block;font-size:12px;font-weight:700;letter-spacing:.03em;
  padding:5px 12px;border-radius:999px;background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.34);color:var(--surface)}

.facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));gap:12px;margin-top:28px}
.fact{background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.22);border-radius:var(--r);padding:14px 16px}
.fact b{display:block;font-size:20px}
.fact span{font-size:13px;color:color-mix(in srgb,var(--surface) 80%,var(--brand))}
.hero .cta{margin-top:26px;display:flex;gap:12px;flex-wrap:wrap}

/* answer-first */
.answer{background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:20px 22px;margin:32px 0}
.answer p{font-weight:500}
/* Блок «ответ первым» — гибрид: ярлык «Кратко» + ведущая фраза (её выхватывает сниппет)
   + факты списком (читаемо человеку, цитируемо AI) + мелкая строка с датой/«подробнее».
   Плотность чисел сохраняется, стена текста уходит. Стандарт — см. design-usability-guide. */
/* Ярлык «Кратко» — инлайн-зачин в начале ведущей фразы (не отдельной строкой:
   пилюля + первые слова на одной строке, дальше текст переносится на всю ширину). */
.answer .lbl{display:inline-block;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;
  color:var(--brand-d);background:var(--surface);border:1px solid var(--line);border-radius:999px;padding:2px 10px;
  margin-right:8px;vertical-align:2px}
.answer .lead{font-weight:600;font-size:16px;line-height:1.55;margin:0 0 12px}
.answer ul.facts{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.answer ul.facts li{position:relative;padding-left:24px;font-weight:500;font-size:15px;line-height:1.45}
.answer ul.facts li::before{content:"✓";position:absolute;left:2px;top:0;color:var(--brand);font-weight:700}
.answer .upd{font-size:13px;color:var(--mut);margin-top:12px;font-weight:400}

/* sections */
section{padding:34px 0}
h2{font-size:clamp(22px,3vw,30px);margin-bottom:18px;line-height:1.25}
h3{font-size:18px;margin:22px 0 10px}
p+p{margin-top:12px}
.lead{color:var(--brand-d)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:28px;align-items:start}
/* КОРЕНЬ ВСЕХ «СТРАНИЦА ЕЗДИТ ВБОК»: у grid- и flex-элементов min-width по умолчанию
   равен auto, то есть «не уже своего содержимого». Достаточно одной неразрывной
   строки внутри (цена 30px, ячейка с td b{white-space:nowrap}, широкая карусель) —
   и колонка отказывается сжиматься, распирая всю страницу. min-width:0 разрешает
   сжатие; переполнение остаётся внутри блока, а не выносит вьюпорт. */
.grid2 > *,.grid3 > *,.gal > *{min-width:0}
.gal,.car,.car-track,.car-thumbs{max-width:100%}
/* Карточка лота: фото шире, панель с ценой уже. Раньше это жило инлайном
   в 492 файлах и перебивало мобильный collapse — страница ездила вбок,
   а блок с ценой было не видно (22.07). */
.grid2.u-top{grid-template-columns:1.25fr 1fr}
/* Панель цены едет за пальцем вдоль длинной галереи — но только в две колонки. */
.u-side{position:sticky;top:74px}

.grid3{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));gap:16px}
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:20px}
.card h3{margin-top:0}
.tick{list-style:none}
.tick li{padding:8px 0 8px 30px;position:relative}
.tick li::before{content:"✓";position:absolute;left:0;top:7px;width:22px;height:22px;border-radius:50%;background:var(--brand);color:var(--surface);font-size:13px;display:flex;align-items:center;justify-content:center}

/* tables */
table{width:100%;border-collapse:collapse;font-size:15px;margin:14px 0}
th,td{text-align:left;padding:12px 12px;border-bottom:1px solid var(--line)}
th{background:var(--bg);font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--brand-d)}
tr:hover td{background:color-mix(in srgb,var(--bg) 45%,var(--surface))}
td b{white-space:nowrap}
.tbl-scroll{overflow-x:auto;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--brand) 36%,var(--surface)) color-mix(in srgb,var(--bg) 70%,var(--surface))}
/* Видимая тонкая полоса прокрутки (где браузер её рисует — Android/десктоп).
   На iOS полосу форсировать нельзя, поэтому надёжный сигнал — бейдж ниже. */
.tbl-scroll::-webkit-scrollbar{height:7px}
.tbl-scroll::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--brand) 36%,var(--surface));border-radius:999px}
.tbl-scroll::-webkit-scrollbar-track{background:color-mix(in srgb,var(--bg) 70%,var(--surface));border-radius:999px}
/* Подсказка прокрутки — бейдж «листайте ↔» в углу таблицы (как в Tilda).
   Зачем не полоса: на мобиле браузеры прячут скроллбар, и что таблица едет вбок —
   неочевидно. Бейдж виден всегда, пока таблица шире экрана; гаснет после первого
   движения. Обёртку .tbl-hintwrap создаёт js/tables.js вокруг таблиц, которые
   реально не влезают, — поэтому на влезающих таблицах и на десктопе его нет. */
.tbl-hintwrap{position:relative}
.tbl-hint{position:absolute;top:8px;right:10px;z-index:3;pointer-events:none;
  background:rgba(44,51,29,.85);color:var(--surface);font-size:12px;font-weight:600;letter-spacing:.02em;
  padding:5px 12px;border-radius:999px;display:inline-flex;gap:5px;align-items:center;
  box-shadow:0 2px 8px rgba(30,35,15,.25);transition:opacity .35s}
.tbl-hintwrap.scrolled .tbl-hint{opacity:0}

/* promo */
.promo-box{display:flex;flex-wrap:wrap;align-items:center;gap:18px;background:linear-gradient(120deg,var(--brand-d),var(--brand));border-radius:var(--r);padding:26px 28px;color:var(--surface)}
.promo-box .p-txt{flex:1;min-width:min(260px,100%)}
.promo-box .p-tag{display:inline-block;background:var(--accent);color:var(--ink);font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;border-radius:999px;padding:4px 12px;margin-bottom:10px}
.promo-box h2{color:var(--surface);margin-bottom:6px;font-size:24px}
.promo-box p{color:color-mix(in srgb,var(--surface) 85%,var(--brand));font-size:15px}
.promo-box .p-date{font-size:13px;color:color-mix(in srgb,var(--surface) 68%,var(--brand));margin-top:6px}

/* currency switch */
.cur-switch{display:flex;align-items:center;gap:8px;margin:6px 0 4px;font-size:14px;color:var(--mut);flex-wrap:wrap}
.cur-switch button{border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:6px 14px;font-size:14px;cursor:pointer;color:var(--ink)}
.cur-switch button.on{background:var(--brand);border-color:var(--brand);color:var(--surface);font-weight:600}
.cur-switch button:hover:not(.on){background:var(--bg)}

/* breadcrumbs */
.bc{font-size:13px;color:var(--mut);padding:14px 0 0}
.bc a{color:var(--mut)}
.bc a:hover{color:var(--brand)}

/* faq */
details{border:1px solid var(--line);border-radius:var(--r);padding:16px 20px;margin-bottom:10px;background:var(--surface)}
details[open]{background:var(--bg)}
summary{font-weight:600;cursor:pointer;list-style:none;position:relative;padding-right:28px}
summary::after{content:"+";position:absolute;right:0;top:-2px;font-size:22px;color:var(--brand)}
details[open] summary::after{content:"–"}
details p{margin-top:10px;color:var(--brand-d)}

/* form */
/* margin-inline:auto — блок 560px висел у левого края в контейнере 1040px,
   и правая половина экрана оставалась пустой. Центрируем. */
.lead-box{background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:26px;max-width:560px;margin-inline:auto}
.lead-box h2{font-size:22px}
.lead-box .note{font-size:14px;color:var(--mut);margin-bottom:16px}
.lead-box input{width:100%;padding:12px 14px;border:1px solid var(--field);border-radius:10px;font-size:16px;margin-bottom:10px;background:var(--surface)}
.lead-box input:focus{outline:2px solid var(--brand);border-color:var(--brand)}
.agree{font-size:13px;color:var(--mut);margin:6px 0 14px}
/* выбор канала связи: один тап, WhatsApp по умолчанию */
.chan{display:flex;gap:8px;flex-wrap:wrap;margin:2px 0 12px}
.chan label{border:1.5px solid var(--line);border-radius:999px;padding:8px 15px;font-size:14px;cursor:pointer;background:var(--surface);color:var(--ink);user-select:none}
/* Радио не прячем display:none — так их не видят клавиатура и скринридер (WCAG 4.1.2,
   аудит KUARTZ 22.09.2026). Визуально скрыты, доступны; фокус рисуем на label. */
.chan label{position:relative}
.chan input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.chan label:has(input:focus-visible){outline:2px solid var(--brand);outline-offset:2px}
.chan i{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:8px;vertical-align:1px}
.chan .i-wa{background:var(--wa-i)}.chan .i-tg{background:var(--tg-i)}.chan .i-call{background:var(--accent)}
.chan label:has(input:checked){background:var(--brand);border-color:var(--brand);color:var(--surface);font-weight:600}
.chan-q{font-size:13px;color:var(--mut);margin-bottom:6px}
.ok-msg{display:none;color:var(--brand-d);font-weight:600;margin-top:10px}

/* gallery placeholders */
.ph{border-radius:var(--r);min-height:240px;aspect-ratio:16/10;background:linear-gradient(135deg,color-mix(in srgb,var(--brand) 22%,var(--surface)),color-mix(in srgb,var(--brand) 38%,var(--surface)));display:flex;align-items:center;justify-content:center;color:var(--brand-d);font-size:13px;text-align:center;padding:10px;overflow:hidden}
.photo{border-radius:var(--r);display:block;width:100%;min-height:240px;aspect-ratio:16/10;object-fit:cover;border:1px solid var(--line);background:color-mix(in srgb,var(--bg) 55%,var(--ink) 4%);overflow:hidden;color:transparent}
.photo.plan{aspect-ratio:1/1;object-fit:contain;background:var(--surface)}
.gal{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));gap:14px;align-items:start}
section{position:relative;background:var(--surface)}
main section{clear:both}

/* схема платежей: простая лента 4×25% без перегруза */
.paysteps{display:flex;gap:0;flex-wrap:wrap;margin:18px 0 6px}
.pstep{flex:1;min-width:130px;position:relative;padding:0 14px 0 0;text-align:center}
.pstep .pp{font-size:24px;font-weight:800;color:var(--brand-d)}
.pstep .pp.small{font-size:16px;padding-top:8px}
.pstep .pl{font-size:13px;font-weight:600;margin-top:2px}
.pstep .pt{font-size:12px;color:var(--mut);margin-top:1px}
.pstep::after{content:"→";position:absolute;right:-2px;top:12px;color:var(--accent);font-size:18px}
.pstep:last-child::after{content:""}
/* На мобиле горизонтальная лента платежей разворачивалась в 5 ВЫСОКИХ блоков
   (число+ярлык+срок в столбик каждый) — тяжело воспринимается. Делаем компактными
   строками «таблицей»: число — фиксированная колонка слева, этап и срок — справа
   в две строки. Высота вдвое меньше, читается как список долей. Разметку не трогаем —
   раскладку задаёт grid поверх тех же трёх div (23.07). */
@media(max-width:760px){
  .paysteps{flex-direction:column;gap:0;margin:14px 0 6px}
  .pstep{display:grid;grid-template-columns:72px 1fr;column-gap:14px;text-align:left;
    padding:12px 0;border-bottom:1px solid color-mix(in srgb,var(--bg) 70%,var(--surface))}
  .pstep::after{content:""}
  .pstep .pp{grid-column:1;grid-row:1/3;align-self:center;font-size:22px}
  .pstep .pp.small{font-size:15px;line-height:1.15}
  .pstep .pl{grid-column:2;grid-row:1;font-size:15px}
  .pstep .pt{grid-column:2;grid-row:2;font-size:13px}
}

/* ряды наличия по типам: подпись · пропорциональный бар · цифры одной строкой */
.trow{display:grid;grid-template-columns:150px 1fr 235px;gap:12px;align-items:center;font-size:14px}
/* Акцент здесь красил текст 12px и давал 3.5 — ниже 4.5. Роль акцента,
   записанная в токенах: «один на сайт, только действие». Мелкая подпись —
   не действие, ей место в приглушённом. */
.trow .tnote{display:block;font-weight:400;font-size:12px;color:var(--mut);margin-top:1px}
.trow .tnum{color:var(--mut);white-space:nowrap}
.trow .track{height:10px;background:color-mix(in srgb,var(--bg) 55%,var(--ink) 4%);border-radius:999px;overflow:hidden}
.trow .track span{display:block;height:100%;background:var(--brand);border-radius:999px}
@media(max-width:760px){
  .trow{grid-template-columns:128px 1fr;gap:8px;font-size:13px}
  .trow .tnum{grid-column:1/3;margin-top:1px;white-space:normal}
}

/* ── НИЖНЯЯ ЗОНА ЭКРАНА ───────────────────────────────────────────────
   За неё дрались пять плавающих блоков: липкая кнопка брони, баннер согласия,
   круглая кнопка связи, чип избранного и всплывашка. На телефоне они налезали
   друг на друга и перекрывали контент.
   Решение: одна переменная --cta-h = высота липкой панели, от неё считаются
   отступы всех остальных. Меняется высота панели — сдвигается всё разом.
   У .cb/.cwb/#favchip/#favtoast стили инжектит JS уже после style.css, поэтому
   перебиваем их через `body ...` — специфичность выше, порядок не важен. */
:root{--cta-h:0px}

/* sticky mobile cta */
.sticky-cta{display:none;position:fixed;bottom:0;left:0;right:0;z-index:60;background:var(--surface);border-top:1px solid var(--line);gap:10px;
  padding:10px 14px calc(10px + env(safe-area-inset-bottom))}   /* полоса-индикатор iPhone */
/* без переноса строк: перенос раздувал панель вдвое на узких экранах.
   clamp ужимает шрифт вместо переноса (13px минимум — читаемо). */
.sticky-cta a{flex:1;text-align:center;padding:12px 6px;font-size:clamp(13px,3.9vw,15px);white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}

/* footer */
footer{background:var(--brand-d);color:color-mix(in srgb,var(--brand) 34%,var(--surface));padding:36px 0 26px;margin-top:40px;font-size:14px}
footer a{color:color-mix(in srgb,var(--brand) 22%,var(--surface))}
footer .cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:22px;margin-bottom:20px}
footer .foot-lang{font-size:14px;color:color-mix(in srgb,var(--brand) 34%,var(--surface));border-top:1px solid color-mix(in srgb,var(--brand) 55%,black);padding-top:14px;margin:0}
footer .foot-lang a{color:color-mix(in srgb,var(--brand) 22%,var(--surface))}
footer .fine{font-size:13px;color:color-mix(in srgb,var(--surface) 60%,var(--brand));padding-top:12px;line-height:1.6}

/* ── ТАБЛИЦЫ-КАРТОЧКИ на узком экране ──
   Широкие таблицы (цены, расчёт рассрочки, лоты) на телефоне превращаются в карточки:
   строка → карточка, каждая ячейка → «ярлык: значение». Ярлык — из data-label
   (проставляет js/tables.js по заголовкам). HTML остаётся <table> (важно для SEO
   и для того, что скрипты валют/сортировки работают с теми же ячейками).
   Порог 600px: на планшете таблица ещё читается, на телефоне — уже нет. */
@media(max-width:600px){
  .t-cards, .t-cards thead, .t-cards tbody, .t-cards tr, .t-cards th, .t-cards td{display:block}
  /* сбрасываем инлайновый min-width (у некоторых таблиц стоит min-width:600px для десктопа):
     иначе карточка остаётся 600px шире экрана и значения уезжают вправо за край (23.07). */
  .t-cards{min-width:0!important;width:100%}
  .t-cards td{overflow-wrap:anywhere}
  .t-cards thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}  /* прячем строку заголовков, но доступно скринридеру */
  .t-cards{font-size:15px;margin:12px 0}
  .t-cards tr{border:1px solid var(--line);border-radius:12px;padding:4px 14px;margin:0 0 10px;background:var(--surface)}
  .t-cards tr:hover td{background:transparent}
  .t-cards td{display:flex;justify-content:space-between;align-items:baseline;gap:14px;
    border:0;border-bottom:1px solid color-mix(in srgb,var(--bg) 70%,var(--surface));padding:8px 0;text-align:right}
  .t-cards tr td:last-child{border-bottom:0}
  .t-cards td::before{content:attr(data-label);color:var(--mut);font-weight:400;text-align:left;flex:0 0 auto}
  .t-cards td b{white-space:normal}
  /* первая ячейка (тип/юнит) — как заголовок карточки: крупнее, без ярлыка */
  .t-cards td:first-child{border-bottom:1px solid var(--line);padding-top:12px;font-size:16px;font-weight:700}
  .t-cards td:first-child::before{display:none}
  /* в карточном режиме таблица влезает — прокрутка и бейдж-подсказка не нужны */
  .t-cards.tbl-scroll,.tbl-scroll:has(.t-cards){overflow:visible}
  .tbl-hintwrap:has(.t-cards) .tbl-hint{display:none}
}

@media(max-width:760px){
  .grid2,.grid2.u-top{grid-template-columns:1fr}
  /* на телефоне порядок сверху вниз: фото → цена и характеристики.
     sticky в одноколоночной ленте только мешает — отключаем. */
  .u-side{position:static;top:auto}
  /* Цена 30px + «≈ $189 000» рядом не влезали в 390px и распирали карточку.
     Уменьшаем и разрешаем перенос: сумма в баттах и её эквивалент встают в две строки,
     каждая при этом остаётся неразрывной. */
  .u-side > p:first-child{font-size:24px;flex-wrap:wrap}
  .u-side .thb small{white-space:nowrap}
  /* Таблица характеристик: ячейки могут переноситься, длинные значения не распирают. */
  .u-side table{width:100%;table-layout:auto}
  .u-side td{overflow-wrap:anywhere}
  .nav nav{display:none}
  .sticky-cta{display:flex}
  section{padding:26px 0}

  /* ── порядок этажей снизу вверх ── */
  :root{--cta-h:64px}
  body{padding-bottom:calc(var(--cta-h) + env(safe-area-inset-bottom))}

  /* Круглая кнопка связи на мобиле убрана совсем: липкая панель внизу делает
     ровно то же (WhatsApp + заявка), а два плавающих элемента с одной функцией
     только съедают экран. На десктопе кнопка остаётся. */
  body .cwb,body .cwp{display:none!important}

  /* Чип избранного и всплывашка — над липкой панелью, а не под ней. */
  body #favchip{bottom:calc(var(--cta-h) + 12px)}
  body #favtoast{bottom:calc(var(--cta-h) + 12px)}

  /* Баннер согласия — тоже над панелью. Пока он открыт, чип избранного прячем:
     три уровня плашек на 390px читаются как свалка. Баннер удаляется из DOM
     после ответа, поэтому :has() отработает корректно. */
  body .cb{bottom:calc(var(--cta-h) + 10px);left:8px;right:8px}
  body:has(.cb) #favchip{display:none!important}

  /* Панель выбранного юнита на странице наличия. */
  body .upanel{bottom:var(--cta-h)}
}

/* ── a11y (Lighthouse 23.07.2026): текстовые ссылки различимы не только цветом ── */
main p a:not(.btn), main li a:not(.btn), p.upd a, .answer a{text-decoration:underline;text-underline-offset:2px;text-decoration-thickness:1px}

/* ── таблица лотов: строка кликабельна, номер — явная ссылка (дизайн-аудит 23.07) ── */
#lots-tbl tbody tr{cursor:pointer}
#lots-tbl tbody tr:hover{background:color-mix(in srgb,var(--bg) 70%,var(--surface))}
#lots-tbl tbody td:first-child a{text-decoration:underline;text-underline-offset:2px}

/* ── таблица лотов на мобиле: компактнее и без переносов цен (фидбек 24.07) ── */
#lots-tbl th{white-space:nowrap}
/* Статус квартиры в таблице. Раньше цвет ставился инлайновым стилем прямо в
   разметке строки — 136 повторов одного и того же цвета в HTML и ни одной
   возможности поменять его из палитры. */
.st{font-weight:600;font-size:13px;white-space:nowrap}
.st-free{color:var(--ok)}
.st-hold{color:var(--warn)}
.st-sold,.st-none{color:var(--mut)}

/* Подписи групп фильтров внутри .tfilter: «Корпус:», «Этаж:», «Вид:». */
.fgl{font-size:13px;color:var(--mut);margin:0 2px 0 10px;align-self:center}
.lots-count{font-size:14px;color:var(--mut);margin:8px 0}

#lots-tbl td{white-space:nowrap}
.mhint{display:none}
@media(max-width:760px){
  #lots-tbl{font-size:13px}
  #lots-tbl th,#lots-tbl td{padding:8px 6px}
  .mhint{display:block;font-size:13px;color:var(--mut);margin:2px 0 8px}
}

/* бургер включается с 1100px (nav.js): прячем ленту меню и сердечко на тех же ширинах,
   иначе на средних экранах видно и бургер, и обрезанное меню (фидбек 25.07) */
@media(max-width:1100px){.nav nav{display:none}.nav #favcount{display:none!important}}

/* ── Форма заявки (английская версия) ──────────────────────────────
   Отдельный контур: русская версия остаётся на мессенджерах и ничего
   не собирает, форма живёт только там, где мы работаем по GDPR. */
.leadform{max-width:560px;margin:18px auto 0;text-align:left}
.lf-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media(max-width:560px){.lf-row{grid-template-columns:1fr}}
.lf-field{display:block}
.lf-field span{display:block;font-size:14px;font-weight:600;margin-bottom:5px;color:var(--ink)}
.lf-field small{font-weight:400;color:var(--mut)}
.lf-field input{width:100%;font:inherit;font-size:16px;padding:12px 14px;border:1px solid var(--field);
  border-radius:var(--r);background:var(--surface);color:var(--ink);transition:border-color .15s}
.lf-field input:focus{outline:2px solid var(--brand);outline-offset:2px;border-color:var(--brand);box-shadow:none}
.lf-field input:user-invalid{border-color:var(--err)}
/* Галочка НЕ предустановлена и равновесна по весу с остальным текстом:
   предвыбранное согласие не считается согласием. */
.lf-consent{display:flex;gap:10px;align-items:flex-start;margin-top:14px;font-size:14px;line-height:1.5;color:var(--mut)}
.lf-consent{padding:6px 0}
.lf-consent input{width:22px;height:22px;margin:1px 0 0;flex:0 0 auto;accent-color:var(--brand)}
.lf-consent a{color:var(--brand-d)}
.lf-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.leadform button[type=submit]{margin-top:16px;width:100%;font-size:16px;padding:14px 20px}
.leadform button[disabled]{opacity:.6;cursor:default}
.lf-msg{margin:10px 0 0;font-size:14px;min-height:1.2em}
.lf-msg.ok{color:var(--ok);font-weight:600}
.lf-msg.err{color:var(--err)}
.lf-or{margin:22px 0 10px;font-size:13px;color:var(--mut);text-transform:uppercase;letter-spacing:.08em}

/* Мессенджеры под формой — тихой строкой, а не второй парой кнопок.
   Три ярких элемента подряд (форма + WhatsApp + Telegram) заставляли выбирать
   способ вместо того, чтобы писать. Канал остаётся, вес снят. */
.lf-alt{margin:14px 0 0;font-size:14px;color:var(--mut)}
.lf-alt a{color:var(--brand);font-weight:600;text-decoration:none;border-bottom:1px solid rgba(92,107,53,.3);padding-bottom:1px;
  min-height:44px;display:inline-flex;align-items:center}   /* тач-цель 44 px на любой раскладке */
.lf-alt a:hover{border-bottom-color:var(--brand)}
.lf-alt i{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:6px;vertical-align:1px}
.lf-alt .i-wa{background:var(--wa-i)}.lf-alt .i-tg{background:var(--tg-i)}
.lf-alt .lf-dot{margin:0 6px;color:var(--line)}

/* Подсказки валидации под полем, а не браузерным пузырём: пузырь исчезает
   через пару секунд, не читается на мобильном и всегда на языке системы. */
.lf-err{margin:5px 0 0;font-size:13px;color:var(--err);line-height:1.35}
.lf-field.is-invalid input,.lf-consent.is-invalid input{border-color:var(--err)}
.lf-field.is-invalid input:focus{outline-color:var(--err);box-shadow:none}
.lf-consent.is-invalid span{color:var(--err)}
.lf-msg.err{color:var(--err)}
.lf-msg.ok{color:var(--brand);font-weight:600}

/* main p a:not(.btn) подчёркивает все ссылки в тексте — из-за него у
   мессенджеров под формой было две линии сразу: своя рамка и подчёркивание.
   Перебиваем адресно. */
/* Селектор должен быть НЕ СЛАБЕЕ, чем `main p a:not(.btn)` (0,1,3), иначе
   подчёркивание не снимается — с первого раза я написал `main .lf-alt a`
   (0,1,2) и правило проиграло. Считать специфичность на глаз — плохая идея. */
main p.lf-alt a:not(.btn){text-decoration:none}

/* Экран после отправки: форма уходит, остаётся подтверждение и следующий шаг.
   Пустая форма после «Спасибо» — мёртвое место: человек уже сделал действие,
   и это лучший момент увести его в подбор квартиры. */
.lf-done{text-align:left}
.lf-done .lf-tick{width:44px;height:44px;border-radius:50%;background:var(--brand);color:var(--surface);
  display:flex;align-items:center;justify-content:center;font-size:22px;margin-bottom:14px}
.lf-done h3{font-size:19px;margin:0 0 6px}
.lf-done p{font-size:14px;color:var(--mut);margin:0 0 16px}
.lf-done .lf-next{display:grid;gap:10px}
.lf-done .lf-next .btn{text-align:center}

/* Строка поиска внутри выпадающего списка стран.
   Настоящая причина наезда была не в моём стиле из consent.js, а в общих
   правилах формы: `.lead-box input` и `.lf-field input` задают padding 12/14px
   и рамку ВСЕМ полям внутри блока — включая поиск, который живёт в разметке
   intl-tel-input внутри того же .lf-field. Библиотека держит слева иконку лупы
   на absolute и рассчитывает на padding-left:30px; наши 14px его перебивали,
   и текст с курсором налезали на иконку.
   Возвращаем геометрию библиотеки селектором заведомо более весомым. */
.lead-box .iti__search-input,
.lf-field .iti__search-input{
  width:100%;margin:0;border:0;border-radius:3px;background:var(--surface);
  padding:10px 30px 10px 32px;font-size:15px;box-shadow:none
}
.lead-box .iti__search-input:focus,
.lf-field .iti__search-input:focus{outline:none;border:0;box-shadow:none}
/* Пункты списка стран тоже не должны наследовать отступы полей формы. */
.lead-box .iti__country,.lf-field .iti__country{margin:0}

/* Выравнивание пары «имя / телефон».
   Поле телефона обёрнуто разметкой intl-tel-input, и его высота отличалась
   от обычного поля на пару пикселей. Незаметно, пока полей два, — но
   подсказки об ошибке под ними вставали на разной высоте и колонка
   выглядела съехавшей. Фиксируем высоту полей: тогда и поля, и подсказки
   под ними стоят на одной линии независимо от обёрток. */
/* Подбирать высоты вручную бесполезно: у поля телефона своя обёртка от
   библиотеки, и любая правка внутри неё снова сдвинет подсказку. Поэтому
   раскладываем подпись, поле и подсказку по СТРОКАМ ОДНОЙ сетки: тогда они
   выровнены по определению, независимо от того, что у поля внутри.
   display:contents убирает сам label из раскладки, оставляя его детей
   прямыми элементами сетки; связь label с полем от этого не теряется. */
.lf-row{display:grid;grid-template-columns:1fr 1fr;gap:0 12px;align-items:start}
.lf-row .lf-field{display:contents}
.lf-row .lf-field > *{min-width:0}
.lf-row .lf-field:first-child  > *{grid-column:1}
.lf-row .lf-field:nth-child(2) > *{grid-column:2}
.lf-row .lf-field > span{grid-row:1}
.lf-row .lf-field > input,
.lf-row .lf-field > .iti{grid-row:2;align-self:start}
.lf-row .lf-field > .lf-err{grid-row:3;margin:6px 0 0}
.lf-field input,
.lf-field .iti input.iti__tel-input{height:52px;line-height:normal}

/* ── ФОРМА НА УЗКОМ ЭКРАНЕ (класс lf-opt, пока только главная) ────────────
   Что было на телефоне 360–412 px: имя и телефон стояли в два столбца,
   в поле имени помещалось «How should w», в поле телефона — четыре цифры
   из девяти. Человек не видит, что вводит, и это то самое поле, от которого
   зависит, дойдёт до нас заявка или нет.

   Правило «на узком экране в одну колонку» в файле БЫЛО (строка 382), но
   ниже его перебила сетка выравнивания подсказок: она объявлена без
   медиазапроса и с той же силой, а побеждает поздняя. Поэтому здесь не
   только колонка, но и возврат label в обычный поток — иначе при одной
   колонке display:contents выстроит обе подписи подряд, а под ними оба
   поля, и «Телефон» окажется над полем имени. */
@media(max-width:560px){
  .lf-opt .lf-row{grid-template-columns:1fr;gap:14px}
  .lf-opt .lf-row .lf-field{display:block}
  .lead-box.lf-opt{padding:18px 16px}       /* +20 px ширины полям */

  /* Выбор канала: было «WhatsApp Telegram» в строку и осиротевший
     «Please call me» под ними. Сетка 2×2 с широкой третьей кнопкой
     читается как задуманная, а не как случайный перенос. */
  .lf-opt .chan{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .lf-opt .chan label{display:flex;align-items:center;justify-content:center;
    min-height:44px;padding:8px 10px;text-align:center}
  .lf-opt .chan label:last-child{grid-column:1 / -1}

  /* Строка мессенджеров переносилась так, что точка-разделитель повисала
     в конце строки, а «Telegram» уезжал вниз один. Убираем разделитель и
     раскладываем ссылки как элементы с внятными промежутками. */
  .lf-opt .lf-alt{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px}
  .lf-opt .lf-alt .lf-dot{display:none}
  .lf-opt .lf-alt a{min-height:44px;display:inline-flex;align-items:center}

  /* Галочка согласия: раньше в неё надо было попасть по квадратику 18 px. */
  .lf-opt .lf-consent{display:flex;align-items:flex-start;gap:10px;padding:6px 0}
  .lf-opt .lf-consent input{width:22px;height:22px;flex:none;margin-top:1px}
}

/* ═══ ВЫБОР КВАРТИРЫ ═══════════════════════════════════════════════════════
   Шахматка, список, зоны на фасаде и поэтажном плане. Работает с
   js/units-select.js. Цветов проекта здесь нет: статусы выражены через
   семантические токены --ok / --warn / --err, поэтому свободное и проданное
   читаются одинаково в любом направлении дизайна. */

/* Пилюли «Корпус A» поверх фасада и ген-плана: вид классом, позиция инлайн.
   На узком экране фасад мелкий, и пилюли фиксированного размера его перекрывали. */
.hotspot{background:var(--brand);color:var(--surface);border:2px solid var(--surface);border-radius:999px;
  padding:8px 16px;font-size:14px;font-weight:700;cursor:pointer;box-shadow:0 3px 10px rgba(0,0,0,.28)}
.legend{display:flex;gap:16px;flex-wrap:wrap;font-size:14px;margin:12px 0;color:var(--mut)}
.legend i{display:inline-block;width:14px;height:14px;border-radius:4px;vertical-align:-2px;margin-right:5px}

.tfilter{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0 4px}
.tfilter button{border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:8px 14px;font-size:14px;cursor:pointer}
.tfilter button.on{background:var(--brand);border-color:var(--brand);color:var(--surface);font-weight:600}

.tower{margin-top:22px}
.tower h3{margin-bottom:8px}
.tower-cnt{font-weight:400;color:var(--mut);font-size:14px}
.chess{display:grid;gap:4px;overflow-x:auto;padding-bottom:6px}
.frow{display:flex;gap:4px;align-items:center}
.fl{min-width:34px;font-size:12px;color:var(--mut);font-weight:700;text-align:center}
.cell{min-width:52px;height:40px;border-radius:8px;font-size:12px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;cursor:pointer;border:1px solid transparent;line-height:1.15;font-weight:600}
.cell.free{background:color-mix(in srgb, var(--ok) 15%, var(--surface));color:var(--ink)}
.cell.free:hover{border-color:var(--brand);background:color-mix(in srgb, var(--ok) 28%, var(--surface))}
.cell.gone{background:color-mix(in srgb, var(--ink) 6%, var(--surface));color:var(--mut);cursor:default;text-decoration:line-through}
.cell.sel{background:var(--brand);color:var(--surface)}
.cell.dim{opacity:.25}
.cell span{font-weight:400;font-size:12px}
.fb-cell{min-width:64px;height:44px;text-decoration:none}

.upanel{position:sticky;bottom:0;z-index:20;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);padding:16px 18px;margin-top:18px;display:none;box-shadow:0 -4px 20px #0001}
.upanel.show{display:flex;gap:18px;flex-wrap:wrap;align-items:center}
.upanel .ud b{font-size:20px;color:var(--brand-d)}
.upanel img{width:120px;border-radius:8px;border:1px solid var(--line)}

/* Зоны юнитов на поэтажном плане. Позиция инлайн из FPZONES, вид — здесь. */
#fbzones{position:absolute;inset:0}
.uz{position:absolute;border-radius:7px;transition:background .15s}
.uz-free{background:color-mix(in srgb, var(--ok) 22%, transparent);border:2px solid color-mix(in srgb, var(--ok) 80%, transparent);cursor:pointer}
.uz-free:hover{background:color-mix(in srgb, var(--ok) 45%, transparent)}
.uz-gone{background:color-mix(in srgb, var(--err) 20%, transparent);border:2px solid color-mix(in srgb, var(--err) 55%, transparent)}

/* Полигоны этажей на фасаде. Светофор наличия: 0 · 1–5 · больше.
   Заливка плотная намеренно: фасад кондо сам по себе зелёно-серый,
   слабая заливка на нём не читалась. */
.fz{cursor:pointer;stroke:rgba(255,255,255,.9);stroke-width:2;transition:fill .15s;
  fill:color-mix(in srgb, var(--ok) 42%, transparent)}
.fz.uz-few{fill:color-mix(in srgb, var(--warn) 42%, transparent)}
.fz.uz-gone{fill:color-mix(in srgb, var(--err) 42%, transparent);border:0}
.fz.hot{fill:color-mix(in srgb, var(--ok) 62%, transparent)}
.fz.uz-few.hot{fill:color-mix(in srgb, var(--warn) 62%, transparent)}
.fz.uz-gone.hot{fill:color-mix(in srgb, var(--err) 62%, transparent)}
/* Области корпусов на ген-плане */
.mpz{cursor:pointer;fill:color-mix(in srgb, var(--ok) 18%, transparent);
  stroke:color-mix(in srgb, var(--brand-d) 60%, transparent);stroke-width:2.5;transition:fill .15s}
.mpz:hover{fill:color-mix(in srgb, var(--ok) 42%, transparent)}

#fbfloors button,#mpfloors button{border:1px solid var(--line);background:var(--surface);border-radius:999px;
  padding:8px 12px;font-size:13px;cursor:pointer;white-space:nowrap;color:var(--ink)}
#fbfloors button.on,#mpfloors button.on{background:var(--brand);border-color:var(--brand);color:var(--surface);font-weight:600}
#fbfloors button.empty{opacity:.5}

@media(max-width:760px){
  /* Тап-цель 44×44 — минимум по WCAG 2.2. Было 44×36 при шрифте 10–11 px:
     пальцем промахивались, номер квартиры читался с трудом. Шахматка и так
     прокручивается вбок, поэтому крупная ячейка ничего не ломает. */
  .cell{min-width:46px;height:46px;font-size:12px}
  .cell span{font-size:12px}
  /* Номер этажа прилипает слева: при прокрутке видно, на каком ты этаже. */
  .fl{position:sticky;left:0;z-index:2;background:var(--surface);min-width:30px;font-size:13px}
  .chess{gap:5px}.frow{gap:5px}
  .fbchips{display:flex!important}
  #fbzones{display:none}   /* на телефоне зоны мельче пальца — работают чипсы */
  #fbfloors,#mpfloors{flex-direction:row!important;flex-wrap:wrap;order:2}
}
@media(max-width:600px){
  #mpprev,#mpnext,#fbprev,#fbnext{top:auto!important;bottom:8px!important;transform:none!important;
    width:38px!important;height:38px!important;font-size:20px!important}
  .hotspot{padding:4px 10px;font-size:12px;border-width:1.5px;box-shadow:0 2px 7px rgba(0,0,0,.3)}
  .fac-legend{font-size:12px!important;padding:5px 8px!important;left:8px!important;bottom:8px!important}
  /* Заливка на маленьком экране плотнее: зоны мелкие, слабая не видна. */
  .fz{stroke-width:3;fill:color-mix(in srgb, var(--ok) 55%, transparent)}
  .fz.uz-few{fill:color-mix(in srgb, var(--warn) 55%, transparent)}
  .fz.uz-gone{fill:color-mix(in srgb, var(--err) 55%, transparent)}
  .mpz{stroke-width:3.5;fill:color-mix(in srgb, var(--ok) 30%, transparent)}
}

/* ═══ КАРТА ЛОКАЦИИ ════════════════════════════════════════════════════════
   Заставка вместо iframe до клика: карта — третья сторона, она ставит куки и
   передаёт IP сразу при загрузке, когда баннер согласия ещё висит. */
.map{position:relative}
.map-still{display:block;width:100%;height:auto;border-radius:var(--r);border:1px solid var(--line)}
.map-frame{display:block;width:100%;border:0;border-radius:var(--r)}
.map-load{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  background:var(--brand);color:var(--surface);border:0;border-radius:999px;
  padding:12px 22px;font-size:15px;font-weight:600;cursor:pointer;
  box-shadow:0 3px 14px rgba(0,0,0,.28);min-height:44px}
.map-load:hover{background:var(--brand-d)}
.map-load[disabled]{opacity:.7;cursor:default}
.map-links{display:flex;gap:10px;flex-wrap:wrap;margin-top:12px}
