Исправить дефекты разметки лендинга
Create and publish a Docker image / build-and-push-image (push) Successful in 1m18s

- Убрать scroll-reveal на IntersectionObserver: секции стартовали с
  opacity:0 и оставались невидимыми, если JS не успевал/не отрабатывал
  (подтверждено на полностраничном скриншоте — большие блоки контента
  были полностью невидимы).
- "Wildberries" в hero-заголовке рендерился шрифтом Cinzel (нет
  кириллицы, поэтому кириллический текст уже шёл через Georgia-фоллбэк),
  а латиница в Cinzel выглядит капителью — визуально WILDBERRIES.
  Принудительно применяем тот же Georgia-фоллбэк к этому слову.
- Плавающий бейдж "-86% к цене" перекрывал текст второго бабла в
  мокапе телефона — сдвинут под нижнюю границу карточки, как у
  парного бейджа "Хап найден!" сверху.
This commit is contained in:
kislovdm
2026-08-11 14:24:56 +03:00
parent db87244696
commit fbdb622976
2 changed files with 23 additions and 42 deletions
+1 -1
View File
@@ -42,4 +42,4 @@ khap-landing/
## Известные особенности ## Известные особенности
- **Важно при изменении nginx-маршрутизации**: `location = /` на прод-хосте — точное совпадение по пути запроса, без учёта query-строки. Реальные return/callback-URL платёжных провайдеров (ЮMoney/ЮKassa/Qiwi, обрабатываются `bot/gatekeeper`/`bot/gatekeeper-payment`) используют только префикс `/payments/...`, поэтому этот сервис не пересекается с платёжными флоу. Не менять этот `location` на нестрогий/regex-catch-all — это заберёт себе трафик `/payments/*`, `/success.html`, `/donate.html` и т.п., которые должны оставаться на `gatekeeper-payment`. - **Важно при изменении nginx-маршрутизации**: `location = /` на прод-хосте — точное совпадение по пути запроса, без учёта query-строки. Реальные return/callback-URL платёжных провайдеров (ЮMoney/ЮKassa/Qiwi, обрабатываются `bot/gatekeeper`/`bot/gatekeeper-payment`) используют только префикс `/payments/...`, поэтому этот сервис не пересекается с платёжными флоу. Не менять этот `location` на нестрогий/regex-catch-all — это заберёт себе трафик `/payments/*`, `/success.html`, `/donate.html` и т.п., которые должны оставаться на `gatekeeper-payment`.
- Юзернейм бота "Стражник" в других частях платформы (FAQ, `bot/wbproductinfo`, и др.) местами указан как `@king_gatekeeper_bot` (без второго подчёркивания) — это расхождение с реально используемым в этом лендинге и в `Gatekeeper.Shared/Constants.cs` `@king_gate_keeper_bot`. Проверено вручную в Telegram: именно `@king_gate_keeper_bot` — живой бот "Королевский Стражник" с фото и описанием. - Юзернейм бота "Стражник" — `@king_gate_keeper_bot` (проверено вручную в Telegram: живой бот "Королевский Стражник" с фото и описанием). Ранее в других частях платформы (FAQ, `bot/wbproductinfo`, и др.) местами был указан ошибочный `@king_gatekeeper_bot` (без второго подчёркивания) — расхождение исправлено.
+22 -41
View File
@@ -47,6 +47,10 @@
overflow-x:hidden; overflow-x:hidden;
} }
h1,h2,h3,.crown-font{font-family:'Cinzel', Georgia, serif;} h1,h2,h3,.crown-font{font-family:'Cinzel', Georgia, serif;}
/* Cinzel has no Cyrillic glyphs; Latin words inside RU headings would render
in Cinzel's small-caps-style latin set (looks SHOUTED) instead of falling
back with the rest of the heading — force the same serif fallback explicitly. */
.latin-serif{font-family:Georgia, 'Times New Roman', serif;}
a{color:inherit;text-decoration:none;} a{color:inherit;text-decoration:none;}
img{max-width:100%;display:block;} img{max-width:100%;display:block;}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px;} .wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px;}
@@ -154,7 +158,7 @@
display:flex;align-items:center;gap:8px; display:flex;align-items:center;gap:8px;
} }
.float-badge.b1{top:-18px;right:-14px;color:var(--gold);} .float-badge.b1{top:-18px;right:-14px;color:var(--gold);}
.float-badge.b2{bottom:18px;left:-22px;color:var(--green);} .float-badge.b2{bottom:-16px;left:24px;color:var(--green);}
.float-badge svg{width:16px;height:16px;} .float-badge svg{width:16px;height:16px;}
/* ---------- how it works ---------- */ /* ---------- how it works ---------- */
@@ -273,10 +277,6 @@
.footer-links a:hover{color:var(--text);} .footer-links a:hover{color:var(--text);}
.footer-note{color:var(--muted-2);font-size:12.5px;margin-top:22px;} .footer-note{color:var(--muted-2);font-size:12.5px;margin-top:22px;}
/* ---------- reveal animation ---------- */
.reveal{opacity:0;transform:translateY(18px);transition:opacity .6s ease, transform .6s ease;}
.reveal.show{opacity:1;transform:none;}
/* ---------- responsive ---------- */ /* ---------- responsive ---------- */
@media (max-width:980px){ @media (max-width:980px){
.hero-grid{grid-template-columns:1fr;} .hero-grid{grid-template-columns:1fr;}
@@ -323,7 +323,7 @@
<div class="wrap hero-grid"> <div class="wrap hero-grid">
<div> <div>
<span class="eyebrow">👑 Бот-охотник за скидками WB</span> <span class="eyebrow">👑 Бот-охотник за скидками WB</span>
<h1>Ловите <span class="accent">ценовые ошибки</span> и лучшие скидки Wildberries раньше всех</h1> <h1>Ловите <span class="accent">ценовые ошибки</span> и лучшие скидки <span class="latin-serif">Wildberries</span> раньше всех</h1>
<p class="lede">«Королевский Хап» сканирует Wildberries 24/7 и мгновенно присылает в Telegram товары с сильно заниженной ценой — пока их не выкупили другие.</p> <p class="lede">«Королевский Хап» сканирует Wildberries 24/7 и мгновенно присылает в Telegram товары с сильно заниженной ценой — пока их не выкупили другие.</p>
<div class="hero-cta"> <div class="hero-cta">
<a class="btn btn-gold" href="https://t.me/king_gate_keeper_bot" target="_blank" rel="noopener"> <a class="btn btn-gold" href="https://t.me/king_gate_keeper_bot" target="_blank" rel="noopener">
@@ -380,22 +380,22 @@
<p class="lede center">Никакого ручного мониторинга каталога. Бот делает всё сам, вам остаётся только забрать товар.</p> <p class="lede center">Никакого ручного мониторинга каталога. Бот делает всё сам, вам остаётся только забрать товар.</p>
<div class="steps"> <div class="steps">
<div class="step reveal"> <div class="step">
<span class="num">01</span> <span class="num">01</span>
<h3>Бот сканирует WB</h3> <h3>Бот сканирует WB</h3>
<p>Непрерывно проверяет цены и остатки тысяч товаров на Wildberries по всем складам.</p> <p>Непрерывно проверяет цены и остатки тысяч товаров на Wildberries по всем складам.</p>
</div> </div>
<div class="step reveal"> <div class="step">
<span class="num">02</span> <span class="num">02</span>
<h3>Находит «хап»</h3> <h3>Находит «хап»</h3>
<p>Замечает товары с ценовой ошибкой или резкой скидкой, которые продавец скоро исправит.</p> <p>Замечает товары с ценовой ошибкой или резкой скидкой, которые продавец скоро исправит.</p>
</div> </div>
<div class="step reveal"> <div class="step">
<span class="num">03</span> <span class="num">03</span>
<h3>Присылает в Telegram</h3> <h3>Присылает в Telegram</h3>
<p>Вы получаете ссылку с ценой, складом и остатком — мгновенно, пока товар ещё доступен.</p> <p>Вы получаете ссылку с ценой, складом и остатком — мгновенно, пока товар ещё доступен.</p>
</div> </div>
<div class="step reveal"> <div class="step">
<span class="num">04</span> <span class="num">04</span>
<h3>Забираете хап</h3> <h3>Забираете хап</h3>
<p>Покупаете сами одной кнопкой в боте — или бот сделает заказ за вас по вашим правилам автовыкупа.</p> <p>Покупаете сами одной кнопкой в боте — или бот сделает заказ за вас по вашим правилам автовыкупа.</p>
@@ -411,32 +411,32 @@
<h2 class="center">Всё, чтобы не пропустить ни одного хапа</h2> <h2 class="center">Всё, чтобы не пропустить ни одного хапа</h2>
<div class="features"> <div class="features">
<div class="feature reveal"> <div class="feature">
<div class="icon"><svg viewBox="0 0 24 24" fill="none"><path d="M12 2v2m0 16v2M4.9 4.9l1.4 1.4m11.4 11.4 1.4 1.4M2 12h2m16 0h2M4.9 19.1l1.4-1.4m11.4-11.4 1.4-1.4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.8"/></svg></div> <div class="icon"><svg viewBox="0 0 24 24" fill="none"><path d="M12 2v2m0 16v2M4.9 4.9l1.4 1.4m11.4 11.4 1.4 1.4M2 12h2m16 0h2M4.9 19.1l1.4-1.4m11.4-11.4 1.4-1.4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.8"/></svg></div>
<h3>Мгновенные уведомления</h3> <h3>Мгновенные уведомления</h3>
<p>Как только бот находит подходящий товар — ссылка приходит вам в Telegram сразу, без задержек.</p> <p>Как только бот находит подходящий товар — ссылка приходит вам в Telegram сразу, без задержек.</p>
</div> </div>
<div class="feature reveal"> <div class="feature">
<div class="icon"><svg viewBox="0 0 24 24" fill="none"><rect x="4" y="2" width="16" height="20" rx="3" stroke="currentColor" stroke-width="1.8"/><path d="M9 18h6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></div> <div class="icon"><svg viewBox="0 0 24 24" fill="none"><rect x="4" y="2" width="16" height="20" rx="3" stroke="currentColor" stroke-width="1.8"/><path d="M9 18h6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></div>
<h3>Кнопка «Купить»</h3> <h3>Кнопка «Купить»</h3>
<p>Заказывайте товар прямо из Telegram одним нажатием — без перехода на сайт Wildberries.</p> <p>Заказывайте товар прямо из Telegram одним нажатием — без перехода на сайт Wildberries.</p>
</div> </div>
<div class="feature reveal"> <div class="feature">
<div class="icon"><svg viewBox="0 0 24 24" fill="none"><rect x="3" y="7" width="18" height="13" rx="2" stroke="currentColor" stroke-width="1.8"/><path d="M8 7V5a4 4 0 0 1 8 0v2" stroke="currentColor" stroke-width="1.8"/></svg></div> <div class="icon"><svg viewBox="0 0 24 24" fill="none"><rect x="3" y="7" width="18" height="13" rx="2" stroke="currentColor" stroke-width="1.8"/><path d="M8 7V5a4 4 0 0 1 8 0v2" stroke="currentColor" stroke-width="1.8"/></svg></div>
<h3>Автовыкуп по правилам</h3> <h3>Автовыкуп по правилам</h3>
<p>Настройте фильтр по товару и цене — бот оформит заказ автоматически, даже если вы не онлайн.</p> <p>Настройте фильтр по товару и цене — бот оформит заказ автоматически, даже если вы не онлайн.</p>
</div> </div>
<div class="feature reveal"> <div class="feature">
<div class="icon"><svg viewBox="0 0 24 24" fill="none"><path d="M17 20c0-3-2.5-5-5-5s-5 2-5 5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><circle cx="12" cy="8" r="3.5" stroke="currentColor" stroke-width="1.8"/><path d="M2 20c.3-2 1.7-3.6 3.5-4.3M22 20c-.3-2-1.7-3.6-3.5-4.3" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></div> <div class="icon"><svg viewBox="0 0 24 24" fill="none"><path d="M17 20c0-3-2.5-5-5-5s-5 2-5 5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><circle cx="12" cy="8" r="3.5" stroke="currentColor" stroke-width="1.8"/><path d="M2 20c.3-2 1.7-3.6 3.5-4.3M22 20c-.3-2-1.7-3.6-3.5-4.3" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></div>
<h3>Реферальная программа</h3> <h3>Реферальная программа</h3>
<p>Приглашайте друзей по своей ссылке и получайте бонусные дни подписки за каждого.</p> <p>Приглашайте друзей по своей ссылке и получайте бонусные дни подписки за каждого.</p>
</div> </div>
<div class="feature reveal"> <div class="feature">
<div class="icon"><svg viewBox="0 0 24 24" fill="none"><path d="M21 11.5a8.5 8.5 0 1 1-3.3-6.7L21 4l-1 3.6a8.5 8.5 0 0 1 1 3.9Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg></div> <div class="icon"><svg viewBox="0 0 24 24" fill="none"><path d="M21 11.5a8.5 8.5 0 1 1-3.3-6.7L21 4l-1 3.6a8.5 8.5 0 0 1 1 3.9Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg></div>
<h3>Живое комьюнити</h3> <h3>Живое комьюнити</h3>
<p>Общий чат и канал с «хвастами» — реальные покупки подписчиков, которые бот помог найти.</p> <p>Общий чат и канал с «хвастами» — реальные покупки подписчиков, которые бот помог найти.</p>
</div> </div>
<div class="feature reveal"> <div class="feature">
<div class="icon"><svg viewBox="0 0 24 24" fill="none"><path d="M12 3 3 7v6c0 4.5 4 7.5 9 8 5-.5 9-3.5 9-8V7l-9-4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg></div> <div class="icon"><svg viewBox="0 0 24 24" fill="none"><path d="M12 3 3 7v6c0 4.5 4 7.5 9 8 5-.5 9-3.5 9-8V7l-9-4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg></div>
<h3>Все склады WB</h3> <h3>Все склады WB</h3>
<p>Учитываются остатки на складах по всей стране — вы видите, где именно есть товар и сколько штук.</p> <p>Учитываются остатки на складах по всей стране — вы видите, где именно есть товар и сколько штук.</p>
@@ -453,7 +453,7 @@
<p class="lede center">Все тарифы включают полный доступ к боту со ссылками и кнопку покупки прямо в Telegram. Оплата и выбор тарифа — внутри бота.</p> <p class="lede center">Все тарифы включают полный доступ к боту со ссылками и кнопку покупки прямо в Telegram. Оплата и выбор тарифа — внутри бота.</p>
<div class="pricing-grid"> <div class="pricing-grid">
<div class="price-card reveal"> <div class="price-card">
<div class="period">7 дней</div> <div class="period">7 дней</div>
<div class="amount">185 ₽</div> <div class="amount">185 ₽</div>
<div class="perday">≈ 26,4 ₽ / день</div> <div class="perday">≈ 26,4 ₽ / день</div>
@@ -465,7 +465,7 @@
<a class="btn btn-ghost btn-block" href="https://t.me/king_gate_keeper_bot" target="_blank" rel="noopener">Выбрать</a> <a class="btn btn-ghost btn-block" href="https://t.me/king_gate_keeper_bot" target="_blank" rel="noopener">Выбрать</a>
</div> </div>
<div class="price-card reveal"> <div class="price-card">
<div class="period">14 дней</div> <div class="period">14 дней</div>
<div class="amount">300 ₽</div> <div class="amount">300 ₽</div>
<div class="perday">≈ 21,4 ₽ / день</div> <div class="perday">≈ 21,4 ₽ / день</div>
@@ -477,7 +477,7 @@
<a class="btn btn-ghost btn-block" href="https://t.me/king_gate_keeper_bot" target="_blank" rel="noopener">Выбрать</a> <a class="btn btn-ghost btn-block" href="https://t.me/king_gate_keeper_bot" target="_blank" rel="noopener">Выбрать</a>
</div> </div>
<div class="price-card featured reveal"> <div class="price-card featured">
<div class="badge">Популярный</div> <div class="badge">Популярный</div>
<div class="period">30 дней</div> <div class="period">30 дней</div>
<div class="amount">500 ₽</div> <div class="amount">500 ₽</div>
@@ -490,7 +490,7 @@
<a class="btn btn-gold btn-block" href="https://t.me/king_gate_keeper_bot" target="_blank" rel="noopener">Выбрать</a> <a class="btn btn-gold btn-block" href="https://t.me/king_gate_keeper_bot" target="_blank" rel="noopener">Выбрать</a>
</div> </div>
<div class="price-card reveal"> <div class="price-card">
<div class="badge" style="background:linear-gradient(135deg,var(--green),#1fae74);color:#04231a;">Выгоднее всего</div> <div class="badge" style="background:linear-gradient(135deg,var(--green),#1fae74);color:#04231a;">Выгоднее всего</div>
<div class="period">60 дней</div> <div class="period">60 дней</div>
<div class="amount">949 ₽</div> <div class="amount">949 ₽</div>
@@ -509,7 +509,7 @@
<!-- SOCIAL PROOF --> <!-- SOCIAL PROOF -->
<section class="tight"> <section class="tight">
<div class="wrap"> <div class="wrap">
<div class="proof-wrap reveal"> <div class="proof-wrap">
<div> <div>
<p class="quote">«Каждый день в чате — <span>новые хвасты</span> подписчиков: кто и что успел забрать по бросовой цене.»</p> <p class="quote">«Каждый день в чате — <span>новые хвасты</span> подписчиков: кто и что успел забрать по бросовой цене.»</p>
</div> </div>
@@ -561,7 +561,7 @@
<!-- FINAL CTA --> <!-- FINAL CTA -->
<section class="tight"> <section class="tight">
<div class="wrap"> <div class="wrap">
<div class="final-cta reveal"> <div class="final-cta">
<span class="eyebrow center" style="display:table;margin-left:auto;margin-right:auto;">Пора начинать</span> <span class="eyebrow center" style="display:table;margin-left:auto;margin-right:auto;">Пора начинать</span>
<h2>Не пропустите свой первый хап</h2> <h2>Не пропустите свой первый хап</h2>
<p class="lede center">Подключитесь за пару минут — и уже сегодня получите первую ссылку на выгодную покупку.</p> <p class="lede center">Подключитесь за пару минут — и уже сегодня получите первую ссылку на выгодную покупку.</p>
@@ -590,24 +590,5 @@
</div> </div>
</footer> </footer>
<script>
document.addEventListener('DOMContentLoaded', function () {
var els = document.querySelectorAll('.reveal');
if (!('IntersectionObserver' in window)) {
els.forEach(function (el) { el.classList.add('show'); });
return;
}
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add('show');
io.unobserve(entry.target);
}
});
}, { threshold: 0.15 });
els.forEach(function (el) { io.observe(el); });
});
</script>
</body> </body>
</html> </html>