/* Лендинг kvadro.app. Шрифт — как в Mini App (системный), монохром, жёлтый — только кнопки. */
:root {
  --ink: #222222;
  --plate: #f0f0f2; /* нейтральный серый: блок финала и QR-карточка в углу */
  --hint: #6a6a6a;
  --fog: #f7f7f7;
  --line: #ebebeb;
  --accent: #ffd23f;
  --accent-hover: #ffc800;
  --accent-text: #0b0b0b;
  color-scheme: light;
}
* { box-sizing: border-box; }
html, body { margin: 0; }
/* iOS в горизонтальной ориентации иначе сам увеличивает текст */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
a, button, summary { -webkit-tap-highlight-color: transparent; }
body {
  background: #ffffff;
  color: var(--ink);
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}
a { color: var(--ink); }
img { display: block; max-width: 100%; }
h1, h2, p { margin: 0; }

.wrap { max-width: 1280px; margin: 0 auto; padding: 0 40px; }
.top { position: absolute; top: 0; left: 0; right: 0; z-index: 10; display: flex; align-items: center; justify-content: center; height: 80px; }
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; font-weight: 700; font-size: 21px; letter-spacing: -0.02em; }
.brand img { border-radius: 9px; }
/* Язык: справа в шапке (и в подвале). Тексты Mini App в телефоне переключаются сразу */
.lang { position: absolute; right: 24px; top: 50%; transform: translateY(-50%); }
.lang-btn {
  display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 12px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent); background: transparent; color: var(--ink);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
@media (hover: hover) { .lang-btn:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); } }
.lang-btn:focus-visible, .lang-menu button:focus-visible, .foot-lang button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.lang-menu {
  position: absolute; right: 0; top: 44px; min-width: 168px; padding: 6px; border-radius: 16px; background: #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,.06), 0 18px 40px -12px rgba(0,0,0,.35); display: flex; flex-direction: column;
}
.lang-menu[hidden] { display: none; }
.lang-menu button {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; height: 40px; padding: 0 12px;
  border: 0; border-radius: 10px; background: none; color: #222; font: inherit; font-size: 15px; text-align: left; cursor: pointer;
}
@media (hover: hover) { .lang-menu button:hover { background: #f2f2f4; } }
.lang-menu button[aria-checked="true"] { font-weight: 600; }
.lang-menu button[aria-checked="true"]::after { content: "✓"; }
.foot-lang { display: flex; gap: 4px 14px; flex-wrap: wrap; }
.foot-lang button { border: 0; background: none; padding: 0; font: inherit; color: var(--hint); cursor: pointer; }
.foot-lang button[aria-pressed="true"] { color: var(--ink); font-weight: 600; }
@media (max-width: 760px) { .lang { right: 16px; } .lang-btn { height: 40px; } }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  height: 56px; padding: 0 28px; border-radius: 999px;
  background: var(--accent); color: var(--accent-text);
  font-weight: 600; font-size: 17px; text-decoration: none;
  transition: background .2s ease, transform .1s ease;
}
@media (hover: hover) { .btn:hover { background: var(--accent-hover); color: var(--accent-text); } }
.btn:active { transform: scale(.97); }
.btn-sm { height: 44px; padding: 0 20px; font-size: 15px; }

.section-head { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 18px; }
.section-head h2 { font-size: clamp(32px, 3.8vw, 56px); line-height: 1.04; letter-spacing: -0.035em; font-weight: 700; text-wrap: balance; }
.lead { font-size: 20px; line-height: 1.5; color: var(--hint); text-wrap: pretty; }

/* Переключатель, как в Mini App */
.lseg { display: inline-flex; gap: 4px; padding: 4px; border-radius: 999px; background: #f1f1f3; }
.lseg button {
  font: inherit; font-size: 15px; font-weight: 600; height: 44px; padding: 0 20px;
  border-radius: 999px; border: 0; background: transparent; color: #4a4a50; cursor: pointer;
  transition: background .2s ease, color .2s ease, box-shadow .2s ease;
}
.lseg button[aria-pressed="true"] { background: #ffffff; color: var(--ink); box-shadow: 0 1px 2px rgba(0,0,0,.08), 0 4px 12px -4px rgba(0,0,0,.12); }

.btn:focus-visible, .lseg button:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

@media (max-width: 760px) {
  .wrap { padding: 0 16px; }
  .lseg button { height: 40px; padding: 0 12px; font-size: 14px; white-space: nowrap; }
}
@media (prefers-reduced-motion: reduce) {
  .btn, .lseg button { transition: none; }
}

/* ---------- Общее для блоков ---------- */
h2 { font-size: clamp(32px, 3.8vw, 56px); line-height: 1.04; letter-spacing: -0.035em; font-weight: 700; text-wrap: balance; }
.muted { color: var(--hint); }

/* ---------- 1. Облако постов ---------- */
.story { --bg: #ffffff; position: relative; height: 6950px; background: var(--bg); timeline-scope: --cloud; }
/* Прогресс сцен считается по невидимой копии секции (tl-proxy), а не по самой секции: landing.js сдвигает
   её так, что анимации догоняют прокрутку плавно и не быстрее предела (быстрая прокрутка не проскакивает
   шаги). Без сдвига (?motion=raw, нет JS) — ровно как по секции */
.tl-proxy { position: absolute; left: 0; top: 0; width: 1px; height: 100%; visibility: hidden; pointer-events: none; view-timeline-axis: block; }
.tl-cloud { view-timeline-name: --cloud; }
/* браузер без timeline-scope: имя копии не видно остальной секции — таймлайн по самой секции, без сглаживания */
@supports not (timeline-scope: --a) {
  .story { view-timeline-name: --cloud; view-timeline-axis: block; }
  .tl-proxy { display: none; }
}

/* Тёмный первый экран (решение владельца 13.10): посты — как в тёмном Telegram, жёлтая кнопка горит на чёрном */
.hero-dark .top, .hero-dark .story { --ink: #f5f5f7; --hint: #a1a1a6; color: var(--ink); }
.hero-dark .story { --bg: #0e0e10; }
/* скруглённый низ тёмной сцены — белыми уголками поверх, а не обрезкой: скругление с overflow на блоке
   в 6950 px с анимированными слоями внутри заставляло браузер перерисовывать маску на каждом кадре */
.hero-dark .story::before, .hero-dark .story::after { content: ""; position: absolute; z-index: 5; bottom: 0; width: 40px; height: 40px; pointer-events: none; }
.hero-dark .story::before { left: 0; background: radial-gradient(circle at 100% 0, transparent 39.5px, #fff 40px); }
.hero-dark .story::after { right: 0; background: radial-gradient(circle at 0 0, transparent 39.5px, #fff 40px); }
.hero-dark .post { background: #1c1c1e; box-shadow: 0 0 0 1px rgba(255,255,255,.06), 0 18px 40px -12px rgba(0,0,0,.7); }
.hero-dark .bar { background: #2c2c2e; }
/* на тёмном фоне чёрная рамка телефона сливается — светлая кромка */
/* корпус — как у телефона в «Узнавайте первым» (.lphone; владелец 17.10): титановый ободок и боковые кнопки; на
   тёмном фоне — глубже тень */
.hero-dark .phone {
  box-shadow: inset 0 0 0 calc(2px * var(--ps)) #3a3a3c, 0 0 0 calc(2.5px * var(--ps)) #7c7d82, 0 0 0 calc(3.5px * var(--ps)) #2c2c2e,
    0 50px 120px -30px rgba(0,0,0,.9);
}
/* --ps — масштаб телефона по высоте экрана; --py — сдвиг телефона от центра сцены по вертикали (на телефоне он
   ниже, над ним текст); --px — куда телефон уезжает вправо, когда слева появляется текст; --gy — куда летят посты
   (первая карточка ленты в телефоне: на 72 «точки» выше центра экрана) */
/* --ps и --shift зарегистрированы, чтобы плавно меняться: в конце сцены (класс live, landing.js) телефон
   вырастает до --ps-full и выезжает в центр (--shift 1 -> 0) */
@property --ps { syntax: "<number>"; inherits: true; initial-value: .8; }
@property --shift { syntax: "<number>"; inherits: true; initial-value: 1; }
/* --pt — верх телефона на узком экране (landing.js, fitScene): у прототипа и экрана блокировки свой, телефон
   переезжает плавно */
@property --pt { syntax: "<length>"; inherits: true; initial-value: 184px; }
.stage {
  --sh: clamp(640px, 100vh, 900px); --ps: .8; --py: 0px; --px: clamp(150px, 20vw, 240px); --shift: 1;
  --gy: calc(var(--py) - 72px * var(--ps));
  position: sticky; top: 0; height: var(--sh); overflow: hidden;
  transition: --ps .6s cubic-bezier(.2,.7,.2,1), --shift .6s cubic-bezier(.2,.7,.2,1), --pt .6s cubic-bezier(.2,.7,.2,1);
}
.stage.live { --ps: var(--ps-full, 1); --shift: 0; }
@media (max-height: 860px) { .stage { --ps: .72; } }
@media (max-height: 760px) { .stage { --ps: .64; } }
@media (max-height: 680px) { .stage { --ps: .58; } }
@supports (height: 100svh) { .stage { --sh: clamp(640px, 100svh, 900px); } }
/* Телефон и планшет: лёгкая отрисовка сцены (фидбэк 14.10 — на iPhone анимация лагала).
   Скругление экрана — обычной обрезкой, без маски: маска заставляла перерисовывать весь экран телефона на
   каждом кадре, пока внутри что-то движется (мигание углов, ради которого она стояла, — в Chrome на компьютере).
   Пуши и кнопки экрана блокировки — плотный фон вместо размытия под ним */
@media (pointer: coarse) {
  /* обои экрана блокировки: карта — просто полупрозрачная, без смешивания цветов (blend перерисовывал весь экран
     блокировки при каждом движении пушей); на тёмных обоях на глаз то же */
  .l-wall::before { mix-blend-mode: normal; opacity: .08; }
  /* телефон растёт при переходе к нажимаемой карте — экран масштабируется готовым слоем, без перерисовки */
  .dev { will-change: transform; }
  html .phone-screen, html .lscreen { -webkit-mask-image: none; mask-image: none; } /* html — сильнее правил ниже */
  .push { background: rgba(245, 245, 247, .96); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .l-btn { background: rgba(60, 60, 64, .7); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
/* телефон: сцена высотой в «маленький» экран (svh), а когда панели браузера спрятаны, видно больше — сцену
   держит посередине видимого landing.js (top у .stage, по visualViewport).
   Размер и место телефона (--ps, --pt: живая карта, экран блокировки) здесь меняются сразу, без перехода: это
   размеры в вёрстке — экран приложения раскладывался и перерисовывался на каждом кадре перехода (замер 16.10:
   60–100 раскладок и 300–700 перерисовок за переход, рывки на iPhone). Плавно к новому месту едет готовая
   картинка телефона (landing.js, morphPhone). Лента, шторка фильтров, карта и экран блокировки — своими слоями:
   сдвигаются и проявляются готовыми, без перерисовки экрана */
@media (pointer: coarse) {
  .stage { transition: top .25s cubic-bezier(.2,.7,.2,1); }
  .dev .m-app .feed, .dev .fsheet, .dev .fsheet-body { will-change: transform; }
  .dev .m-maplayer, .dev .sheet-backdrop, .dev .m-lock { will-change: opacity; }
  /* уведомления гаснут под часами без маски: маска перерисовывала их на каждом кадре сдвига */
  .l-pushes { -webkit-mask-image: none; mask-image: none; }
}
.hero {
  position: absolute; left: 50%; top: 50%; width: min(1000px, 92vw); transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 22px; z-index: 2;
}
/* мягкий белый ореол: даже если пост подлетит близко, текст читается */
.hero::before { content: ""; position: absolute; inset: -56px -96px; background: radial-gradient(closest-side, var(--bg) 62%, transparent); z-index: -1; pointer-events: none; }
.hero .hero-title { font-size: clamp(40px, 5.6vw, 80px); line-height: 1.02; letter-spacing: -0.035em; font-weight: 700; text-wrap: balance; }
/* h1 страницы — строка запроса над лозунгом (видимая: скрытый текст поисковики наказывают); ближе к лозунгу, чем
   остальные строки первого экрана */
.hero .hero-kicker { font-size: 15px; line-height: 1.3; font-weight: 600; letter-spacing: 0.01em; color: var(--hint); margin-bottom: -10px; }
.post {
  position: absolute; z-index: 4; left: 50%; top: 50%; width: var(--w, 220px); background: #fff; border-radius: 18px; padding: 8px;
  box-shadow: 0 0 0 1px rgba(0,0,0,.04), 0 18px 40px -12px rgba(0,0,0,.18);
  display: flex; flex-direction: column; gap: 7px; filter: blur(var(--b, 0px)); will-change: transform, opacity;
  --ty: calc(var(--y) * var(--sh));
  transform: translate(calc(-50% + var(--x)), calc(-50% + var(--ty))) rotate(var(--r)) scale(var(--k, 1));
}
.post img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 12px; }
.post p { padding: 0 4px 2px; font-size: 13px; line-height: 1.4; }
.post-meta { display: flex; align-items: center; gap: 6px; padding: 2px 4px 0; }
.ava { width: 18px; height: 18px; border-radius: 999px; }
.bar { height: 7px; border-radius: 4px; background: #e6e6ea; }
/* --y — доля высоты сцены от центра; верх по центру свободен под логотип */
.p1 { --x: -36vw; --y: -.3; --r: -6deg; --s: 2.48%; --w: 210px; }
.p2 { --x: 35vw; --y: -.29; --r: 5deg; --s: 3.31%; --w: 200px; --b: 1.5px; --k: .86; }
.p3 { --x: -42vw; --y: .09; --r: 4deg; --s: 4.13%; --w: 190px; --b: 2px; --k: .8; }
.p4 { --x: 41vw; --y: .12; --r: -4deg; --s: 4.96%; --w: 220px; }
.p5 { --x: -24vw; --y: .33; --r: 7deg; --s: 5.79%; --w: 200px; --b: 1px; --k: .9; }
.p6 { --x: 25vw; --y: .33; --r: -8deg; --s: 6.61%; --w: 210px; --b: 1.5px; --k: .85; }
.p7 { --x: 2vw; --y: .4; --r: 3deg; --s: 7.44%; --w: 180px; --b: 2.5px; --k: .75; }
@media (max-width: 1279px) {
  .p1 { --x: -30vw; --y: -.32; --w: 180px; } .p2 { --x: 30vw; --y: -.32; --w: 170px; }
  .p3 { --x: -47vw; --y: .02; --w: 170px; }  .p4 { --x: 47vw; --y: .03; --w: 180px; }
  .p5 { --x: -26vw; --y: .33; --w: 170px; }  .p6 { --x: 26vw; --y: .34; --w: 170px; }
  .p7 { --x: 0vw; --y: .4; --w: 150px; }
}
/* широкий, но низкий экран ноутбука (1280×720, 1366×768, 1440×800): верхние посты меньше и выше — иначе
   задевают первую строку заголовка */
@media (min-width: 1280px) and (max-height: 820px) {
  .p1 { --y: -.335; --k: .84; } .p2 { --y: -.33; --k: .76; }
}
@media (max-width: 760px) {
  .p1 { --x: -38vw; --y: -.34; --w: 130px; --r: -8deg; } .p2 { --x: 38vw; --y: -.335; --w: 124px; --r: 7deg; }
  .p5 { --x: -30vw; --y: .36; --w: 128px; } .p6 { --x: 30vw; --y: .37; --w: 128px; }
  .p3, .p4, .p7 { display: none; }
  .post p { font-size: 11px; }
  /* размытие слоёв, которые двигаются при прокрутке, — заметная нагрузка для телефона */
  .post { filter: none; }
}
@media (max-width: 380px) {
  .p1 { --w: 112px; --y: -.3; } .p2 { --w: 108px; --y: -.29; }
  .p5, .p6 { --w: 112px; }
}
/* низкий телефон (iPhone SE, Android 360×640): верхние посты меньше, в две строки текста и прижаты к краям —
   иначе ложатся на заголовок, а правый — на кнопку языка */
@media (max-width: 760px) and (max-height: 700px) {
  .post p { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
  .p1 { --y: -.36; --k: .85; } .p2 { --x: 45vw; --y: -.29; --k: .82; }
}
/* узбекский и английский заголовок первого экрана длиннее (слово «Telegramdagi», подзаголовок в две строки) —
   на узком низком телефоне чуть мельче, иначе верхние посты ложатся на него */
@media (max-width: 380px) and (max-height: 700px) {
  html:lang(uz) .hero .hero-title, html:lang(en) .hero .hero-title { font-size: 34px; }
  html:lang(uz) .hero .hero-kicker, html:lang(en) .hero .hero-kicker { margin-bottom: -6px; }
  html:lang(uz) .hero, html:lang(en) .hero { gap: 16px; }
}
/* маленький телефон лёжа (667×375): сверху места нет — верхние посты по бокам заголовка, на середине высоты */
@media (max-width: 760px) and (max-height: 480px) {
  .p1 { --x: -42vw; --y: -.02; } .p2 { --x: 42vw; --y: .02; }
}
.story-cap { position: absolute; left: 0; right: 0; top: max(12px, calc(50% - 433px * var(--ps) - 64px)); text-align: center; font-size: clamp(24px, 2.8vw, 38px); line-height: 1.15; text-wrap: balance; font-weight: 700; letter-spacing: -0.03em; padding: 0 16px; opacity: 0; }

/* ---------- 2. Узнавайте первым: экран блокировки ----------
   Пуши о настоящих новых квартирах (/api/landing/live) приходят сами, когда телефон на экране, — по таймеру,
   не от прокрутки; новые за время на странице — тоже пушем. Под телефоном — счётчик за сутки (или неделю).
   Обои — подложка карты лендинга; время и дата — настоящие, по Ташкенту (landing.js) */
.live-story { background: var(--fog); padding: 128px 0 120px; }
.live-wrap { display: flex; flex-direction: column; align-items: center; gap: 48px; }
.live-wrap .lead { max-width: 560px; }
/* Телефон — как в первой сцене: экран в «точках» iPhone (390×844) уменьшен целиком (--lps), рамка и углы в тех же
   пропорциях; статус-бар — тот же (.m-status, белый). Корпус — титановый ободок и боковые кнопки */
.lphone {
  --lps: .88; position: relative; padding: calc(12px * var(--lps)); border-radius: calc(60px * var(--lps));
  background: #0b0b0b;
  box-shadow: inset 0 0 0 calc(2px * var(--lps)) #3a3a3c, 0 0 0 calc(2.5px * var(--lps)) #7c7d82, 0 0 0 calc(3.5px * var(--lps)) #2c2c2e,
    0 50px 90px -40px rgba(0,0,0,.45), 0 20px 40px -24px rgba(0,0,0,.3);
}
/* кнопки: справа — питание, слева — действие и громкость (одна полоска и её тени) */
.lphone::before, .lphone::after { content: ""; position: absolute; width: calc(4px * var(--lps)); border-radius: 2px; background: #6e6f74; }
.lphone::before { right: calc(-6px * var(--lps)); top: calc(250px * var(--lps)); height: calc(100px * var(--lps)); }
.lphone::after {
  left: calc(-6px * var(--lps)); top: calc(160px * var(--lps)); height: calc(34px * var(--lps));
  box-shadow: 0 calc(66px * var(--lps)) 0 0 #6e6f74, 0 calc(140px * var(--lps)) 0 0 #6e6f74;
}
.lscreen {
  position: relative; width: calc(390px * var(--lps)); height: calc(844px * var(--lps)); border-radius: calc(48px * var(--lps));
  overflow: hidden; isolation: isolate; background: #111;
  -webkit-mask-image: -webkit-radial-gradient(white, black); mask-image: radial-gradient(white, black);
}
.ldev {
  position: absolute; left: 0; top: 0; width: 390px; height: 844px; transform: scale(var(--lps)); transform-origin: 0 0;
  color: #fff; overflow: hidden;
}
/* обои экрана блокировки: тёмные, снизу тёплое жёлтое свечение (цвет кнопок), еле видная карта Ташкента */
.l-wall {
  background:
    radial-gradient(120% 70% at 20% 108%, rgba(255, 210, 63, .85), rgba(255, 170, 40, .35) 38%, transparent 66%),
    radial-gradient(90% 55% at 100% 0%, rgba(90, 110, 160, .45), transparent 70%),
    linear-gradient(180deg, #15161b, #1d1f27 55%, #2a2118);
}
.l-wall::before { content: ""; position: absolute; inset: 0; background: url("map-tashkent.webp") 58% 38% / auto 120% no-repeat; opacity: .12; mix-blend-mode: screen; }
.ldev .m-status { color: #fff; }
/* дата и часы экрана блокировки iOS: дата — 22 pt, часы — крупно и плотно */
.l-date { position: absolute; left: 0; right: 0; top: 76px; text-align: center; font: 600 22px/1.2 -apple-system, BlinkMacSystemFont, "SF Pro Display", sans-serif; opacity: .9; }
.l-clock {
  position: absolute; left: 0; right: 0; top: 98px; text-align: center;
  font: 700 104px/1 -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", sans-serif; letter-spacing: -2px; font-variant-numeric: tabular-nums;
}
/* уведомления — внизу, над фонариком и камерой (как в iOS 16+): новое приходит снизу, старые уходят вверх и гаснут */
.l-pushes {
  position: absolute; left: 10px; right: 10px; top: 250px; bottom: 112px; display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden;
  -webkit-mask-image: linear-gradient(transparent, #000 60px); mask-image: linear-gradient(transparent, #000 60px);
}
/* пуш в «слоте»: новый всплывает снизу, остальные съезжают вверх сдвигом (landing.js, addPushTo) — раньше слот
   раздвигался по высоте, и уведомления раскладывались заново на каждом кадре (16.10) */
.push-slot { display: block; }
.push-in { padding-top: 8px; }
.push {
  display: flex; gap: 11px; align-items: center; padding: 13px 14px; border-radius: 24px; color: #111; text-decoration: none;
  background: rgba(245, 245, 247, .82); -webkit-backdrop-filter: blur(24px) saturate(170%); backdrop-filter: blur(24px) saturate(170%);
  font: 15px/1.3 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", sans-serif;
  opacity: 0; transform: translateY(18px) scale(.97); transition: opacity .35s ease .08s, transform .5s cubic-bezier(.2,.8,.2,1) .08s;
}
.push-slot.in .push { opacity: 1; transform: none; }
.push img { flex: 0 0 auto; border-radius: 9px; }
.push-text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.push-top { display: flex; justify-content: space-between; gap: 8px; }
.push-top b { font-weight: 600; }
.push-top span { color: rgba(60, 60, 67, .6); font-size: 13px; white-space: nowrap; }
.push-text > b { font-weight: 400; }
a.push { cursor: pointer; }
.l-btn {
  position: absolute; bottom: 46px; width: 50px; height: 50px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: rgba(30, 30, 34, .45); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
}
.l-torch { left: 46px; }
.l-cam { right: 46px; }
.ldev .l-home { background: #fff; }
/* v2 (владелец 17.10): телефон крупнее и обрезан сверху — видна нижняя часть с уведомлениями (часы не нужны);
   срез уходит в фон блока плавно (наложенный градиент, не маска: маска перерисовывала бы пуши на каждом кадре).
   Высоту среза и размер телефона считает landing.js (lsFit); снизу — место под тень телефона */
.lcrop, .lcrop-in { display: contents; }
.lcrop-fade { display: none; }
html.v2 .lcrop { display: block; position: relative; width: 100%; height: var(--lcrop-h, 520px); }
/* режем внутренним слоем и только сверху (по бокам и снизу — тень телефона, иначе виден прямоугольник), на 3 px ниже
   края: градиент — снаружи среза и у края плотный, поэтому сглаженный край среза под ним не виден (на iPhone в крайней
   строке сквозь полупрозрачный градиент проступал тёмный телефон — тонкая чёрная полоска, 18.10) */
html.v2 .lcrop-in {
  display: flex; position: absolute; inset: 0; padding-bottom: 28px; box-sizing: border-box;
  justify-content: center; align-items: flex-end; clip-path: inset(3px -200px -200px -200px);
}
html.v2 .lcrop .lphone { flex: none; }
/* небольшой параллакс (владелец 17.10): пока блок проходит экран, телефон в срезе едет вверх чуть быстрее страницы —
   от +64 px (блок только показался снизу) до −48 px (уходит вверх). Привязан к прокрутке (view-timeline среза) — на
   iPhone такое рисуется на главном потоке, но это один слой; «уменьшить движение» — без него */
@supports (view-timeline: --a) {
  html.v2 .lcrop { view-timeline: --lcrop block; }
  html.v2 .lcrop .lphone { animation: lp-parallax linear both; animation-timeline: --lcrop; animation-range: cover 0% cover 100%; }
}
@keyframes lp-parallax { from { transform: translateY(64px); } to { transform: translateY(-48px); } }
@media (prefers-reduced-motion: reduce) { html.v2 .lcrop .lphone { animation: none; } }
html.v2 .lcrop-fade {
  display: block; position: absolute; z-index: 2; left: calc(50% - 50vw); width: 100vw; top: 0; height: 16%; pointer-events: none;
  background: linear-gradient(var(--fog), rgba(247, 247, 247, 0)); /* во всю ширину экрана: накрывает и срез тени; слабее (17.10) */
}
html.v2 .live-story { overflow-x: clip; } /* тень и срез телефона не расширяют страницу (clip — не мешает sticky) */
/* счётчик: за сутки (или неделю) — крупно */
.live-count { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; margin-top: -8px; }
.live-count[hidden] { display: none; }
.live-count b { font-size: clamp(48px, 6vw, 72px); line-height: 1; font-weight: 700; letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
.live-count > span { font-size: 17px; color: var(--hint); }
@media (max-width: 760px) {
  .live-story { padding: 88px 0 96px; }
  .live-wrap { gap: 36px; }
  .lphone { --lps: .74; } /* 414 точек × .74 ≈ 306 px */
}
@media (prefers-reduced-motion: reduce) {
  .push { transition: none; }
}

/* ---------- 3. Хозяин или риелтор: «Хозяин ◐ Риелтор» — заголовок и есть переключатель ----------
   Слева три хозяина, справа три риелтора, под каждой карточкой — «почему». Карточки уезжают в сторону переключения
   (landing.js). Активное слово — чёрное, другое — серое; нажимаются и слова, и тумблер. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.o-grid { width: 100%; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px 18px; margin-top: 4px; }
.o-card { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 14px; }
.o-photo { position: relative; margin-bottom: 8px; }
.o-photo img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: 16px; }
.o-badge { position: absolute; left: 10px; top: 10px; height: 26px; padding: 0 10px; border-radius: 999px; font-size: 13px; font-weight: 600; display: flex; align-items: center; box-shadow: 0 2px 8px rgba(0,0,0,.18); }
.o-badge.owner { background: var(--ink); color: #fff; }
.o-badge.agent { background: #fff; color: var(--ink); }
.o-badge.none { background: #fff; color: var(--hint); }
.o-price { font-size: 18px; font-weight: 700; letter-spacing: -0.03em; }
.o-price small { font-size: 13px; font-weight: 500; color: var(--hint); letter-spacing: 0; }
.o-params { color: var(--ink); }
.o-district { color: var(--hint); }
/* «почему» — строка с иконкой, у всех карточек одинаковая */
.o-ev { display: flex; align-items: flex-start; gap: 7px; margin-top: 8px; padding: 8px 10px; border-radius: 12px; background: var(--fog); font-size: 13px; line-height: 1.35; color: var(--hint); }
.o-ev svg { flex: 0 0 auto; margin-top: 1px; color: var(--ink); }
.o-ev b { color: var(--ink); font-weight: 600; }
.or2 { display: flex; flex-direction: column; align-items: center; gap: 26px; padding-top: 128px; padding-bottom: 128px; }
.or2-head { --h: clamp(42px, 5vw, 66px); --w: calc(var(--h) * 1.72); display: flex; align-items: center; justify-content: center; gap: clamp(12px, 2.2vw, 30px); }
.or2-word {
  padding: 0; border: 0; background: none; font: inherit; font-size: clamp(38px, 5.6vw, 80px); line-height: 1; font-weight: 700;
  letter-spacing: -0.045em; color: #c9c9ce; cursor: pointer; transition: color .3s ease;
}
/* неактивное слово — светло-серое (решение владельца 13.10: темнее, до контраста 3:1, — не надо) */
.or2-head[data-side="owner"] .or2-word[data-side="owner"], .or2-head[data-side="agent"] .or2-word[data-side="agent"] { color: var(--ink); }
@media (hover: hover) { .or2-word:hover { color: #8e8e93; } }
.or2-switch { position: relative; flex: 0 0 auto; width: var(--w); height: var(--h); padding: 0; border: 0; border-radius: 999px; background: var(--ink); cursor: pointer; }
.or2-knob {
  position: absolute; left: 4px; top: 4px; width: calc(var(--h) - 8px); height: calc(var(--h) - 8px); border-radius: 50%; background: #fff;
  box-shadow: 0 3px 8px rgba(0,0,0,.25); transition: transform .35s cubic-bezier(.3,1.3,.5,1);
}
.or2-head[data-side="agent"] .or2-knob { transform: translateX(calc(var(--w) - var(--h))); }
.or2-word:focus-visible, .or2-switch:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 12px; }
.or2-switch:focus-visible { border-radius: 999px; }
.or2-lead { text-align: center; max-width: 620px; min-height: 3em; }
.or2-stage { width: 100%; max-width: 780px; }
.or2-set[hidden] { display: none; }
@media (max-width: 760px) {
  .or2 { gap: 20px; padding-top: 96px; padding-bottom: 96px; }
  .or2-head { --h: 36px; gap: 10px; }
  .or2-word { font-size: clamp(26px, 8.4vw, 34px); }
  .or2-lead { font-size: 17px; }
  /* на телефоне карточки — в ряд с прокруткой вбок: от края до края экрана, следующая выглядывает справа,
     листаются по одной (scroll-snap) */
  .or2-stage { width: calc(100% + 32px); margin: 0 -16px; }
  .or2-set.o-grid {
    grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: min(78%, 300px); gap: 12px; margin: 0;
    padding: 0 16px 4px; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-padding: 0 16px;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .or2-set.o-grid::-webkit-scrollbar { display: none; }
  .or2 .o-card { scroll-snap-align: start; }
}
@media (prefers-reduced-motion: reduce) { .or2-knob, .or2-word { transition: none; } }

/* ---------- 4. «Хорошая ли цена»: экономия в деньгах ---------- */
.pc { display: flex; flex-direction: column; align-items: center; gap: 28px; padding-top: 112px; padding-bottom: 128px; }
.pc-save-box { width: 100%; max-width: 760px; display: flex; flex-direction: column; align-items: center; gap: 22px; text-align: center; padding: 48px 28px; border-radius: 40px; background: var(--fog); }
.pc-save-pre { font-size: 19px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: -6px; text-wrap: balance; }
.pc-save-big { display: flex; flex-direction: column; align-items: center; font-size: clamp(72px, 13vw, 156px); line-height: .9; font-weight: 800; letter-spacing: -0.06em; font-variant-numeric: tabular-nums; }
.pc-save-big small { font-size: 22px; letter-spacing: -0.01em; font-weight: 600; color: var(--hint); margin-top: 12px; }
.pc-save-what { max-width: 580px; font-size: 18px; line-height: 1.45; color: var(--hint); text-wrap: pretty; }
.pc-save-box .pc-districts { width: calc(100% + 56px); margin: 0 -28px; justify-content: safe center; }
.pc-save-week { max-width: 520px; font-size: 16px; line-height: 1.45; color: var(--hint); }
.pc-save-week b { color: var(--ink); }
.pc-save-week[hidden] { display: none; }
/* районы — ряд листается вбок, края гаснут */
.pc-districts {
  display: flex; gap: 6px; padding: 2px 28px; overflow-x: auto; scrollbar-width: none;
  scroll-padding-inline: 28px; -webkit-mask-image: linear-gradient(90deg, transparent, #000 24px, #000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 24px, #000 calc(100% - 24px), transparent);
}
.pc-districts::-webkit-scrollbar { display: none; }
.pc-districts button {
  flex: 0 0 auto; height: 36px; padding: 0 14px; border-radius: 999px; border: 1px solid #e2e2e6; background: #fff;
  color: var(--ink); font: inherit; font-size: 14px; font-weight: 500; cursor: pointer; transition: background .2s ease, color .2s ease;
}
.pc-districts button[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
.pc-districts button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (max-width: 760px) {
  .pc { padding-top: 80px; padding-bottom: 96px; gap: 22px; }
  .pc-save-box { padding: 36px 16px; border-radius: 28px; }
  .pc-save-box .pc-districts { width: calc(100% + 32px); margin: 0 -16px; }
  .pc-save-what { font-size: 16px; }
}

/* ---------- 6. Вопросы ---------- */
.faq-section { display: flex; flex-direction: column; align-items: center; gap: 40px; padding-bottom: 120px; }
.faq { width: 100%; max-width: 760px; }
.faq details { border-top: 1px solid var(--line); }
.faq-col:last-child details:last-child { border-bottom: 1px solid var(--line); }
@media (min-width: 900px) {
  .faq { max-width: 1180px; display: grid; grid-template-columns: 1fr 1fr; gap: 0 64px; align-items: start; }
  .faq-col details:last-child { border-bottom: 1px solid var(--line); }
}
.faq summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 24px 0; font-size: 20px; font-weight: 600; letter-spacing: -0.01em; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: ""; width: 12px; height: 12px; border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink); transform: rotate(45deg) translateY(-4px); transition: transform .2s ease; flex: 0 0 auto; }
.faq details[open] summary::after { transform: rotate(-135deg) translateY(-2px); }
.faq p { padding: 0 0 24px; font-size: 17px; line-height: 1.55; color: var(--hint); max-width: 620px; }

/* ---------- 7. Финал: большой серый блок, как у Klarna ---------- */
.final { padding: 0 16px 96px; }
.final-box {
  max-width: 1180px; margin: 0 auto; display: flex; flex-direction: column; align-items: flex-start; gap: 28px;
  padding: 48px 28px 40px; border-radius: 48px; background: var(--plate); color: var(--ink);
}
.final-main { display: flex; flex-direction: column; align-items: flex-start; gap: 22px; }
/* строка над заголовком: «Бесплатно · 2 942 новые квартиры за неделю» (число — живое, landing.js) */
.final-live { font-size: 17px; line-height: 1.4; }
.final-count[hidden] { display: none; }
.final-live b { font-weight: 700; font-variant-numeric: tabular-nums; }
.final-box h2 { font-size: clamp(44px, 6.4vw, 96px); line-height: .95; font-weight: 800; letter-spacing: -0.05em; max-width: 9.5em; text-wrap: balance; }
.final-qr { display: none; }
/* компьютер: без кнопки — QR прямо на сером справа и «Откройте на телефоне» под ним; на QR прилетает карточка из угла.
   Блок — по центру страницы, поля и скругления одинаковые со всех сторон */
@media (min-width: 900px) and (hover: hover) and (pointer: fine) {
  .final-box {
    flex-direction: row; justify-content: space-between; align-items: center; gap: 48px;
    width: min(100%, 1000px); margin: 0 auto; padding: 72px; border-radius: 64px;
  }
  .final-btn { display: none; }
  .final-qr { display: flex; flex-direction: column; align-items: center; gap: 16px; flex: 0 0 auto; }
  .final-qr img { display: block; width: 220px; height: 220px; }
  .final-qr b { font-size: 22px; font-weight: 800; letter-spacing: -0.03em; }
}

/* подвал: тёмный, строка (©, языки, OpenStreetMap) и огромная надпись kvadro² во всю ширину, как у Klarna */
.foot { margin-top: 24px; background: #0e0e10; color: #a1a1a6; border-radius: 40px 40px 0 0; overflow: hidden; }
.foot-row { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px 24px; padding-top: 40px; padding-bottom: 8px; font-size: 14px; }
.foot a { color: #a1a1a6; }
.foot-rent { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 16px; padding-top: 20px; font-size: 14px; }
.foot-rent b { color: #fff; font-weight: 600; }
.foot .foot-lang button { color: #a1a1a6; }
.foot .foot-lang button[aria-pressed="true"] { color: #fff; }
.foot .foot-lang button:focus-visible { outline-color: #fff; }
.foot-mark {
  margin: 0; padding: 0 16px; font-size: clamp(96px, 25.5vw, 420px); line-height: .78; font-weight: 800; letter-spacing: -0.065em;
  color: #fff; text-align: center; white-space: nowrap; translate: 0 .1em; user-select: none;
  pointer-events: none; /* надпись крупнее своей строки и наезжает на ссылки городов выше — нажатия ей не нужны */
}
.foot-mark span { color: var(--accent); font-size: .42em; vertical-align: .62em; letter-spacing: 0; margin-left: -.02em; }

/* ---------- Анимации, привязанные к прокрутке ---------- */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    :where(html:not(.v2)) .hero { animation: leave linear both; animation-timeline: --cloud; animation-range: contain 0.83% contain 7.44%; }
    :where(html:not(.v2)) .post { animation: gather linear both; animation-timeline: --cloud; animation-range: contain var(--s) contain 18.18%; }
    :where(html:not(.v2)) .phone { animation: phone linear both; animation-timeline: --cloud; animation-range: contain 4.13% contain 36.36%; }
    :where(html:not(.v2)) .dev .m-first .lc-media > *, :where(html:not(.v2)) .dev .m-first .lc-info { animation: land linear both; animation-timeline: --cloud; animation-range: contain 15.7% contain 19.83%; }
    :where(html:not(.v2)) .story-cap { animation: cap linear both; animation-timeline: --cloud; animation-range: contain 18.18% contain 30.58%; }
    :where(html:not(.v2)) .app-text { animation: m-show linear both; animation-timeline: --cloud; animation-range: contain 30.58% contain 35.54%; }
  }
}
/* Без поддержки или с «уменьшить движение» — сразу готовая карточка */
@supports not (animation-timeline: view()) { .post, .story-cap { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .post, .story-cap { display: none; }
}
@keyframes leave { from { opacity: 1; transform: translate(-50%, -50%); } to { opacity: 0; transform: translate(-50%, -62%) scale(.96); } }
@keyframes gather {
  0% { transform: translate(calc(-50% + var(--x)), calc(-50% + var(--ty))) rotate(var(--r)) scale(var(--k, 1)); opacity: 1; }
  80% { opacity: 1; }
  100% { transform: translate(-50%, calc(-50% + var(--gy))) rotate(0deg) scale(1.25); opacity: 0; }
}
/* телефон поднимается снизу к центру, пока посты летят в него; потом уезжает вправо — слева текст */
@keyframes phone {
  0% { transform: translate(-50%, calc(-50% + var(--py) + 100vh)) scale(.92); }
  27%, 80% { transform: translate(-50%, calc(-50% + var(--py) * var(--shift))) scale(1); }
  100% { transform: translate(calc(-50% + var(--px) * var(--shift)), calc(-50% + var(--py) * var(--shift))) scale(1); }
}
@keyframes land { from { opacity: 0; transform: scale(.94); } to { opacity: 1; transform: none; } }
@keyframes cap { 0% { opacity: 0; transform: translateY(14px); } 30%, 75% { opacity: 1; transform: none; } 100% { opacity: 0; } }

@media (max-width: 760px) {
  .o-photo img { border-radius: 14px; }
  .o-price { font-size: 17px; }
  .o-card { font-size: 13px; }
  .o-ev { font-size: 12px; padding: 7px 8px; gap: 6px; margin-top: 6px; }
  .o-ev svg { width: 13px; height: 13px; }
  .faq summary { font-size: 18px; padding: 20px 0; }
}

/* ---------- QR в углу экрана (только компьютер, как у Klarna) ----------
   Маленький серый квадрат с QR, под ним «На телефоне», «Закрыть». Появляется после первой сцены (в ней справа телефон —
   карточка его закрывала); у финала сама разворачивается в серый блок (landing.js), назад — сворачивается в угол.
   «Закрыть» прячет до перезагрузки. Экран уже 1200 px — карточки нет, QR только в финале */
.qr-float { display: none; }
/* с 1200 px: уже — карточка ложилась бы на блоки страницы (по бокам меньше её ширины); там QR — только в финале */
@media (min-width: 1200px) and (hover: hover) and (pointer: fine) {
  /* правая колонка вопросов не уходит под карточку */
  .faq { max-width: min(1180px, calc(100vw - 360px)); }
  .qr-float {
    display: block; position: fixed; right: 24px; bottom: 24px; z-index: 49; transform-origin: 0 0;
    opacity: 0; visibility: hidden; translate: 0 24px; transition: opacity .3s ease, translate .35s cubic-bezier(.2,.7,.2,1), visibility 0s linear .35s;
  }
  .qr-float.on { opacity: 1; visibility: visible; translate: 0 0; transition-delay: 0s; }
  .qr-float.landed { opacity: 0; visibility: hidden; transition: none; }
  .qr-mini {
    /* ровный квадрат: только QR, поля одинаковые со всех сторон, углы — тоже (разворачивается в блок финала) */
    display: block; padding: 16px; border-radius: 28px;
    background: var(--plate); box-shadow: 0 0 0 1px rgba(0,0,0,.04), 0 16px 36px -14px rgba(0,0,0,.3);
  }
  .qr-mini img { display: block; width: 96px; height: 96px; }
  /* подпись — под квадратом (внутри он перестал бы быть ровным), как «Откройте на телефоне» под QR в финале */
  .qr-float .qr-title {
    display: block; width: max-content; margin: 10px auto 0; padding: 6px 12px; border-radius: 999px;
    font-size: 13px; line-height: 1; font-weight: 800; letter-spacing: -0.02em; color: var(--ink);
    background: var(--plate); box-shadow: 0 0 0 1px rgba(0,0,0,.04), 0 8px 20px -10px rgba(0,0,0,.3);
  }
  /* крестик — кружок у верхнего правого угла карточки */
  .qr-close {
    position: absolute; top: -9px; right: -9px; width: 26px; height: 26px; padding: 0; border: 0; border-radius: 50%;
    display: flex; align-items: center; justify-content: center; background: #fff; color: var(--hint); cursor: pointer;
    box-shadow: 0 0 0 1px rgba(0,0,0,.08), 0 4px 10px rgba(0,0,0,.12); transition: color .2s ease;
  }
  .qr-close:hover { color: var(--ink); }
  .qr-close:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
  /* пока карточка в углу — блока финала нет: она в него развернётся; потом проявляется его текст */
  .final-box.in-float { visibility: hidden; }
  .final-box .final-main { transition: opacity .45s ease .05s; }
  .final-box.in-float .final-main { opacity: 0; transition: none; }
}
/* «призрак» на время разворота: серый фон и QR, размеры и место меняет landing.js */
.qr-ghost { position: fixed; z-index: 48; background: var(--plate); pointer-events: none; box-shadow: 0 16px 36px -14px rgba(0,0,0,.28); }
.qr-ghost-img { position: fixed; z-index: 48; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .qr-float { transition: none; } }

/* ---------- Кнопка внизу экрана ---------- */
.dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; display: flex; justify-content: center;
  padding: 0 16px calc(16px + env(safe-area-inset-bottom)); pointer-events: none;
  transform: translateY(130%); opacity: 0; visibility: hidden;
  transition: transform .35s cubic-bezier(.2,.7,.2,1), opacity .25s ease, visibility 0s linear .35s;
}
.dock.on { transform: none; opacity: 1; visibility: visible; transition-delay: 0s; }
/* Кнопка внизу (btn-md): у блока финала уходит — там своя кнопка (телефон) или QR (компьютер) */
.btn-md { height: 48px; padding: 0 22px; gap: 8px; font-size: 16px; }
.btn-md svg { width: 18px; height: 18px; }
.dock .btn { pointer-events: auto; box-shadow: 0 0 0 1px rgba(0,0,0,.04), 0 10px 26px -10px rgba(0,0,0,.4); }
@media (prefers-reduced-motion: reduce) { .dock { transition: none; } }

/* ---------- 2. Mini App в телефоне ----------
   Экран собран в «точках» iPhone (390×844) и уменьшен целиком (--ps): пропорции те же, что в webapp/.
   Классы внутри — с m-, чтобы не пересекаться со стилями лендинга. */
.app-text {
  position: absolute; z-index: 3; left: max(40px, calc(50% - 520px)); top: 50%; width: min(520px, calc(50% - 80px));
  transform: translateY(-50%); display: flex; flex-direction: column; gap: 40px; opacity: 0;
  transition: filter .35s ease;
}
/* opacity занята анимацией прокрутки — прячем фильтром, его можно плавно */
.stage.live .app-text { filter: opacity(0); pointer-events: none; }
/* растворённые заголовок, посты и подпись остаются на месте поверх телефона — клики должны проходить сквозь них */
.post, .story-cap { pointer-events: none; }
.stage.live .hero { pointer-events: none; }
.app-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.st { display: flex; flex-direction: column; gap: 4px; padding: 14px 0 14px 22px; border-left: 2px solid var(--ink); }
.st b { font-size: 22px; letter-spacing: -0.02em; }
.st span { font-size: 17px; color: var(--hint); }

.phone {
  position: absolute; z-index: 1; left: 50%; top: 50%; transform: translate(-50%, calc(-50% + var(--py))); will-change: transform;
  padding: calc(12px * var(--ps)); border-radius: calc(60px * var(--ps)); background: #0b0b0b;
  box-shadow: inset 0 0 0 calc(2px * var(--ps)) #3a3a3c, 0 0 0 calc(2.5px * var(--ps)) #7c7d82, 0 0 0 calc(3.5px * var(--ps)) #2c2c2e,
    0 50px 90px -40px rgba(0,0,0,.45), 0 20px 40px -24px rgba(0,0,0,.3);
}
/* кнопки, как у .lphone: справа — питание, слева — действие и громкость (одна полоска и её тени) */
.phone::before, .phone::after { content: ""; position: absolute; width: calc(4px * var(--ps)); border-radius: 2px; background: #6e6f74; }
.phone::before { right: calc(-6px * var(--ps)); top: calc(250px * var(--ps)); height: calc(100px * var(--ps)); }
.phone::after {
  left: calc(-6px * var(--ps)); top: calc(160px * var(--ps)); height: calc(34px * var(--ps));
  box-shadow: 0 calc(66px * var(--ps)) 0 0 #6e6f74, 0 calc(140px * var(--ps)) 0 0 #6e6f74;
}
/* Скругление экрана — маской на отдельном слое: обрезка через overflow/clip-path на мгновение
   отпускала углы, когда внутри начиналась анимация (сворачивание панелей) — экран «мигал» за рамкой */
.phone-screen {
  position: relative; width: calc(390px * var(--ps)); height: calc(844px * var(--ps));
  border-radius: calc(48px * var(--ps)); overflow: hidden; isolation: isolate; background: #fff;
  transform: translateZ(0); will-change: transform;
  -webkit-mask-image: -webkit-radial-gradient(white, black); mask-image: radial-gradient(white, black);
}
/* Экран — разметка и стили самого Mini App (landing/miniapp.css и miniapp-i18n.js собирает
   scripts/landing_miniapp.mjs), полная графика, как на iPhone. Здесь — только размер экрана, отступы
   Telegram в полноэкранном режиме и то, что нужно сцене. */
.dev {
  --tg-safe-area-inset-top: 50px; --tg-content-safe-area-inset-top: 42px; --tg-safe-area-inset-bottom: 34px;
  position: absolute; left: 0; top: 0; width: 390px; height: 844px; overflow: hidden;
  transform: scale(var(--ps)); transform-origin: 0 0; text-align: left; letter-spacing: normal;
}
/* общие правила лендинга для заголовков не должны менять экран приложения */
.dev h2, .dev h3 { line-height: inherit; letter-spacing: normal; text-wrap: wrap; }
/* заголовки экранов в телефоне — абзацы, не h1–h3: у страницы для поисковиков один h1 и свои h2. Вид — как у
   .dev .fsheet-head h2, .dev .fsheet-body h3, .dev .set-group h3 в miniapp.css */
.dev .fsheet-head .fsheet-title { text-align: center; font-size: 17px; font-weight: 700; }
.dev .fsheet-body .fsheet-h { font-size: 17px; font-weight: 700; }
.dev .set-group .set-h { margin: 0 4px 8px; font-size: 13px; font-weight: 600; color: var(--hint); }
/* облегчённая графика (палец вместо мыши, landing.js) — карточки ленты рисуются все: лента в сцене двигается
   анимацией, «ленивые» карточки появлялись бы с опозданием */
.dev.lite .lc:not(.compact) { content-visibility: visible; contain-intrinsic-size: none; }
/* шапка и низ шторки фильтров лежат поверх прокручиваемого списка: со стеклом Safari рисовал их своим слоем, без
   него список на iPhone оказывался поверх них (кнопки цены на «Показать», пустая шапка — 14.10). Свой слой —
   и без размытия */
.dev.lite .fsheet-head, .dev.lite .fsheet-foot { transform: translateZ(0); }
.dev .lc { content-visibility: visible; contain-intrinsic-size: none; }
.dev input { pointer-events: none; }
/* Сворачивание панелей в круги (chrome-mini): форму даёт clip-path, а размытие стекла (backdrop-filter) Chrome
   обрезает по нему без скругления — вокруг кругов проступали квадраты. Свёрнутые круги — без размытия, почти
   непрозрачные (на глаз то же стекло); размытие возвращается, когда панель развернулась целиком (.42 с) */
.dev .tabbar {
  transition: clip-path .42s cubic-bezier(.3, 1.1, .45, 1), background-color .2s ease,
    -webkit-backdrop-filter 0s linear .42s, backdrop-filter 0s linear .42s;
}
.dev .view-toggle {
  transition: transform .42s cubic-bezier(.3, 1.1, .45, 1), clip-path .42s cubic-bezier(.3, 1.1, .45, 1), background-color .2s ease,
    -webkit-backdrop-filter 0s linear .42s, backdrop-filter 0s linear .42s;
}
.dev.chrome-mini .tabbar, .dev.chrome-mini .view-toggle {
  -webkit-backdrop-filter: none; backdrop-filter: none; background-color: color-mix(in srgb, var(--bg) 90%, transparent);
}
.dev.chrome-mini .tabbar { transition: clip-path .42s cubic-bezier(.3, 1.1, .45, 1), background-color .2s ease; }
.dev.chrome-mini .view-toggle { transition: transform .42s cubic-bezier(.3, 1.1, .45, 1), clip-path .42s cubic-bezier(.3, 1.1, .45, 1), background-color .2s ease; }
.dev .sheet-backdrop { opacity: 0; animation: none; }
.dev .fsheet { transform: translateY(105%); animation: none; }
/* шторка фильтров — до статус-бара (решение владельца); кнопки Telegram на это время прячутся,
   иначе легли бы на крестик и «Сбросить» */
.dev .fsheet { height: calc(100% - 58px); }
/* верх шторки скруглён: шапка с размытием (backdrop-filter) рисуется своим слоем и обрезку скругления
   родителя не слушается — скругляем и её */
.dev .fsheet-head { border-radius: var(--r-l) var(--r-l) 0 0; }
.dev .fsheet-body { overflow: visible; }
/* «Фильтры» по центру шторки: в приложении колонки 40px | 1fr | auto, и «Сбросить» шире крестика —
   заголовок съезжает влево. Здесь колонки равные; в Mini App поправить так же (webapp/src/styles.css) */
.dev .fsheet-head { grid-template-columns: 1fr auto 1fr; }
.dev .fsheet-head .icon-round { justify-self: start; }
.dev .fsheet-head .text-btn { justify-self: end; }
.m-maplayer { position: absolute; inset: 0; z-index: 60; opacity: 0; visibility: hidden; }
/* карта — подложка лендинга (как в блоке ниже), ценники и карточка — самого приложения */
/* карта в телефоне: подложка с ценами — один слой .m-pan, его сдвигают (landing.js) */
.dev { pointer-events: none; }
.dev .m-viewport { overflow: hidden; touch-action: pan-y; }
/* нажимаемая карта: палец тянет карту, а не страницу (фидбэк 14.10 с телефона) */
.dev.m-interactive .m-viewport { touch-action: none; }
/* карточка, в которую собираются посты: без сердечка — оно появлялось вместе с фото и пропадало (14.10).
   У карточки в нажимаемом прототипе (landing.js, storyCard) сердечко своё и работает */
.dev .m-first .fav { display: none; }
.dev.m-interactive .m-viewport { cursor: grab; }
.dev.m-interactive .m-viewport.dragging { cursor: grabbing; }
.dev .m-pan { position: absolute; left: 0; top: 0; }
.dev .m-mapimg { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; user-select: none; -webkit-user-drag: none; }
.dev .m-pins { position: absolute; inset: 0; }
.dev .m-pins.has-live .m-decor { display: none; } /* живые цены пришли — нарисованные не нужны */
.dev .m-pinpos { position: absolute; }
.dev .m-pinpos.is-sel { z-index: 2; }
/* как .pin в приложении: ниже рынка — тёмная обводка, выше — оранжевая цена (тон — как _tone на сервере, ±5%) */
.dev .m-pin.good { border-color: #222222; }
.dev .m-pin.high { color: var(--high); }
.dev .m-pin.is-sel { background: #222222; color: #ffffff; transform: translate(-50%, -50%) scale(1.08); }
.dev .map-card.m-off { visibility: hidden; }
/* «Где я» — как в приложении: пока открыта карточка, кнопки нет (MapViewGL.tsx, sel === null); в показе гаснет, когда
   появляется карточка, на живой карте — по выбранной цене (landing.js, renderCard) */
@keyframes m-off-l { to { opacity: 0; visibility: hidden; } }
.dev.m-interactive .map-locate { animation: none; }
.dev .map-locate[hidden] { display: none; }

/* ---------- Прототип: в конце сцены экран в телефоне можно нажимать (класс m-interactive, landing.js) ----------
   Анимации прокрутки внутри экрана выключаются, состояние — классами: m-list (лента вместо карты), m-sheet
   (шторка фильтров), data-screen (вкладка). Экраны «Избранное», «Подписки», «Настройки» — разметка приложения */
.dev .m-screen { position: absolute; inset: 0; z-index: 5; display: none; overflow-y: auto; background: var(--bg); }
.dev[data-screen="favorites"] .m-screen[data-screen="favorites"],
.dev[data-screen="subs"] .m-screen[data-screen="subs"],
.dev[data-screen="settings"] .m-screen[data-screen="settings"] { display: block; }
.dev.m-interactive { pointer-events: auto; }
.dev.m-interactive button, .dev.m-interactive .lc, .dev.m-interactive .map-card { cursor: pointer; }
/* z-index: свой слой — шапка и «Карта» ленты не вылезают поверх других вкладок */
.dev.m-interactive .m-app { position: absolute; inset: 0; z-index: 0; overflow-y: auto; }
.dev.m-interactive .m-app .feed { animation: none; transform: none; }
.dev.m-interactive .m-maplayer { animation: none; opacity: 1; visibility: visible; }
.dev.m-interactive.m-list .m-maplayer,
.dev.m-interactive:not([data-screen="search"]) .m-maplayer { visibility: hidden; }
.dev.m-interactive .m-pinpos { animation: none; opacity: 1; transform: none; }
.dev.lite.m-interactive .m-pins, .dev.m-interactive .m-pins { animation: none; opacity: 1; transform: none; }
.dev.m-interactive .m-pin.m-pin-on { animation: none; }
.dev.m-interactive .map-card { animation: none; opacity: 1; transform: none; }
/* с карты в список не переходим (решение владельца) — кнопки «Список» на карте нет */
.dev .m-maplayer .m-to-list { display: none; }
/* z-index 65: шторку открывают и с карты — она должна лечь поверх слоя карты (60), под Telegram (70) */
.dev.m-interactive .sheet-backdrop { z-index: 65; animation: none; opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .2s ease, visibility 0s linear .28s; }
/* Аренда / Продажа (m-sale): у продажи своя цена в шторке, без «Срока аренды» */
.dev.m-sale .m-rent-only, .dev:not(.m-sale) .m-sale-only { display: none; }
.dev.m-interactive .fsheet { animation: none; transform: translateY(105%); transition: transform .28s cubic-bezier(.2,.9,.3,1); }
.dev.m-interactive.m-sheet .sheet-backdrop { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .2s ease; }
.dev.m-interactive.m-sheet .fsheet { transform: none; }
.dev.m-interactive .fsheet-body { animation: none; transform: none; overflow-y: auto; }
.dev.m-interactive .fchip, .dev.m-interactive .room, .dev.m-interactive .seg { animation: none; }
/* кнопки, которые «нажимала» прокрутка: у их анимации та же сила селектора, и она ниже в файле */
.dev.m-interactive .room.r-any, .dev.m-interactive .room.r2, .dev.m-interactive .fchip.c1,
.dev.m-interactive .fchip.c2, .dev.m-interactive .seg.o-all, .dev.m-interactive .seg.o-no { animation: none; }
.dev.m-interactive .m-tg { animation: none; opacity: 1; transition: opacity .2s ease; }
.dev.m-interactive.m-sheet .m-tg { opacity: 0; }
/* Палец-подсказка (landing.js demoStart, тест 13.10): подлетает снизу справа, нажимает цену (расходится круг), прижатым
   тянет карту, уходит. Кончик пальца — в точке цены (svg 24×24, кончик ≈ (8, 2)) */
.dev .m-hand {
  position: absolute; z-index: 5; width: 40px; height: 40px; margin: -4px 0 0 -13px; pointer-events: none;
  opacity: 0; filter: drop-shadow(0 6px 10px rgba(0, 0, 0, .28));
}
.dev .m-hand svg { display: block; width: 100%; height: 100%; }
.dev .m-hand-ring {
  position: absolute; left: 13px; top: 4px; width: 40px; height: 40px; margin: -20px 0 0 -20px; border-radius: 50%;
  border: 2px solid rgba(17, 17, 17, .5); opacity: 0;
}
.dev .m-hand.tap { animation: m-hand-tap 1.6s cubic-bezier(.3, .7, .3, 1) both; }
.dev .m-hand.tap .m-hand-ring { animation: m-hand-ring 1.6s ease-out both; }
.dev .m-hand.drag { animation: none; opacity: 1; transform: scale(.88); transition: transform .15s ease; }
.dev .m-hand.out { opacity: 0; transform: translate(14px, 18px) scale(1.04); transition: opacity .45s ease, transform .45s ease; }
@keyframes m-hand-tap {
  0% { opacity: 0; transform: translate(44px, 56px) rotate(-8deg); }
  45% { opacity: 1; transform: none; }
  58% { transform: scale(.86); }
  70%, 100% { opacity: 1; transform: none; }
}
@keyframes m-hand-ring { 0%, 56% { opacity: 0; transform: scale(.5); } 60% { opacity: .9; } 100% { opacity: 0; transform: scale(2.2); } }
@media (prefers-reduced-motion: reduce) { .dev .m-hand.tap, .dev .m-hand.tap .m-hand-ring { animation: none; opacity: 1; } .dev .m-hand.tap .m-hand-ring { opacity: 0; } }
.dev .m-pin {
  border: 1.5px solid transparent; font-family: inherit;
  position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); display: flex; align-items: center;
  height: 26px; padding: 0 9px; border-radius: 999px; background: #fff; color: #222;
  font-size: 12.5px; font-weight: 700; line-height: 1; letter-spacing: -0.01em; white-space: nowrap;
  box-shadow: 0 0 0 1px rgba(0,0,0,.08), 0 2px 6px rgba(0,0,0,.14);
}
.dev .map-card { opacity: 0; animation: none; }
.m-attr { position: absolute; z-index: 5; right: 8px; top: 150px; padding: 1px 4px; border-radius: 4px; font-size: 9px; color: var(--hint); background: rgba(255,255,255,.7); }

/* статус-бар iPhone и кнопки Telegram в полноэкранном режиме */
/* Статус-бар как на iPhone с островом: время — по центру левого «уха», сеть / Wi-Fi / батарея — по центру
   правого, всё на одной линии с серединой острова (y = 29,5) */
.m-status { position: absolute; z-index: 70; left: 0; right: 0; top: 0; height: 54px; color: #000; pointer-events: none; }
.m-island { position: absolute; left: 50%; top: 11px; width: 126px; height: 37px; margin-left: -63px; border-radius: 18.5px; background: #000; }
.m-time {
  position: absolute; left: 0; width: 132px; top: 18.5px; text-align: center;
  font: 600 17px/22px -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif; letter-spacing: -0.4px;
}
.m-sys { position: absolute; left: 258px; width: 132px; top: 23px; display: flex; align-items: center; justify-content: center; gap: 6px; height: 13px; }
.m-ic { display: block; fill: currentColor; }
.m-tg { position: absolute; z-index: 70; left: 14px; right: 14px; top: 56px; display: flex; justify-content: space-between; }
/* кнопки Telegram в полноэкранном режиме — только значки, кружками (решение владельца: минимализм) */
.m-tg-btn { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; background: #ececee; color: #0f0f10; }
.m-home { position: absolute; z-index: 70; left: 50%; bottom: 8px; width: 134px; height: 5px; margin-left: -67px; border-radius: 3px; background: #0f0f10; }

@media (max-width: 760px) {
  /* --pt — верх телефона: под заголовком и шагами */
  .stage { --sh: clamp(480px, 100vh, 900px); --ps: var(--ps-m, .72); --px: 0px; --pt: var(--pt-m, 184px); --py: calc(var(--pt) + 433px * var(--ps) - var(--sh) / 2); }
  @supports (height: 100svh) {
    .stage { --sh: clamp(480px, 100svh, 900px); }
  }
  .app-text { left: 16px; right: 16px; top: 28px; width: auto; transform: none; gap: 10px; text-align: center; }
  .story-cap { top: 40px; font-size: 26px; }
  .app-text h2 { font-size: 30px; }
  /* шаги — переключателем под телефоном (.st-bar); здесь — только для экранного диктора */
  .app-steps { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
}
@media (max-width: 760px) and (max-height: 860px) { .stage { --ps: var(--ps-m, .66); } }
@media (max-width: 760px) and (max-height: 800px) { .stage { --ps: var(--ps-m, .6); } }
@media (max-width: 760px) and (max-height: 740px) { .stage { --ps: var(--ps-m, .54); } }
/* экран блокировки: над телефоном — заголовок, подзаголовок и счётчик; телефон ниже и меньше (landing.js) */
@media (max-width: 760px) { .stage.lock { --ps: var(--ps-l, var(--ps-m, .6)); --pt: var(--pt-l, var(--pt-m, 184px)); } }
@media (max-width: 760px) and (max-height: 700px) {
  .stage { --ps: var(--ps-m, .5); }
  .stage.lock { --ps: var(--ps-l, var(--ps-m, .5)); }
  /* низкий экран (iPhone SE, Safari с панелями): текст над телефоном плотнее — телефону больше места */
  .app-text { top: 16px; gap: 8px; }
  .app-text h2 { font-size: 25px; }
  .story-cap { top: 24px; font-size: 22px; }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    :where(html:not(.v2)) .dev .m-app .feed { animation: m-scroll linear both; animation-timeline: --cloud; animation-range: contain 35.04% contain 47.93%; }
    /* все три шага — на одном участке до самого конца сцены: после конца анимации Safari терял значение
       прозрачности, заданное через var(), и пройденный шаг пропадал совсем; значения — только числами */
    :where(html:not(.v2)) .st { animation-timeline: --cloud; animation-range: contain 33.06% contain 100%; animation-timing-function: linear; animation-fill-mode: both; }
    :where(html:not(.v2)) .st1 { animation-name: st-first; } :where(html:not(.v2)) .st2 { animation-name: st-mid; } :where(html:not(.v2)) .st3 { animation-name: st-last; }
    /* эпизод с фильтрами — медленнее (было 680 px на всё): у каждого нажатия ~100 px, между ними паузы */
    :where(html:not(.v2)) .dev .sheet-backdrop { animation: m-fade linear both; animation-timeline: --cloud; animation-range: contain 48.93% contain 82.64%; }
    :where(html:not(.v2)) .dev .fsheet { animation: m-sheet linear both; animation-timeline: --cloud; animation-range: contain 48.93% contain 82.64%; }
    :where(html:not(.v2)) .m-tg { animation: m-hide linear both; animation-timeline: --cloud; animation-range: contain 48.93% contain 82.64%; }
    :where(html:not(.v2)) .dev .room.r-any { animation: m-off linear both; animation-timeline: --cloud; animation-range: contain 54.55% contain 56.2%; }
    :where(html:not(.v2)) .dev .room.r2 { animation: m-on linear both; animation-timeline: --cloud; animation-range: contain 54.55% contain 56.2%; }
    :where(html:not(.v2)) .dev .fsheet-body { animation: m-sheet-scroll linear both; animation-timeline: --cloud; animation-range: contain 58.68% contain 64.46%; }
    :where(html:not(.v2)) .dev .fchip.c1 { animation: m-on linear both; animation-timeline: --cloud; animation-range: contain 66.94% contain 68.6%; }
    :where(html:not(.v2)) .dev .fchip.c2 { animation: m-on linear both; animation-timeline: --cloud; animation-range: contain 71.07% contain 72.73%; }
    :where(html:not(.v2)) .dev .seg.o-all { animation: m-seg-off linear both; animation-timeline: --cloud; animation-range: contain 75.21% contain 76.86%; }
    :where(html:not(.v2)) .dev .seg.o-no { animation: m-seg-on linear both; animation-timeline: --cloud; animation-range: contain 75.21% contain 76.86%; }
    :where(html:not(.v2)) .m-maplayer { animation: m-show linear both; animation-timeline: --cloud; animation-range: contain 81.65% contain 84.13%; }
    :where(html:not(.v2)) .dev .m-pinpos { animation: m-pin linear both; animation-timeline: --cloud; animation-range: contain calc(83.14% + var(--i) * 0.289%) contain calc(84.13% + var(--i) * 0.289%); }
    /* палец: ценники появляются все вместе, одной анимацией слоя, а не 12 своими */
    :where(html:not(.v2)) .dev.lite .m-pinpos { animation: none; }
    :where(html:not(.v2)) .dev.lite .m-pins { animation: m-pin linear both; animation-timeline: --cloud; animation-range: contain 83.14% contain 86.6%; }
    :where(html:not(.v2)) .dev .m-pin.m-pin-on { animation: m-pin-on linear both; animation-timeline: --cloud; animation-range: contain 87.6% contain 88.84%; }
    :where(html:not(.v2)) .dev .map-card { animation: m-card linear both; animation-timeline: --cloud; animation-range: contain 88.43% contain 90.91%; }
    :where(html:not(.v2)) .dev .map-locate { animation: m-off-l linear both; animation-timeline: --cloud; animation-range: contain 88.43% contain 90.91%; }
  }
}
@supports not (animation-timeline: view()) {
  .dev .sheet-backdrop, .m-maplayer { display: none; }
  .story { height: auto; }
  .stage { position: relative; height: auto; display: flex; flex-direction: column; align-items: center; gap: 48px; padding: 140px 16px 96px; }
  .hero, .app-text, .phone { position: relative; left: auto; top: auto; right: auto; transform: none; opacity: 1; }
  .app-text { width: min(440px, 100%); }
}
@media (prefers-reduced-motion: reduce) {
  .dev .sheet-backdrop, .m-maplayer { display: none; }
  .story { height: auto; }
  .stage { position: relative; height: auto; display: flex; flex-direction: column; align-items: center; gap: 48px; padding: 140px 16px 96px; }
  .hero, .app-text, .phone { position: relative; left: auto; top: auto; right: auto; transform: none; opacity: 1; }
  .app-text { width: min(440px, 100%); }
}
/* Низкий широкий экран — телефон в горизонтальной ориентации, низкое окно: сцена и переписка по высоте
   экрана, а не минимум 640 / 700 px (иначе кнопка первого экрана и низ телефона — за краем); масштаб
   телефона считает landing.js (fitScene); подпись «Семь постов» здесь легла бы на телефон — без неё */
@media (min-width: 761px) and (max-height: 639px) {
  .stage { --sh: max(320px, 100vh); --ps: var(--ps-m, .4); }
  @supports (height: 100svh) {
    .stage { --sh: max(320px, 100svh); }
  }
  .hero { gap: 14px; }
  .hero .hero-title { font-size: clamp(32px, 11vh, 80px); }
  .hero .hero-kicker { font-size: 13px; margin-bottom: -4px; }
  .story-cap, .p3, .p4, .p7 { display: none; } /* боковые посты легли бы на заголовок */
  .p1 { --x: -40vw; --y: -.33; --w: 120px; } .p2 { --x: 40vw; --y: -.14; --w: 116px; } /* p2 — ниже кнопки языка */
  .p5 { --x: -36vw; --y: .33; --w: 120px; } .p6 { --x: 36vw; --y: .34; --w: 120px; }
  .post p { font-size: 11px; }
  .app-text { gap: 16px; }
  .app-text h2 { font-size: clamp(26px, 8vh, 56px); }
  .st { padding: 6px 0 6px 18px; }
  .st b { font-size: 18px; }
  .st span { font-size: 15px; }
}
@keyframes m-scroll { to { transform: translateY(-780px); } }
@keyframes st-first { 0%, 22.96% { opacity: 1; } 26.67%, 100% { opacity: .3; } }
@keyframes st-mid { 0%, 22.22% { opacity: .3; } 25.93%, 71.11% { opacity: 1; } 74.81%, 100% { opacity: .3; } }
@keyframes st-last { 0%, 70.37% { opacity: .3; } 74.81%, 100% { opacity: 1; } }

/* ---------- Шаги сцены на узком экране — переключатель под телефоном (решение владельца 13.10) ----------
   «Лента · Фильтры · Карта»: активный — белый, полоска внизу — сколько пройдено; вверху — только заголовок */
.st-bar { display: none; }
@media (max-width: 760px) {
  .st-bar { display: flex; }
  @supports not (animation-timeline: view()) { .st-bar { display: none; } }
  @media (prefers-reduced-motion: reduce) { .st-bar { display: none; } }
}
.st-bar {
  position: absolute; z-index: 3; left: 16px; right: 16px; bottom: calc(14px + env(safe-area-inset-bottom));
  justify-content: center; opacity: 0; pointer-events: none; transition: filter .35s ease;
}
.sb-seg { position: relative; display: flex; padding: 4px 4px 7px; border-radius: 22px; background: #1c1c1e; box-shadow: 0 0 0 1px rgba(255,255,255,.08); }
.sb { position: relative; height: 34px; padding: 0 16px; display: flex; align-items: center; border-radius: 999px; font-size: 15px; font-weight: 600; letter-spacing: -0.01em; color: #a1a1a6; }
/* выбранный шаг — светлая копия подписи поверх (текст — data-label, landing.js), меняется только прозрачность:
   перекраска фона и текста шла на каждом кадре прокрутки и на iPhone роняла кадры (15.10) */
.sb::after {
  content: attr(data-label); position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  border-radius: inherit; background: #f5f5f7; color: #0f0f10; opacity: 0; will-change: opacity;
}
@media (max-width: 380px) { .sb { padding: 0 14px; } }
/* полоска пройденного — тонкая линия под подписями */
.sb-prog { position: absolute; left: 18px; right: 18px; bottom: 2px; height: 2px; border-radius: 1px; background: #f5f5f7; transform-origin: 0 50%; transform: scaleX(0); }
.stage.live .st-bar, .stage.lock .st-bar { filter: opacity(0); }
/* «Листайте дальше ↓» под телефоном, пока карта нажимаемая: телефон на весь экран казался концом страницы.
   Место под ней оставляет fitPhone (landing.js) */
.scroll-cue {
  position: absolute; z-index: 3; left: 50%; bottom: calc(14px + env(safe-area-inset-bottom)); display: flex; align-items: center; gap: 6px;
  font: inherit; font-size: 15px; line-height: 20px; font-weight: 600; color: var(--hint); white-space: nowrap; pointer-events: none;
  padding: 8px 12px; margin-bottom: -8px; border: 0; border-radius: 999px; background: none; cursor: pointer;
  opacity: 0; visibility: hidden; transform: translate(-50%, 8px); transition: opacity .3s ease, transform .3s ease, visibility 0s linear .3s;
}
.stage.live .scroll-cue { opacity: 1; visibility: visible; transform: translate(-50%, 0); transition: opacity .45s ease .35s, transform .45s ease .35s; pointer-events: auto; }
/* на телефоне карта в прототипе тянется пальцем (страница под ней не листается) — «Листайте дальше» нажимается
   и перелистывает к экрану блокировки (landing.js) */
.scroll-cue:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.scroll-cue svg { animation: cue-bob 1.6s ease-in-out infinite; }
/* «Попробуйте сами» (тест 13.10): широкий экран — слева от телефона со стрелкой к нему; уже 1100 px — строкой над
   телефоном (место над ним оставляет fitPhone, как под ним для «Листайте дальше»). Только пока карта нажимаемая */
.live-hint {
  position: absolute; z-index: 3; left: 16px; right: 16px; top: calc(14px + env(safe-area-inset-top)); text-align: center;
  font-size: 15px; line-height: 20px; font-weight: 600; color: var(--ink); pointer-events: none;
  opacity: 0; visibility: hidden; transform: translateY(-8px); transition: opacity .3s ease, transform .3s ease, visibility 0s linear .3s;
}
.live-hint .lh-h, .live-hint .lh-long, .live-hint .lh-arrow { display: none; }
.stage.live .live-hint { opacity: 1; visibility: visible; transform: none; transition: opacity .5s ease .45s, transform .5s ease .45s; }
@media (min-width: 1100px) {
  .live-hint {
    left: auto; right: calc(50% + 207px * var(--ps) + 56px); top: 50%; width: 300px; text-align: left;
    display: flex; flex-direction: column; align-items: flex-start; gap: 12px; transform: translate(-12px, -50%);
  }
  .stage.live .live-hint { transform: translate(0, -50%); }
  .live-hint .lh-short { display: none; }
  .live-hint .lh-h { display: block; font-size: 32px; line-height: 1.1; font-weight: 800; letter-spacing: -0.035em; }
  .live-hint .lh-long { display: block; font-size: 17px; line-height: 1.45; font-weight: 500; color: var(--hint); text-wrap: pretty; }
  .live-hint .lh-arrow { display: block; align-self: flex-end; margin-top: 8px; color: var(--ink); animation: lh-nudge 1.6s ease-in-out infinite; }
}
@keyframes lh-nudge { 0%, 100% { transform: none; } 50% { transform: translateX(6px); } }
@media (prefers-reduced-motion: reduce) { .live-hint .lh-arrow { animation: none; } }
@keyframes cue-bob { 0%, 100% { transform: none; } 50% { transform: translateY(4px); } }
@media (prefers-reduced-motion: reduce) { .scroll-cue svg { animation: none; } }
@keyframes sb-first { 0%, 22.96% { opacity: 1; } 25.19%, 100% { opacity: 0; } }
@keyframes sb-mid { 0%, 23.7% { opacity: 0; } 25.93%, 71.11% { opacity: 1; } 73.33%, 100% { opacity: 0; } }
@keyframes sb-last { 0%, 72.59% { opacity: 0; } 74.81%, 100% { opacity: 1; } }
@keyframes sb-prog { to { transform: scaleX(1); } }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    :where(html:not(.v2)) .st-bar { animation: m-show linear both; animation-timeline: --cloud; animation-range: contain 30.58% contain 35.54%; }
    :where(html:not(.v2)) .sb::after { animation-timeline: --cloud; animation-range: contain 33.06% contain 100%; animation-timing-function: linear; animation-fill-mode: both; }
    :where(html:not(.v2)) .sb1::after { animation-name: sb-first; } :where(html:not(.v2)) .sb2::after { animation-name: sb-mid; } :where(html:not(.v2)) .sb3::after { animation-name: sb-last; }
    :where(html:not(.v2)) .sb-prog { animation: sb-prog linear both; animation-timeline: --cloud; animation-range: contain 33.06% contain 92%; }
  }
}
@keyframes m-fade { 0% { opacity: 0; } 7.28%, 92.72% { opacity: 1; } 100% { opacity: 0; } }
@keyframes m-hide { 0% { opacity: 1; } 5.82%, 94.18% { opacity: 0; } 100% { opacity: 1; } }
@keyframes m-sheet { 0% { transform: translateY(105%); } 8.74%, 92.24% { transform: none; } 100% { transform: translateY(105%); } }
@keyframes m-sheet-scroll { to { transform: translateY(-690px); } }
@keyframes m-on { to { background: #0f0f10; color: #ffffff; border-color: #0f0f10; } }
@keyframes m-off { to { background: transparent; color: #0f0f10; } }
@keyframes m-seg-on { to { background: #ffffff; color: #0f0f10; box-shadow: 0 1px 4px rgba(0,0,0,.12); } }
@keyframes m-seg-off { to { background: transparent; color: #8a8f98; box-shadow: none; } }
@keyframes m-show { from { opacity: 0; visibility: visible; } to { opacity: 1; visibility: visible; } }
@keyframes m-pin { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
/* выбранная цена — как на большой карте лендинга */
@keyframes m-pin-on { to { background: #222222; color: #ffffff; transform: translate(-50%, -50%) scale(1.08); } }
@keyframes m-card { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@media (max-width: 380px) { .lphone { --lps: .68; } }

/* ---------- Фаза «экран блокировки» в конце первой сцены (проба 12.10) ----------
   После прототипа тот же телефон отъезжает вправо (как на шаге «Как приложение»), гаснет до экрана блокировки, и
   при прокрутке на него приходят пуши о настоящих новых квартирах; слева — «Узнавайте первым» и счётчик. Сцена
   длиннее на 2250 px: первые 250 — пауза на нажимаемой карте (иначе после неё сразу экран блокировки), дальше
   2000 — сама фаза (LOCK_DWELL в landing.js). Анимации облака считаются по копии секции высотой 6950 px
   (.tl-cloud), поэтому их шаги не сдвигаются. Только там, где есть timeline-scope и движение не выключено; иначе — отдельный блок ниже */
@supports (timeline-scope: --a) and (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    :where(html:not(.v2)) .story { height: 9200px; }
    :where(html:not(.v2)) .tl-cloud { height: 6950px; }
    :where(html:not(.v2)) .live-story { display: none; }
  }
}
.dev .m-lock {
  position: absolute; inset: 0; z-index: 68; color: #fff; overflow: hidden; pointer-events: none;
  opacity: 0; visibility: hidden; transition: opacity .4s ease, visibility 0s linear .4s;
}
.dev.m-locked .m-lock { opacity: 1; visibility: visible; transition: opacity .4s ease; }
/* экран блокировки поверх живой карты (узкий сенсорный экран, landing.js keepLiveUnderLock): касания — странице,
   а не карте под ним; подсказки живой карты прячутся */
.dev.m-locked .m-lock { pointer-events: auto; }
/* живая карта ставит телефон в середину (--shift: 0); у экрана блокировки — своё место (под текстом, справа) */
.stage.lock { --shift: 1; }
.stage.lock .scroll-cue, .stage.lock .live-hint { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .2s ease, visibility 0s linear .2s; }
.dev.m-locked .m-status { color: #fff; }
.dev.m-locked .m-time, .dev.m-locked .m-tg { visibility: hidden; }
.dev.m-locked .m-home { background: #fff; }
.dev .m-lock a.push { pointer-events: auto; }
.lock-text {
  position: absolute; z-index: 3; left: max(40px, calc(50% - 520px)); top: 50%; width: min(520px, calc(50% - 80px));
  transform: translateY(calc(-50% + 16px)); display: flex; flex-direction: column; gap: 18px;
  opacity: 0; visibility: hidden; transition: opacity .45s ease, transform .55s cubic-bezier(.2,.7,.2,1), visibility 0s linear .45s;
}
.stage.lock .lock-text { opacity: 1; visibility: visible; transform: translateY(-50%); transition: opacity .45s ease .15s, transform .55s cubic-bezier(.2,.7,.2,1) .15s; }
.stage.lock .app-text { filter: opacity(0); }
.lock-count { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; margin-top: 18px; }
.lock-count[hidden] { display: none; }
.lock-count b { font-size: clamp(48px, 5vw, 72px); line-height: 1; font-weight: 700; letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
.lock-count > span { font-size: 17px; color: var(--hint); }
@media (max-width: 760px) {
  /* на телефоне — заголовок и подзаголовок над телефоном, счётчик одной строкой ПОД ним (владелец 13.10): блок
     текста — на всю высоту сцены, счётчик прижат к низу; место телефону между ними считает landing.js — fitScene */
  .lock-text {
    left: 16px; right: 16px; top: 28px; bottom: calc(14px + env(safe-area-inset-bottom)); width: auto; transform: translateY(16px);
    gap: 6px; text-align: center; align-items: center; pointer-events: none; /* пуши в телефоне под ним нажимаются */
  }
  .stage.lock .lock-text { transform: none; }
  .lock-text h2 { font-size: 30px; }
  .lock-text .lead { font-size: 15px; line-height: 1.4; max-width: 340px; }
  .lock-count { flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: baseline; gap: 4px 8px; margin-top: auto; }
  .lock-count b { font-size: 26px; letter-spacing: -0.02em; }
  .lock-count > span { font-size: 15px; }
}
@media (max-width: 760px) and (max-height: 700px) { .lock-text { top: 16px; } .lock-text h2 { font-size: 25px; } }


/* ---------- v2 (телефоны и планшеты, ?v=2; ?v=1 — сцена по прокрутке): сцены проигрываются сами, по времени ----------
   На iPhone анимации, привязанные к прокрутке, рисуются не чаще 60 раз в секунду при прокрутке в 120 — сцена
   отставала от пальца; сцену посередине экрана в Chrome держал скрипт, и она прыгала, когда Chrome прячет свою
   панель. Здесь к прокрутке ничего не привязано и ничего не центрируется скриптом. Первый экран — как в старой
   сцене (решение владельца 16.10): заголовок и кнопка посередине, посты вокруг (места — те же --x/--y), при открытии
   мягко прилетают. Класс v2 ставит скрипт в <head>; правила старой сцены выключены для v2 через :where(html:not(.v2)).
   Три слоя сцены, друг за другом, ничего не закреплено: посты (s-posts, над всем; листаются со страницей), первый
   экран (s-back) и «Как приложение» с телефоном (s-front, ровно в «маленький» экран --vh0 — в нём телефон на живой
   карте становится на весь экран). Закрепление (пробы 17.10) владелец отменил */
.s-posts, .s-back, .s-front { display: contents; } /* старая сцена: обёрток будто нет */
html.v2 .story { height: auto; overflow: hidden; overflow: clip; }
html.v2 .tl-proxy { display: none; }
html.v2 .stage {
  --vh0: 100svh; --pt: 160px; --g1: 24px; --g2: 20px;
  position: relative; top: auto; height: auto; overflow: visible; display: block; padding: 0 0 48px; transition: none;
}
/* блок с телефоном — в «маленький» экран (svh); когда Safari и Chrome прячут панели, экран выше — снизу проглядывал
   светлый следующий блок (17.10). Тёмный запас снизу — на эту разницу */
@supports (height: 100lvh) { html.v2 .stage { padding-bottom: calc(48px + 100lvh - var(--vh0)); } }
/* Серый блок «Узнавайте первым» наезжает на тёмный низ сцены (владелец 18.10): он поверх, со скруглёнными верхними
   углами, и заходит на тёмное на 40 px (под ним — запас); тёмный низ при этом отстаёт от страницы (landing.js, сдвиг
   .story). Свои углы тёмного низа (белые уголки) не нужны — их закрывает серый блок */
html.v2 .stage { padding-bottom: 88px; }
@supports (height: 100lvh) { html.v2 .stage { padding-bottom: calc(88px + 100lvh - var(--vh0)); } }
html.v2 .hero-dark .story::before, html.v2 .hero-dark .story::after { display: none; }
html.v2 .story { transform: translateY(0px); will-change: transform; } /* свой слой с самого начала — его сдвиг ничего не пересобирает */
html.v2 .live-story { position: relative; z-index: 6; margin-top: -40px; border-radius: 40px 40px 0 0; box-shadow: 0 -18px 40px -24px rgba(0, 0, 0, .55); }
html.v2 .s-posts { display: block; position: relative; z-index: 3; height: 0; pointer-events: none; }
html.v2 .s-back { display: flex; position: relative; z-index: 0; height: var(--sh); align-items: center; justify-content: center; padding: 0 16px; }
html.v2 .s-front { display: block; position: relative; z-index: 2; height: var(--vh0); pointer-events: none; }
html.v2 .s-front > * { pointer-events: auto; }
/* посты летят в телефон — страница стоит, пока не начнётся «Лента» (landing.js, holdScroll). Только html: с body он сам
   становится областью прокрутки */
html.v2-hold { overflow: hidden; }
/* первый экран: заголовок по центру */
html.v2 .hero { position: relative; left: auto; top: auto; transform: none; width: min(1000px, 100%); }
/* «Как приложение» — над телефоном, телефон — с --pt, переключатель шагов — под ним (места считает landing.js, v2Fit) */
html.v2 .app-text {
  position: absolute; left: 16px; right: 16px; top: auto; bottom: calc(var(--vh0) - var(--pt) + var(--g1)); width: auto; max-width: 720px;
  margin: 0 auto; transform: none; opacity: 1; text-align: center; transition: opacity .35s ease;
}
/* шаги — только для экранного диктора (на экране — переключатель под телефоном) */
html.v2 .app-steps { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
html.v2 .phone { position: absolute; left: calc(50% - 207px * var(--ps)); top: var(--pt); margin: 0; transform: none; transform-origin: 50% 0; }
html.v2 .story-cap, html.v2 .lock-text { display: none; }
/* посты первого экрана — от середины первого экрана, как в старой сцене; при открытии прилетают снизу */
html.v2 .post { display: flex; top: calc(var(--sh) / 2); opacity: 1; pointer-events: none; animation: v2-post-in .8s cubic-bezier(.2,.8,.2,1) both; }
html.v2 .p1 { animation-delay: .1s; } html.v2 .p2 { animation-delay: .17s; } html.v2 .p3 { animation-delay: .24s; }
html.v2 .p4 { animation-delay: .31s; } html.v2 .p5 { animation-delay: .38s; } html.v2 .p6 { animation-delay: .45s; } html.v2 .p7 { animation-delay: .52s; }
@keyframes v2-post-in { from { opacity: 0; translate: 0 48px; } to { opacity: 1; translate: 0 0; } }
@media (max-width: 760px) { html.v2 .p3, html.v2 .p4, html.v2 .p7 { display: none; } }
@media (min-width: 761px) and (max-height: 639px) { html.v2 .p3, html.v2 .p4, html.v2 .p7 { display: none; } }
/* посты в полёте: место и полёт задаёт landing.js */
html.v2 .post.v2-fly { display: flex; left: 0; top: 0; transform: none; translate: none; opacity: 0; filter: none; animation: none; }
html.v2 .post.v2-off { display: none; }
/* пока посты не влетели (v2-armed ставит landing.js): телефон уменьшен (--s0, от середины верха), первая карточка
   ленты пуста — в неё слетятся посты. Без скрипта — сразу обычный телефон */
html.v2-armed .phone { transform: scale(var(--s0, 1)); transform-origin: 50% 0; }
html.v2-armed .dev .m-first .lc-media > *, html.v2-armed .dev .m-first .lc-info { opacity: 0; }
@media (max-width: 760px) {
  html.v2 .post.v2-fly p { font-size: 11px; }
}
/* ---- v2: сцены в телефоне по времени (landing.js: классы шагов на .dev — v2s-feed, v2s-filters, v2s-map) ----
   Те же кадры, что в старой сцене по прокрутке, но со своей длительностью и плавностью; в конце — живая карта
   (m-interactive, классы шагов сняты) */
html.v2 .dev.v2s-feed .m-app .feed { animation: m-scroll 1.6s cubic-bezier(.25,.6,.25,1) .6s both; } /* быстрее, с разгона (17.10) */
html.v2 .dev.v2-feed-done .m-app .feed { transform: translateY(-780px); }
html.v2 .dev.v2s-filters .sheet-backdrop { animation: v2-fade 7.4s .65s both; }
html.v2 .dev.v2s-filters .fsheet { animation: v2-sheet 7.4s .65s both; }
html.v2 .dev.v2s-filters .m-tg { animation: v2-hide 7.4s .65s both; }
html.v2 .dev.v2s-filters .room.r-any { animation: m-off .25s ease 2.15s both; }
html.v2 .dev.v2s-filters .room.r2 { animation: m-on .25s ease 2.15s both; }
html.v2 .dev.v2s-filters .fsheet-body { animation: m-sheet-scroll .9s cubic-bezier(.25,.6,.25,1) 2.95s both; }
html.v2 .dev.v2s-filters .fchip.c1 { animation: m-on .25s ease 4.75s both; }
html.v2 .dev.v2s-filters .fchip.c2 { animation: m-on .25s ease 5.6s both; }
html.v2 .dev.v2s-filters .seg.o-all { animation: m-seg-off .25s ease 6.45s both; }
html.v2 .dev.v2s-filters .seg.o-no { animation: m-seg-on .25s ease 6.45s both; }
html.v2 .dev.v2s-map .m-maplayer { animation: m-show .4s ease .75s both; }
html.v2 .dev.v2s-map .m-pinpos { animation: m-pin .45s cubic-bezier(.2,.8,.2,1) both; animation-delay: calc(1.05s + var(--i) * 40ms); }
html.v2 .dev.v2s-map .m-pin.m-pin-on { animation: m-pin-on .3s ease 2.25s both; }
html.v2 .dev.v2s-map .map-card { animation: m-card .45s cubic-bezier(.2,.8,.2,1) 2.45s both; }
html.v2 .dev.v2s-map .map-locate { animation: m-off-l .3s ease 2.45s both; }
/* Касание в показе (владелец 17.10): кружок, как «показ касаний» в записи экрана iPhone, — серый с белой каймой,
   виден и на белом интерфейсе, и на фото; при нажатии сжимается. Место — сдвигом обёртки (landing.js, touch) */
html.v2 .dev .v2-touch { position: absolute; left: 0; top: 0; z-index: 95; width: 0; height: 0; pointer-events: none; }
html.v2 .dev .v2-touch i {
  position: absolute; left: -23px; top: -23px; width: 46px; height: 46px; border-radius: 50%; opacity: 0;
  background: rgba(60, 60, 67, .32); box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .9), 0 2px 10px rgba(0, 0, 0, .22);
}
/* шторка: въезжает с замедлением, стоит, уезжает с ускорением */
@keyframes v2-sheet {
  0% { transform: translateY(105%); animation-timing-function: cubic-bezier(.2,.9,.3,1); }
  8%, 92% { transform: none; animation-timing-function: cubic-bezier(.5,0,.75,0); }
  100% { transform: translateY(105%); }
}
@keyframes v2-fade { 0% { opacity: 0; } 7%, 93% { opacity: 1; } 100% { opacity: 0; } }
@keyframes v2-hide { 0% { opacity: 1; } 6%, 94% { opacity: 0; } 100% { opacity: 1; } }
/* Сердечко на фото (v2-glass): без тени-фильтра (drop-shadow) — на iPhone такой слой поверх листаемых фото
   пересобирался на ходу, и сердечки «скакали», пока лента едет (17.10; в облегчённой графике фильтра не было). Читаемость на
   светлом фото — мягкая тёмная подложка под ним (обычная заливка, не фильтр) */
/* Фото карточки в показе — не листаемая область (overflow hidden вместо auto): на iPhone листаемая область — свой
   слой прокрутки, и при сдвиге ленты он ехал не вместе с тем, что поверх него, — сердечки и точки фото «скакали»
   (17.10). На живой карте (m-interactive) фото снова листаются пальцем */
html.v2 .dev:not(.m-interactive) .strip { overflow: hidden; }
html.v2-glass .dev .fav.overlay { filter: none; }
html.v2-glass .dev .fav.overlay::before {
  content: ""; position: absolute; inset: 3px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, rgba(0, 0, 0, .26), rgba(0, 0, 0, .1) 70%, rgba(0, 0, 0, 0));
}
html.v2-glass .dev .fav.overlay svg { position: relative; fill: rgba(0, 0, 0, .3); }
/* Стекло как в Mini App (v2-glass, landing.js; владелец 17.10): на телефоне пуши и кнопки экрана блокировки снова
   с размытием под ними (в старой сцене их отключали — перерисовка на каждом кадре прокрутки); ?glass=off — без */
@media (pointer: coarse) {
  html.v2-glass .push { background: rgba(245, 245, 247, .82); -webkit-backdrop-filter: blur(24px) saturate(170%); backdrop-filter: blur(24px) saturate(170%); }
  html.v2-glass .l-btn { background: rgba(30, 30, 34, .45); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); }
}
/* «Лента · Фильтры · Карта» под телефоном: идут сами, нажатие — к этому шагу; полоска — сколько пройдено */
html.v2 .st-bar {
  display: flex; position: absolute; left: 16px; right: 16px; top: calc(var(--pt) + 868px * var(--ps) + var(--g2)); bottom: auto;
  opacity: 1; pointer-events: auto; filter: none; transition: opacity .3s ease;
}
html.v2 .sb { cursor: pointer; -webkit-user-select: none; user-select: none; }
html.v2 .sb::after { transition: opacity .3s ease; }
html.v2 .sb.on::after { opacity: 1; }
html.v2 .sb-prog { transform: scaleX(0); }
/* Живая карта (v2-live; владелец 17.10 — «как на проде»): телефон — на весь экран (--ps и --pt живой карты,
   landing.js), «Как приложение» и переключатель гаснут — видно, что показ кончился и можно трогать самому; над
   телефоном — подсказка, под ним — «Листайте дальше» (на карте палец тянет карту, а не страницу) */
html.v2 .stage.v2-live .app-text, html.v2 .stage.v2-live .st-bar { opacity: 0; pointer-events: none; }
html.v2 .stage.v2-live .live-hint { opacity: 1; visibility: visible; transform: none; transition: opacity .5s ease .45s, transform .5s ease .45s; }
html.v2 .stage.v2-live .scroll-cue {
  opacity: 1; visibility: visible; transform: translate(-50%, 0); pointer-events: auto;
  transition: opacity .45s ease .35s, transform .45s ease .35s;
}
@media (min-width: 1100px) { html.v2 .stage.v2-live .live-hint { transform: translate(0, -50%); } }
/* простая версия (landing.js: «уменьшить движение», слабое устройство, рывки, ?anim=off): без сцен — переключатель
   не нужен, посты остаются у заголовка */
html.v2-static .st-bar { display: none; }
@media (prefers-reduced-motion: reduce) {
  html.v2 .post { display: none; }
  html.v2 .st-bar { display: none; }
}
