fix(mera/b2c): на мобильном липкий хром съедал 42% экрана
Жалоба «много всплывашек, экрана не видно» — это не всплывашки, а постоянный
хром: на 375×812 липкая шапка (235 px) и фиксированная нижняя панель (109 px)
вместе занимали 42% экрана и отъедали их при любой прокрутке. Замер тем же
способом (getBoundingClientRect по элементам с position fixed/sticky): было
366 px = 45,1% высоты экрана, стало 119,5 px = 14,7%. На 1280 — 135,5 px до и
после, без изменений.
Шапка на узком экране сведена к одной строке (лого + «Для бизнеса»):
- навигация по секциям скрыта — четыре пункта переносились в две строки, а
на мобильном к секциям всё равно доезжают прокруткой; «Статьи» и «МЕРА для
бизнеса» остаются ссылками в подвале, «Продажа под ключ» и на десктопе
неактивная заглушка;
- CTA скрыт — он вёл туда же, куда нижняя панель, и два одинаковых призыва
на одном экране это и есть жалоба; панель осталась, шапка уступила.
Селектор города (CityPicker) удалён совсем, а не спрятан: он не владел своим
выбором — состояние жило внутри компонента и никуда не отправлялось, — тогда
как гео-гейт расчёта стоит на городе из формы (FreeCheckCard, #2576). Два
места, задающих одно значение, из которых работает одно, — дефект сам по себе;
то же правило уже записано в InnerHeader. Граница покрытия, ради которой
выпадашку открывали, стоит текстом в герое.
Нижняя панель на узком экране — только кнопка: её строка переносилась на две-
три и делала панель втрое выше кнопки. То же обещание остаётся словами героя.
Шаг медиазапроса — 1000 px, а не общий для файла 720: на 720 шапка макета всё
ещё переносится в две строки (замерено: 109 px хрома), то есть возвращать её
там значило бы вернуть тот же дефект планшету.
This commit is contained in:
parent
1f3d8d0b15
commit
5ed4a4ec25
5 changed files with 100 additions and 305 deletions
|
|
@ -1,140 +0,0 @@
|
|||
"use client";
|
||||
|
||||
/**
|
||||
* CityPicker — выбор города в шапке лэндинга v3 (макет ~ строки 47-73).
|
||||
*
|
||||
* Презентационный клиентский остров: сегодня публичный расчёт выключен
|
||||
* (`PUBLIC_ESTIMATE_ENABLED = false` в content.ts), поэтому выбранный здесь
|
||||
* город никуда не отправляется — состояние живёт только в этом компоненте и
|
||||
* показывает посетителю, что сервис знает больше одного города области.
|
||||
* Когда форма расчёта откроется, сюда нужно будет добавить проброс выбора
|
||||
* наружу (проп/контекст) — в этом заходе scope ограничен шапкой/подвалом/
|
||||
* sticky-баром, самой формы здесь нет.
|
||||
*
|
||||
* Список городов и деление на «полное покрытие» / «данных меньше» берутся из
|
||||
* `OBLAST_CITIES` / `PRIMARY_CITY` (content.ts, тот же реестр, что честно
|
||||
* объясняет разницу в покрытии в Hero.tsx). Макет показывал числовые «веса»
|
||||
* по городам (тысячи объявлений) — мы их не повторяем: таких цифр в коде нет,
|
||||
* а гадать нельзя (правило честности в content.ts).
|
||||
*/
|
||||
|
||||
import { useEffect, useId, useRef, useState } from "react";
|
||||
|
||||
import { DEFAULT_CITY, OBLAST_CITIES } from "@/lib/city-registry";
|
||||
|
||||
import { PRIMARY_CITY, REGION_NAME } from "../../content";
|
||||
import styles from "../../landing-v3.module.css";
|
||||
|
||||
export function CityPicker() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [query, setQuery] = useState("");
|
||||
const [city, setCity] = useState<string>(DEFAULT_CITY.label);
|
||||
const wrapRef = useRef<HTMLDivElement>(null);
|
||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||
const panelId = useId();
|
||||
|
||||
// Клик вне панели — закрыть. Тот же паттерн, что components/auth/UserMenu.tsx.
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
function handleClick(e: MouseEvent) {
|
||||
if (wrapRef.current && !wrapRef.current.contains(e.target as Node)) {
|
||||
setOpen(false);
|
||||
}
|
||||
}
|
||||
document.addEventListener("mousedown", handleClick);
|
||||
return () => document.removeEventListener("mousedown", handleClick);
|
||||
}, [open]);
|
||||
|
||||
// Escape — закрыть и вернуть фокус на кнопку.
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
function handleKey(e: KeyboardEvent) {
|
||||
if (e.key === "Escape") {
|
||||
setOpen(false);
|
||||
buttonRef.current?.focus();
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", handleKey);
|
||||
return () => document.removeEventListener("keydown", handleKey);
|
||||
}, [open]);
|
||||
|
||||
const normalizedQuery = query.trim().toLowerCase();
|
||||
const filtered = normalizedQuery
|
||||
? OBLAST_CITIES.filter((c) =>
|
||||
c.label.toLowerCase().includes(normalizedQuery),
|
||||
)
|
||||
: OBLAST_CITIES;
|
||||
|
||||
return (
|
||||
<div className={styles.hdrCityWrap} ref={wrapRef}>
|
||||
<button
|
||||
ref={buttonRef}
|
||||
type="button"
|
||||
className={styles.hdrCityBtn}
|
||||
onClick={() => setOpen((v) => !v)}
|
||||
aria-haspopup="true"
|
||||
aria-expanded={open}
|
||||
aria-controls={panelId}
|
||||
>
|
||||
<span className={styles.hdrCityDot} aria-hidden="true" />
|
||||
<span>{city}</span>
|
||||
<span className={styles.hdrCityCaret} aria-hidden="true">
|
||||
{open ? "▲" : "▼"}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{open ? (
|
||||
<div
|
||||
id={panelId}
|
||||
className={styles.hdrCityPanel}
|
||||
aria-label="Выбор города"
|
||||
>
|
||||
<div className={styles.hdrCitySearchRow}>
|
||||
<input
|
||||
type="text"
|
||||
className={styles.hdrCityInput}
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder="Поиск города"
|
||||
aria-label="Поиск города"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.hdrCityList}>
|
||||
{filtered.length > 0 ? (
|
||||
filtered.map((c) => (
|
||||
<button
|
||||
key={c.id}
|
||||
type="button"
|
||||
className={styles.hdrCityItem}
|
||||
data-active={c.label === city ? "true" : undefined}
|
||||
onClick={() => {
|
||||
setCity(c.label);
|
||||
setOpen(false);
|
||||
setQuery("");
|
||||
buttonRef.current?.focus();
|
||||
}}
|
||||
>
|
||||
<span className={styles.hdrCityItemName}>{c.label}</span>
|
||||
<span className={styles.hdrCityItemNote}>
|
||||
{c.label === PRIMARY_CITY
|
||||
? "Полное покрытие"
|
||||
: "Данных меньше"}
|
||||
</span>
|
||||
</button>
|
||||
))
|
||||
) : (
|
||||
<p className={styles.hdrCityEmpty}>
|
||||
Города нет в списке. Мы работаем там, где хватает данных по
|
||||
сделкам — напишите нам, и добавим.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.hdrCityFooter}>
|
||||
ДАННЫЕ ПО {OBLAST_CITIES.length} ГОРОДАМ:{" "}
|
||||
{REGION_NAME.toUpperCase()}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -28,10 +28,11 @@
|
|||
* Правило из шапки `lib/city-registry.ts`: город считается известным, только
|
||||
* если человек выбрал его сам ИЛИ `detectCityInText` нашёл его в тексте
|
||||
* адреса; молча подставлять Екатеринбург нельзя. Ответ про город вне покрытия
|
||||
* — тот же и дословно тот же, что в v1. Выпадашка города в шапке
|
||||
* (`CityPicker`) сюда НЕ пробрасывается: она презентационная и своим выбором
|
||||
* не владеет (см. её JSDoc), а гейт обязан читать то, что человек указал
|
||||
* рядом с адресом.
|
||||
* — тот же и дословно тот же, что в v1. Выпадашки города в шапке больше нет
|
||||
* вовсе (`CityPicker` удалён 29.08.2026, см. JSDoc HeaderV3): она была
|
||||
* презентационной и своим выбором не владела, то есть значение задавалось в
|
||||
* двух местах, а на расчёт влияло только это. Гейт обязан читать то, что
|
||||
* человек указал рядом с адресом, — и теперь это единственное такое место.
|
||||
*
|
||||
* СОСТОЯНИЕ ТЕПЕРЬ ДОЕЗЖАЕТ ДО ЧЕРНОВИКА. Поле было обязательным, а его
|
||||
* значение никуда не клалось — человек выбирал состояние квартиры, и мы его
|
||||
|
|
|
|||
|
|
@ -1,10 +1,34 @@
|
|||
/**
|
||||
* HeaderV3 — шапка лэндинга v3 (макет ~ строки 32-78): sticky, blur, лого +
|
||||
* навигация + селектор города + CTA.
|
||||
* навигация + CTA.
|
||||
*
|
||||
* Логотип НЕ ссылка: на публичном домене корень — это сам лэндинг, то есть
|
||||
* ссылка вела бы на текущую же страницу.
|
||||
*
|
||||
* СЕЛЕКТОРА ГОРОДА ЗДЕСЬ БОЛЬШЕ НЕТ (29.08.2026). `CityPicker` жил в этой
|
||||
* шапке с тех пор, когда карточка проверки города не спрашивала вовсе, и
|
||||
* своим выбором он НЕ владел: состояние оставалось внутри компонента и никуда
|
||||
* не отправлялось (см. его прежний JSDoc). Город у формы появился —
|
||||
* `FreeCheckCard` спрашивает его сама и на нём стоит гео-гейт расчёта (#2576),
|
||||
* — и с этого момента шапка стала вторым местом, задающим одно значение, но
|
||||
* ни на что не влияющим: человек выбирал в шапке Нижний Тагил и всё равно
|
||||
* заполнял город в форме. Правило то же, по которому селектора нет во
|
||||
* внутренней шапке (`_components/InnerHeader.tsx`). Граница покрытия, ради
|
||||
* которой выпадашку когда-то читали, теперь стоит текстом в герое (плашка
|
||||
* «полное покрытие / данных меньше», HeroV3), то есть видна без клика.
|
||||
*
|
||||
* НА УЗКОМ ЭКРАНЕ ШАПКА — ОДНА СТРОКА: лого и «Для бизнеса». Навигация по
|
||||
* секциям и CTA скрыты в CSS (`landing-v3.module.css`, блок шапки) и
|
||||
* возвращаются с той ширины, на которой шапка макета замерена как
|
||||
* однострочная, — а не с общего для файла шага в 720px, где она всё ещё
|
||||
* переносится. На 375px переносилось всё, и липкая шапка занимала 29%
|
||||
* экрана — эти проценты отъедались при любой прокрутке. Куда делись пункты: «Точность»
|
||||
* и «Проверьте себя» — секции этой же страницы, до них доезжают прокруткой
|
||||
* (ради чего на мобильном и скроллят); «Статьи» и «МЕРА для бизнеса» стоят
|
||||
* ссылками в подвале (`FooterV3`); «Продажа под ключ» и на десктопе не
|
||||
* ссылка, а заглушка. CTA не потерян: снизу висит `StickyCtaV3` — на экране
|
||||
* остаётся ОДИН призыв вместо двух одинаковых.
|
||||
*
|
||||
* НЕАКТИВНЫЕ ПУНКТЫ (29.08.2026). Осталась одна «Продажа под ключ» —
|
||||
* партнёрской формы нет ни в коде, ни у владельца, и пункт остаётся видимым,
|
||||
* но некликабельным. «Проверьте себя» и «Статьи» раньше стояли рядом с ней по
|
||||
|
|
@ -21,16 +45,14 @@
|
|||
* «Для бизнеса» ведёт на АБСОЛЮТНЫЙ адрес B2B-контура: относительный «/» на
|
||||
* публичном домене вёл на сам лэндинг, то есть пункт не работал вовсе.
|
||||
*
|
||||
* Единственный клиентский остров — `CityPicker` (открытие/закрытие, поиск).
|
||||
* Сама шапка серверная.
|
||||
* Шапка целиком серверная: клиентских островов в ней не осталось (последним
|
||||
* был `CityPicker`).
|
||||
*/
|
||||
|
||||
import { B2B_URL } from "../../content";
|
||||
import styles from "../../landing-v3.module.css";
|
||||
import { PublicLink } from "../PublicLink";
|
||||
|
||||
import { CityPicker } from "./CityPicker";
|
||||
|
||||
export function HeaderV3() {
|
||||
return (
|
||||
<header className={styles.hdrRoot}>
|
||||
|
|
@ -65,7 +87,6 @@ export function HeaderV3() {
|
|||
</nav>
|
||||
|
||||
<div className={styles.hdrRight}>
|
||||
<CityPicker />
|
||||
<a href={B2B_URL} className={styles.hdrBizLink}>
|
||||
Для бизнеса
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,16 @@
|
|||
* того, куда именно в дерево страницы его вставят (ожидаемое место — сразу
|
||||
* после подвала, как Header/Footer в текущем `layout.tsx`).
|
||||
*
|
||||
* НА УЗКОМ ЭКРАНЕ ПАНЕЛЬ — ТОЛЬКО КНОПКА (29.08.2026). Строка «Узнайте цену
|
||||
* своей квартиры…» на 375px переносилась и панель занимала 13% экрана, а
|
||||
* вместе с шапкой хром съедал 42% при любой прокрутке. Текст скрыт в CSS
|
||||
* (`.barText`), а не удалён: с той же ширины, что возвращает шапку макета
|
||||
* (1000px — там строка и кнопка встают рядом), панель снова целиком. То же
|
||||
* обещание на самой странице остаётся словами героя («Бесплатно: сколько
|
||||
* похожих квартир продаётся рядом и как давно они висят»), то есть уходит
|
||||
* повтор, а не мысль. Призыв на мобильном теперь ОДИН: `HeaderV3` свою
|
||||
* кнопку на этой ширине не показывает.
|
||||
*
|
||||
* НА КНОПКЕ НЕТ СРОКА. Здесь стояло «Проверить за 30 секунд» — замера времени
|
||||
* заполнения формы нет и не было (та же причина, по которой «30 СЕКУНД» ушло
|
||||
* из бейджа первого шага, см. `landing-facts.ts`). Панель висит на экране
|
||||
|
|
|
|||
|
|
@ -17,14 +17,15 @@
|
|||
*
|
||||
* ------------------------------------------------------------------------
|
||||
* ЭТОТ БЛОК (шапка / подвал / sticky-CTA) — префиксы hdr / ftr / bar.
|
||||
* Секция «Шапка» = HeaderV3.tsx + CityPicker.tsx.
|
||||
* Секция «Шапка» = HeaderV3.tsx (селектор города из неё убран 29.08.2026:
|
||||
* город спрашивает сама форма проверки, FreeCheckCard).
|
||||
* Секция «Подвал» = FooterV3.tsx.
|
||||
* Секция «Sticky CTA» = StickyCtaV3.tsx.
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ==========================================================================
|
||||
* Шапка (HeaderV3 + CityPicker)
|
||||
* Шапка (HeaderV3)
|
||||
* ========================================================================== */
|
||||
|
||||
.hdrRoot {
|
||||
|
|
@ -40,11 +41,15 @@
|
|||
border-bottom: 1px solid var(--b2c-line);
|
||||
}
|
||||
|
||||
/* База — узкий экран: в шапке остаются только лого и «Для бизнеса», они
|
||||
помещаются в одну строку, поэтому и высота узкая (`flex-wrap` тут страховка,
|
||||
а не режим работы). Навигация и CTA возвращаются в @media-блоке в конце
|
||||
секции. */
|
||||
.hdrInner {
|
||||
max-width: 1280px;
|
||||
margin-inline: auto;
|
||||
padding: 10px clamp(20px, 5vw, 56px);
|
||||
min-height: 64px;
|
||||
padding: 8px clamp(20px, 5vw, 56px);
|
||||
min-height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px 26px;
|
||||
|
|
@ -101,7 +106,10 @@
|
|||
}
|
||||
|
||||
.hdrNav {
|
||||
display: flex;
|
||||
/* База — узкий экран, где навигации по секциям НЕТ: четыре пункта
|
||||
переносились в две строки и вместе с остальным делали липкую шапку в 29%
|
||||
экрана. Куда делись пункты — в шапке HeaderV3.tsx. */
|
||||
display: none;
|
||||
gap: 10px 22px;
|
||||
flex-wrap: wrap;
|
||||
font-size: 14.5px;
|
||||
|
|
@ -119,8 +127,9 @@
|
|||
color: var(--b2c-accent-text);
|
||||
}
|
||||
|
||||
/* «Статьи» — раздела нет в коде (ни маршрута, ни контента): пункт нарочно
|
||||
неинтерактивен (aria-disabled, без href), а не ссылка в 404. */
|
||||
/* «Продажа под ключ» — раздела нет в коде (ни маршрута, ни контента): пункт
|
||||
нарочно неинтерактивен (aria-disabled, без href), а не ссылка в 404.
|
||||
«Статьи» стояли здесь же, пока не появился `articles/`. */
|
||||
.hdrNavDisabled {
|
||||
color: var(--b2c-muted);
|
||||
opacity: 0.65;
|
||||
|
|
@ -164,7 +173,11 @@
|
|||
color: var(--b2c-on-accent);
|
||||
}
|
||||
|
||||
/* На узком экране призыв в шапке скрыт: он вёл туда же, куда липкая нижняя
|
||||
панель (`.barRoot`), и два одинаковых призыва на одном экране — это ровно то
|
||||
«много всплывашек», на которое жалуются. Панель остаётся, шапка отдаёт. */
|
||||
.hdrCta {
|
||||
display: none;
|
||||
padding: 11px 22px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
|
@ -174,146 +187,24 @@
|
|||
filter: brightness(0.92);
|
||||
}
|
||||
|
||||
/* -- Селектор города (CityPicker) ---------------------------------------- */
|
||||
/* Шапка макета целиком — с той ширины, на которой она РЕАЛЬНО влезает в одну
|
||||
строку (замерено: 1000px — лого, четыре пункта, «Для бизнеса» и кнопка;
|
||||
на 720px то же самое переносится в две строки и даёт 109px липкого хрома,
|
||||
то есть ровно тот дефект, от которого узкий экран и лечили). Отсюда шаг
|
||||
1000, а не общий для файла 720. */
|
||||
@media (min-width: 1000px) {
|
||||
.hdrInner {
|
||||
padding-block: 10px;
|
||||
min-height: 64px;
|
||||
}
|
||||
|
||||
.hdrCityWrap {
|
||||
position: relative;
|
||||
}
|
||||
.hdrNav {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.hdrCityBtn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: none;
|
||||
border: 1px solid var(--b2c-line);
|
||||
border-radius: 6px;
|
||||
padding: 9px 14px;
|
||||
cursor: pointer;
|
||||
font-family: var(--b2c-font-sans);
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: var(--b2c-ink);
|
||||
}
|
||||
|
||||
.hdrCityBtn:hover {
|
||||
border-color: var(--b2c-accent);
|
||||
color: var(--b2c-accent-text);
|
||||
}
|
||||
|
||||
.hdrCityDot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
flex: 0 0 auto;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
background: var(--b2c-accent);
|
||||
}
|
||||
|
||||
.hdrCityCaret {
|
||||
font-family: var(--b2c-font-mono);
|
||||
font-size: 11px;
|
||||
color: var(--b2c-muted);
|
||||
}
|
||||
|
||||
.hdrCityPanel {
|
||||
position: absolute;
|
||||
top: calc(100% + 10px);
|
||||
left: 0;
|
||||
z-index: 80;
|
||||
width: min(84vw, 340px);
|
||||
max-width: calc(100vw - 40px);
|
||||
overflow: hidden;
|
||||
background: var(--b2c-surface);
|
||||
border: 1px solid var(--b2c-line);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 24px 64px color-mix(in srgb, var(--b2c-ink) 18%, transparent);
|
||||
}
|
||||
|
||||
.hdrCitySearchRow {
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid var(--b2c-line-soft);
|
||||
}
|
||||
|
||||
.hdrCityInput {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid var(--b2c-line);
|
||||
border-radius: 6px;
|
||||
padding: 11px 14px;
|
||||
font-family: var(--b2c-font-sans);
|
||||
font-size: 14.5px;
|
||||
color: var(--b2c-ink);
|
||||
background: var(--b2c-page-bg);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.hdrCityInput:focus {
|
||||
border-color: var(--b2c-accent);
|
||||
background: var(--b2c-surface);
|
||||
}
|
||||
|
||||
.hdrCityList {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.hdrCityItem {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 11px 18px;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
font-family: var(--b2c-font-sans);
|
||||
}
|
||||
|
||||
.hdrCityItem:hover {
|
||||
background: var(--b2c-page-bg);
|
||||
}
|
||||
|
||||
/* Текущий выбранный город (проставляется из CityPicker.tsx как data-атрибут,
|
||||
не класс — состояние живёт в JS, а не в CSS-модуле). */
|
||||
.hdrCityItem[data-active="true"] {
|
||||
background: var(--b2c-surface-soft);
|
||||
}
|
||||
|
||||
.hdrCityItem[data-active="true"] .hdrCityItemName {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.hdrCityItemName {
|
||||
font-size: 14.5px;
|
||||
font-weight: 600;
|
||||
color: var(--b2c-ink);
|
||||
}
|
||||
|
||||
.hdrCityItemNote {
|
||||
font-family: var(--b2c-font-mono);
|
||||
font-size: 10.5px;
|
||||
color: var(--b2c-muted);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hdrCityEmpty {
|
||||
margin: 0;
|
||||
padding: 22px 18px;
|
||||
font-size: 14px;
|
||||
line-height: 1.55;
|
||||
color: var(--b2c-muted);
|
||||
}
|
||||
|
||||
.hdrCityFooter {
|
||||
padding: 12px 18px;
|
||||
border-top: 1px solid var(--b2c-line-soft);
|
||||
font-family: var(--b2c-font-mono);
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--b2c-muted);
|
||||
.hdrCta {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
|
|
@ -472,16 +363,10 @@
|
|||
/* Компенсация fixed-позиционирования `.barRoot` (тот вырезан из потока
|
||||
документа): без спейсера панель легла бы поверх последних пикселей
|
||||
страницы при докрутке до конца (реквизиты в подвале, последний вопрос
|
||||
FAQ). Высота — на мобильном тексте+кнопка чаще переносятся на две строки
|
||||
(flex-wrap), поэтому база выше; на 720px+ строка одна. */
|
||||
FAQ). Высота одна на все ширины: панель везде в одну строку — на узком
|
||||
экране за счёт того, что текст скрыт (см. `.barText`), а не переносится. */
|
||||
.barSpacer {
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
@media (min-width: 720px) {
|
||||
.barSpacer {
|
||||
height: 68px;
|
||||
}
|
||||
height: 68px;
|
||||
}
|
||||
|
||||
.barRoot {
|
||||
|
|
@ -495,14 +380,20 @@
|
|||
justify-content: center;
|
||||
gap: 16px 24px;
|
||||
flex-wrap: wrap;
|
||||
padding: 12px clamp(16px, 4vw, 32px);
|
||||
padding: 10px clamp(16px, 4vw, 32px);
|
||||
/* Фоллбэк на непрозрачный surfaceDark для браузеров без color-mix(). */
|
||||
background: var(--b2c-surface-dark);
|
||||
background: color-mix(in srgb, var(--b2c-surface-dark) 97%, transparent);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
/* На узком экране панель — только кнопка. Строка «Узнайте цену своей
|
||||
квартиры…» переносилась на две-три строки и делала постоянную панель втрое
|
||||
выше кнопки; то же самое сказано словами в герое (заголовок, лид и перк
|
||||
«Бесплатно: сколько похожих квартир продаётся рядом»), то есть со страницы
|
||||
мысль не пропадает — пропадает её третий повтор поверх контента. */
|
||||
.barText {
|
||||
display: none;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
|
|
@ -518,6 +409,18 @@
|
|||
font-size: 14.5px;
|
||||
}
|
||||
|
||||
/* Панель макета целиком — с той же ширины, что и шапка (1000px): ниже неё
|
||||
текст и кнопка тоже переносились, и панель становилась вдвое выше. */
|
||||
@media (min-width: 1000px) {
|
||||
.barRoot {
|
||||
padding-block: 12px;
|
||||
}
|
||||
|
||||
.barText {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
* HERO (hero*) — первый экран: герой-текст + карточка «Бесплатная проверка».
|
||||
* Секция «Герой» = HeroV3.tsx + FreeCheckCard.tsx + FreeResultV3.tsx.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue