mobile-optimize: +19 patterns (safe-area, sticky CTA, mobile menu, touch feedback, dvh, reduced-motion, font preload, overscroll, -webkit-backdrop-filter)

This commit is contained in:
Nikita Tarasov committed 2026-07-13 14:27:45 +05:00
1 parent 6b25c046db
commit 6b6a119568
1 file changed
+166 -1
+166 -1
View File
@@ -6,6 +6,7 @@
<title>SEOIQ — SEO, которое меняет правила</title> <title>SEOIQ — SEO, которое меняет правила</title>
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;700&display=swap" as="style">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style> <style>
:root { :root {
@@ -42,6 +43,105 @@
color: var(--text); color: var(--text);
overflow-x: hidden; overflow-x: hidden;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
overscroll-behavior-y: contain;
}
@supports (padding: max(0px)) {
body {
padding-top: max(0px, env(safe-area-inset-top));
padding-bottom: max(0px, env(safe-area-inset-bottom));
}
.nav {
padding-top: max(0px, env(safe-area-inset-top));
}
.content {
padding-left: max(24px, env(safe-area-inset-left));
padding-right: max(24px, env(safe-area-inset-right));
}
}
/* ── Touch feedback ── */
.btn {
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
.btn:active {
transform: scale(0.97);
}
.btn-primary:active {
transform: scale(0.97);
}
.btn-glass:active {
transform: scale(0.97);
}
.price-btn:active {
transform: scale(0.97);
}
/* ── Mobile menu ── */
.mobile-menu-btn {
display: none;
width: 44px;
height: 44px;
padding: 10px;
background: transparent;
border: 1px solid var(--border);
border-radius: 8px;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
.mobile-menu-btn span {
display: block;
width: 20px;
height: 2px;
background: var(--text);
margin: 4px auto;
transition: all 0.3s;
}
.mobile-menu {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(3,0,20,0.98);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
z-index: 200;
display: flex;
flex-direction: column;
padding: 80px 24px 40px;
transform: translateX(100%);
transition: transform 0.3s var(--ease);
}
.mobile-menu.open {
transform: translateX(0);
}
.mobile-menu-close {
position: absolute;
top: 20px;
right: 20px;
width: 44px;
height: 44px;
background: transparent;
border: 1px solid var(--border);
border-radius: 8px;
font-size: 24px;
color: var(--text);
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
.mobile-menu a {
display: flex;
align-items: center;
gap: 12px;
padding: 16px 0;
color: var(--text);
text-decoration: none;
font-size: 18px;
font-weight: 500;
border-bottom: 1px solid var(--border);
min-height: 44px;
}
.mobile-menu a:active {
background: rgba(255,255,255,0.05);
} }
/* ── Three.js Canvas ── */ /* ── Three.js Canvas ── */
@@ -147,7 +247,7 @@
/* ── Hero Section ── */ /* ── Hero Section ── */
.hero { .hero {
min-height: 100vh; min-height: 100dvh;
display: flex; flex-direction: column; display: flex; flex-direction: column;
justify-content: center; align-items: center; justify-content: center; align-items: center;
text-align: center; text-align: center;
@@ -687,19 +787,62 @@
footer a { color: var(--text-muted); text-decoration: none; transition: color 0.2s; } footer a { color: var(--text-muted); text-decoration: none; transition: color 0.2s; }
footer a:hover { color: var(--text); } footer a:hover { color: var(--text); }
/* ── Sticky CTA (mobile) ── */
.sticky-cta {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 12px 16px;
padding-bottom: max(12px, env(safe-area-inset-bottom));
background: rgba(3,0,20,0.95);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border-top: 1px solid var(--border);
z-index: 90;
display: none;
flex-direction: column;
gap: 8px;
box-shadow: 0 -4px 12px rgba(0,0,0,0.3);
}
.sticky-cta__btn {
width: 100%;
text-align: center;
padding: 14px 24px;
}
.sticky-cta__hint {
text-align: center;
font-size: 12px;
color: var(--text-muted);
}
/* ── Responsive ── */ /* ── Responsive ── */
@media (max-width: 900px) { @media (max-width: 900px) {
.nav-links { display: none; } .nav-links { display: none; }
.mobile-menu-btn { display: flex; }
.bento-grid { grid-template-columns: 1fr; } .bento-grid { grid-template-columns: 1fr; }
.bento-card.span-2 { grid-column: span 1; } .bento-card.span-2 { grid-column: span 1; }
.pricing-grid { grid-template-columns: 1fr; max-width: 420px; margin: 0 auto; } .pricing-grid { grid-template-columns: 1fr; max-width: 420px; margin: 0 auto; }
.testimonials-grid { grid-template-columns: 1fr; } .testimonials-grid { grid-template-columns: 1fr; }
.hero-stats { gap: 32px; } .hero-stats { gap: 32px; }
.float-el { display: none; } .float-el { display: none; }
.sticky-cta { display: flex; }
main { padding-bottom: 80px; }
} }
@media (max-width: 600px) { @media (max-width: 600px) {
.hero-title { letter-spacing: -2px; } .hero-title { letter-spacing: -2px; }
} }
/* ── Reduced motion ── */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
.reveal { opacity: 1; transform: none; }
}
</style> </style>
</head> </head>
<body> <body>
@@ -713,6 +856,7 @@
<div class="noise"></div> <div class="noise"></div>
<div class="content"> <div class="content">
<main>
<!-- Nav --> <!-- Nav -->
<nav class="nav" id="nav"> <nav class="nav" id="nav">
@@ -724,8 +868,21 @@
<a href="#process">Процесс</a> <a href="#process">Процесс</a>
<a href="#contact" class="nav-cta">Обсудить проект →</a> <a href="#contact" class="nav-cta">Обсудить проект →</a>
</div> </div>
<button class="mobile-menu-btn" aria-label="Открыть меню" onclick="document.querySelector('.mobile-menu').classList.add('open'); document.body.style.overflow='hidden'">
<span></span><span></span><span></span>
</button>
</nav> </nav>
<!-- Mobile Menu -->
<div class="mobile-menu" id="mobile-menu">
<button class="mobile-menu-close" aria-label="Закрыть меню" onclick="document.querySelector('.mobile-menu').classList.remove('open'); document.body.style.overflow=''">✕</button>
<a href="#approach" onclick="document.querySelector('.mobile-menu').classList.remove('open'); document.body.style.overflow=''">📊 Подход</a>
<a href="#results" onclick="document.querySelector('.mobile-menu').classList.remove('open'); document.body.style.overflow=''">📈 Результаты</a>
<a href="#pricing" onclick="document.querySelector('.mobile-menu').classList.remove('open'); document.body.style.overflow=''">💰 Тарифы</a>
<a href="#process" onclick="document.querySelector('.mobile-menu').classList.remove('open'); document.body.style.overflow=''">⚡ Процесс</a>
<a href="#contact" onclick="document.querySelector('.mobile-menu').classList.remove('open'); document.body.style.overflow=''">📞 Обсудить проект →</a>
</div>
<!-- Hero --> <!-- Hero -->
<section class="hero"> <section class="hero">
<div class="floating-elements"> <div class="floating-elements">
@@ -1077,6 +1234,14 @@
<span>Уфа, Россия · <a href="mailto:nikita@tarasov.top">nikita@tarasov.top</a></span> <span>Уфа, Россия · <a href="mailto:nikita@tarasov.top">nikita@tarasov.top</a></span>
</footer> </footer>
</main>
<!-- Sticky CTA (mobile only) -->
<div class="sticky-cta">
<a href="#contact" class="btn btn-primary sticky-cta__btn">Обсудить проект →</a>
<span class="sticky-cta__hint">Средний отклик — менее 2 часов</span>
</div>
</div> </div>
<!-- Three.js + GSAP --> <!-- Three.js + GSAP -->