wa-dev-tools/public/landing.html
treamz f8616e32b4 Auth + Landing + Categories
- Local auth: registration/login with email+password (bcrypt, MariaDB)
- Landing page: marketing page at / with hero, categories, advantages, CTA
- Tool categories: Images (4), Code (3), Web (3), Utilities (2)
- Sidebar: category dividers, user avatar with logout
- Protected routes: all tools require auth, landing/login/register public
- New files: lib/db.js, routes/auth.js, login.html, register.html, landing.html
- Dependencies: bcrypt, mysql2
2026-03-21 22:54:31 +03:00

897 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WA Dev Tools — 13 бесплатных инструментов для веб-разработчика</title>
<meta name="description" content="Сжатие картинок, форматирование кода, HTTP-клиент и ещё 10 инструментов для веб-разработчиков — всё в браузере, бесплатно." />
<script src="/vendor/tailwind.js"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: { extend: {
fontFamily: { mono: ['JetBrains Mono', 'monospace'], sans: ['Manrope', 'sans-serif'] },
colors: { surface: { 900: '#060c18', 800: '#091020', 700: '#0d1828', 600: '#162040' }, accent: { DEFAULT: '#0054e6', dim: '#0043b8', bright: '#6b9fff' } }
}}
};
</script>
<link href="/vendor/fonts.css" rel="stylesheet">
<link href="/shared.css" rel="stylesheet">
<style>
/* ── Resets & base ── */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* ── Animations ── */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(28px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes glow-pulse {
0%, 100% { opacity: 0.45; }
50% { opacity: 0.70; }
}
@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-8px); }
}
.animate-fade-in { animation: fadeIn 0.7s ease both; }
.animate-slide-up { animation: slideUp 0.7s ease both; }
.delay-100 { animation-delay: 0.10s; }
.delay-200 { animation-delay: 0.20s; }
.delay-300 { animation-delay: 0.30s; }
.delay-400 { animation-delay: 0.40s; }
.delay-500 { animation-delay: 0.50s; }
.delay-600 { animation-delay: 0.60s; }
/* Intersection-observer driven reveal */
.reveal {
opacity: 0;
transform: translateY(24px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.reveal.visible {
opacity: 1;
transform: translateY(0);
}
.reveal-delay-1 { transition-delay: 0.10s; }
.reveal-delay-2 { transition-delay: 0.20s; }
.reveal-delay-3 { transition-delay: 0.30s; }
.reveal-delay-4 { transition-delay: 0.40s; }
/* ── Hero ── */
.hero {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 80px 20px 60px;
position: relative;
overflow: hidden;
}
/* Glow blobs */
.hero-glow-1 {
position: absolute;
top: -10%;
left: 50%;
transform: translateX(-50%);
width: min(700px, 120vw);
height: min(700px, 120vw);
background: radial-gradient(ellipse at center, rgba(0, 84, 230, 0.18) 0%, transparent 65%);
pointer-events: none;
animation: glow-pulse 5s ease-in-out infinite;
}
.hero-glow-2 {
position: absolute;
bottom: 0;
right: -15%;
width: 420px;
height: 420px;
background: radial-gradient(ellipse at center, rgba(107, 159, 255, 0.08) 0%, transparent 60%);
pointer-events: none;
animation: glow-pulse 7s ease-in-out infinite reverse;
}
.hero-glow-3 {
position: absolute;
bottom: 10%;
left: -10%;
width: 360px;
height: 360px;
background: radial-gradient(ellipse at center, rgba(0, 67, 184, 0.10) 0%, transparent 60%);
pointer-events: none;
animation: glow-pulse 6s ease-in-out infinite 1s;
}
/* Grid lines overlay */
.hero-grid {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(0, 84, 230, 0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 84, 230, 0.04) 1px, transparent 1px);
background-size: 60px 60px;
mask-image: radial-gradient(ellipse at center, black 20%, transparent 75%);
pointer-events: none;
}
.hero-logo {
font-family: 'JetBrains Mono', monospace;
font-size: clamp(11px, 1.5vw, 13px);
font-weight: 700;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: 28px;
}
.hero-logo span {
color: var(--accent-bright);
}
.hero-headline {
font-family: 'Manrope', sans-serif;
font-size: clamp(2rem, 5.5vw, 3.75rem);
font-weight: 800;
line-height: 1.15;
letter-spacing: -0.03em;
color: var(--text-primary);
max-width: 820px;
margin: 0 auto 20px;
}
.hero-headline .accent { color: var(--accent); }
.hero-sub {
font-family: 'Manrope', sans-serif;
font-size: clamp(1rem, 2vw, 1.2rem);
line-height: 1.65;
color: var(--text-secondary);
max-width: 600px;
margin: 0 auto 44px;
}
.hero-cta-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
@media (min-width: 480px) {
.hero-cta-group { flex-direction: row; justify-content: center; }
}
.btn-primary {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 15px 32px;
background: var(--accent);
color: #fff;
border: none;
border-radius: 12px;
font-family: 'Manrope', sans-serif;
font-weight: 700;
font-size: 16px;
text-decoration: none;
cursor: pointer;
transition: background 0.2s, transform 0.2s, box-shadow 0.2s;
box-shadow: 0 0 0 0 rgba(0, 84, 230, 0);
}
.btn-primary:hover {
background: var(--accent-dim);
transform: translateY(-2px);
box-shadow: 0 8px 32px rgba(0, 84, 230, 0.35);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-secondary {
display: inline-flex;
align-items: center;
font-family: 'Manrope', sans-serif;
font-size: 15px;
color: var(--text-secondary);
text-decoration: none;
transition: color 0.2s;
}
.btn-secondary:hover { color: var(--text-primary); }
.btn-secondary .link-text {
border-bottom: 1px solid var(--surface-600);
padding-bottom: 1px;
}
/* Count badge in hero */
.hero-badge {
display: inline-flex;
align-items: center;
gap: 8px;
background: var(--surface-700);
border: 1px solid var(--surface-600);
border-radius: 999px;
padding: 6px 16px 6px 10px;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
color: var(--text-muted);
margin-bottom: 28px;
}
.hero-badge .dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent-bright);
box-shadow: 0 0 6px var(--accent-bright);
animation: glow-pulse 2s ease-in-out infinite;
}
/* ── Scroll hint ── */
.scroll-hint {
position: absolute;
bottom: 28px;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
color: var(--text-muted);
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
letter-spacing: 0.15em;
text-transform: uppercase;
animation: float 2.5s ease-in-out infinite;
}
/* ── Section common ── */
.section {
padding: 80px 20px;
}
.section-inner {
max-width: 1120px;
margin: 0 auto;
}
.section-label {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--accent-bright);
margin-bottom: 12px;
}
.section-title {
font-family: 'Manrope', sans-serif;
font-size: clamp(1.6rem, 4vw, 2.4rem);
font-weight: 800;
letter-spacing: -0.025em;
color: var(--text-primary);
margin: 0 0 48px;
line-height: 1.2;
}
/* ── Category cards ── */
.cat-grid {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
@media (min-width: 640px) {
.cat-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
.cat-grid { grid-template-columns: repeat(4, 1fr); }
}
.cat-card {
background: var(--surface-700);
border: 1px solid var(--surface-600);
border-radius: 16px;
padding: 28px 24px;
display: flex;
flex-direction: column;
gap: 16px;
transition: border-color 0.25s, transform 0.25s, box-shadow 0.25s;
}
.cat-card:hover {
border-color: rgba(0, 84, 230, 0.5);
transform: translateY(-4px);
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(0, 84, 230, 0.15);
}
.cat-icon-wrap {
width: 48px;
height: 48px;
border-radius: 12px;
background: var(--accent-bg);
display: flex;
align-items: center;
justify-content: center;
color: var(--accent-bright);
flex-shrink: 0;
}
.cat-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.cat-title {
font-family: 'Manrope', sans-serif;
font-size: 18px;
font-weight: 700;
color: var(--text-primary);
}
.cat-badge {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
font-weight: 700;
color: var(--accent-bright);
background: rgba(107, 159, 255, 0.12);
border: 1px solid rgba(107, 159, 255, 0.2);
border-radius: 999px;
padding: 2px 10px;
white-space: nowrap;
}
.cat-desc {
font-family: 'Manrope', sans-serif;
font-size: 14px;
line-height: 1.6;
color: var(--text-secondary);
flex: 1;
}
.cat-tools {
display: flex;
flex-direction: column;
gap: 6px;
padding-top: 4px;
border-top: 1px solid var(--surface-600);
}
.cat-tool-item {
display: flex;
align-items: center;
gap: 8px;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
color: var(--text-muted);
}
.cat-tool-item::before {
content: '';
width: 4px;
height: 4px;
border-radius: 50%;
background: var(--accent-bright);
opacity: 0.5;
flex-shrink: 0;
}
/* ── Advantages ── */
.adv-section {
background: var(--surface-700);
border-top: 1px solid var(--surface-600);
border-bottom: 1px solid var(--surface-600);
}
.adv-grid {
display: grid;
grid-template-columns: 1fr;
gap: 0;
}
@media (min-width: 640px) {
.adv-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
.adv-grid { grid-template-columns: repeat(4, 1fr); }
}
.adv-card {
padding: 36px 28px;
display: flex;
flex-direction: column;
gap: 12px;
border-right: 1px solid var(--surface-600);
border-bottom: 1px solid var(--surface-600);
}
.adv-card:last-child { border-right: none; }
@media (min-width: 640px) {
.adv-card:nth-child(2) { border-right: none; }
.adv-card:nth-child(3) { border-bottom: none; }
.adv-card:nth-child(4) { border-right: none; border-bottom: none; }
}
@media (min-width: 1024px) {
.adv-card:nth-child(2) { border-right: 1px solid var(--surface-600); }
.adv-card:nth-child(3) { border-bottom: 1px solid var(--surface-600); }
.adv-card:last-child { border-right: none; border-bottom: none; }
/* last row has no bottom border */
.adv-card { border-bottom: none; }
}
.adv-icon-wrap {
width: 44px;
height: 44px;
border-radius: 10px;
background: var(--accent-bg);
display: flex;
align-items: center;
justify-content: center;
color: var(--accent-bright);
}
.adv-title {
font-family: 'Manrope', sans-serif;
font-size: 17px;
font-weight: 700;
color: var(--text-primary);
}
.adv-desc {
font-family: 'Manrope', sans-serif;
font-size: 14px;
line-height: 1.65;
color: var(--text-secondary);
}
/* ── Final CTA ── */
.cta-section {
text-align: center;
padding: 100px 20px;
}
.cta-glow {
position: relative;
display: inline-block;
}
.cta-glow::before {
content: '';
position: absolute;
inset: -40px -80px;
background: radial-gradient(ellipse at center, rgba(0, 84, 230, 0.12) 0%, transparent 65%);
pointer-events: none;
}
.cta-headline {
font-family: 'Manrope', sans-serif;
font-size: clamp(1.8rem, 4vw, 2.8rem);
font-weight: 800;
letter-spacing: -0.025em;
color: var(--text-primary);
margin: 0 0 16px;
}
.cta-sub {
font-family: 'Manrope', sans-serif;
font-size: clamp(0.95rem, 1.8vw, 1.1rem);
line-height: 1.65;
color: var(--text-secondary);
margin: 0 auto 40px;
max-width: 480px;
}
/* ── Nav ── */
.landing-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 32px;
background: rgba(6, 12, 24, 0);
border-bottom: 1px solid transparent;
transition: background 0.3s, border-color 0.3s, backdrop-filter 0.3s;
}
.landing-nav.scrolled {
background: rgba(6, 12, 24, 0.85);
border-color: var(--surface-600);
backdrop-filter: blur(12px);
}
.nav-logo {
font-family: 'Manrope', sans-serif;
font-size: 18px;
font-weight: 800;
color: var(--text-primary);
text-decoration: none;
letter-spacing: -0.02em;
}
.nav-logo span { color: var(--accent); }
.nav-actions {
display: flex;
align-items: center;
gap: 12px;
}
.nav-link {
font-family: 'Manrope', sans-serif;
font-size: 14px;
font-weight: 600;
color: var(--text-secondary);
text-decoration: none;
transition: color 0.2s;
padding: 8px 4px;
}
.nav-link:hover { color: var(--text-primary); }
.nav-btn {
font-family: 'Manrope', sans-serif;
font-size: 14px;
font-weight: 700;
color: #fff;
background: var(--accent);
text-decoration: none;
padding: 9px 20px;
border-radius: 8px;
transition: background 0.2s;
}
.nav-btn:hover { background: var(--accent-dim); }
/* ── Footer ── */
.landing-footer {
padding: 28px 32px;
border-top: 1px solid var(--surface-600);
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12px;
}
.footer-copy {
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
color: var(--text-muted);
}
.footer-links {
display: flex;
gap: 20px;
}
.footer-link {
font-family: 'Manrope', sans-serif;
font-size: 13px;
color: var(--text-muted);
text-decoration: none;
transition: color 0.2s;
}
.footer-link:hover { color: var(--text-secondary); }
/* ── Divider line with accent ── */
.section-divider {
width: 40px;
height: 3px;
background: var(--accent);
border-radius: 2px;
margin-bottom: 16px;
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
</style>
</head>
<body>
<!-- ════════════════════════════════════════════
NAV
════════════════════════════════════════════ -->
<nav class="landing-nav" id="mainNav">
<a href="/" class="nav-logo">WA Dev <span>Tools</span></a>
<div class="nav-actions">
<a href="/auth/login" class="nav-link">Войти</a>
<a href="/auth/register" class="nav-btn">Регистрация</a>
</div>
</nav>
<!-- ════════════════════════════════════════════
HERO
════════════════════════════════════════════ -->
<section class="hero">
<div class="hero-glow-1"></div>
<div class="hero-glow-2"></div>
<div class="hero-glow-3"></div>
<div class="hero-grid"></div>
<div style="position:relative;z-index:1;width:100%;">
<div class="hero-badge animate-fade-in">
<span class="dot"></span>
<span>13 инструментов — бесплатно навсегда</span>
</div>
<div class="hero-logo animate-slide-up delay-100">
WA Dev <span>Tools</span>
</div>
<h1 class="hero-headline animate-slide-up delay-200">
Инструменты для<br>
<span class="accent">веб-разработчика</span>
</h1>
<p class="hero-sub animate-slide-up delay-300">
Сжатие картинок, форматирование кода, HTTP-клиент и ещё 10 инструментов —
всё в браузере, бесплатно и без регистрации карты.
</p>
<div class="hero-cta-group animate-slide-up delay-400">
<a href="/auth/register" class="btn-primary">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M13 5H7a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6"/>
<path d="M17 3h4v4"/>
<path d="M10 14 21 3"/>
</svg>
Начать бесплатно
</a>
<a href="/auth/login" class="btn-secondary">
<span class="link-text">Уже есть аккаунт? Войти</span>
</a>
</div>
</div>
<a href="#tools" class="scroll-hint" aria-label="Прокрутить вниз">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m6 9 6 6 6-6"/>
</svg>
<span>Подробнее</span>
</a>
</section>
<!-- ════════════════════════════════════════════
CATEGORIES
════════════════════════════════════════════ -->
<section class="section" id="tools">
<div class="section-inner">
<div class="reveal">
<p class="section-label">Что внутри</p>
<div class="section-divider"></div>
<h2 class="section-title">Инструменты</h2>
</div>
<div class="cat-grid">
<!-- Изображения -->
<div class="cat-card reveal reveal-delay-1">
<div class="cat-icon-wrap">
<!-- Heroicons: photo -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="3"/>
<path d="M3 9h18"/>
<circle cx="9" cy="6" r="1" fill="currentColor" stroke="none"/>
<path d="M3 15l4-4 4 4 3-3 5 5"/>
</svg>
</div>
<div>
<div class="cat-header">
<span class="cat-title">Изображения</span>
<span class="cat-badge">4 инструмента</span>
</div>
</div>
<p class="cat-desc">Сжатие, редактирование, SVG и placeholder-генератор</p>
<ul class="cat-tools">
<li class="cat-tool-item">Сжатие картинок</li>
<li class="cat-tool-item">Placeholder-генератор</li>
<li class="cat-tool-item">SVG-редактор</li>
<li class="cat-tool-item">Фоторедактор</li>
</ul>
</div>
<!-- Код -->
<div class="cat-card reveal reveal-delay-2">
<div class="cat-icon-wrap">
<!-- Heroicons: code-bracket -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
<path d="m8 6-4 6 4 6"/>
<path d="m16 6 4 6-4 6"/>
<path d="m14 4-4 16"/>
</svg>
</div>
<div>
<div class="cat-header">
<span class="cat-title">Код</span>
<span class="cat-badge">3 инструмента</span>
</div>
</div>
<p class="cat-desc">Форматирование, очистка и конвертация кода между форматами</p>
<ul class="cat-tools">
<li class="cat-tool-item">Форматирование кода</li>
<li class="cat-tool-item">HTML Sanitizer</li>
<li class="cat-tool-item">Конвертер форматов</li>
</ul>
</div>
<!-- Веб -->
<div class="cat-card reveal reveal-delay-3">
<div class="cat-icon-wrap">
<!-- Heroicons: globe-alt -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"/>
<path d="M3.6 9h16.8M3.6 15h16.8"/>
<path d="M12 3a14.4 14.4 0 0 1 0 18M12 3a14.4 14.4 0 0 0 0 18"/>
</svg>
</div>
<div>
<div class="cat-header">
<span class="cat-title">Веб</span>
<span class="cat-badge">3 инструмента</span>
</div>
</div>
<p class="cat-desc">HTTP-клиент, парсер страниц и анализ редиректов</p>
<ul class="cat-tools">
<li class="cat-tool-item">HTTP-клиент</li>
<li class="cat-tool-item">Парсер статей</li>
<li class="cat-tool-item">Redirect-анализатор</li>
</ul>
</div>
<!-- Утилиты -->
<div class="cat-card reveal reveal-delay-4">
<div class="cat-icon-wrap">
<!-- Heroicons: wrench-screwdriver -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
<path d="M11.42 15.17 17.25 21A2.652 2.652 0 0 0 21 17.25l-5.877-5.877"/>
<path d="M11.42 15.17l-2.496-2.496a3.5 3.5 0 0 1-4.95-4.95l2.496 2.496"/>
<path d="m6.496 10.22 4.258-4.257a3.5 3.5 0 0 1 4.95 4.95l-4.258 4.257"/>
</svg>
</div>
<div>
<div class="cat-header">
<span class="cat-title">Утилиты</span>
<span class="cat-badge">2 инструмента</span>
</div>
</div>
<p class="cat-desc">Генератор паролей и Markdown-просмотрщик с превью</p>
<ul class="cat-tools">
<li class="cat-tool-item">Генератор паролей</li>
<li class="cat-tool-item">Markdown Viewer</li>
</ul>
</div>
</div>
</div>
</section>
<!-- ════════════════════════════════════════════
ADVANTAGES
════════════════════════════════════════════ -->
<section class="adv-section">
<div style="max-width:1120px;margin:0 auto;">
<div class="adv-grid">
<div class="adv-card reveal">
<div class="adv-icon-wrap">
<!-- Heroicons: gift -->
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 12v10H4V12"/>
<path d="M22 7H2v5h20V7z"/>
<path d="M12 22V7"/>
<path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/>
<path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/>
</svg>
</div>
<div class="adv-title">Бесплатно навсегда</div>
<p class="adv-desc">Никаких подписок и скрытых платежей. Все 13 инструментов доступны сразу после регистрации.</p>
</div>
<div class="adv-card reveal reveal-delay-1">
<div class="adv-icon-wrap">
<!-- Heroicons: computer-desktop -->
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
<rect x="2" y="3" width="20" height="14" rx="2"/>
<path d="M8 21h8M12 17v4"/>
</svg>
</div>
<div class="adv-title">В браузере</div>
<p class="adv-desc">Ничего устанавливать не нужно. Работает на любом устройстве с современным браузером.</p>
</div>
<div class="adv-card reveal reveal-delay-2">
<div class="adv-icon-wrap">
<!-- Heroicons: shield-check -->
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
<path d="m9 12 2 2 4-4"/>
</svg>
</div>
<div class="adv-title">Безопасно</div>
<p class="adv-desc">Ваши файлы обрабатываются локально или транзитно и не сохраняются на нашем сервере.</p>
</div>
<div class="adv-card reveal reveal-delay-3">
<div class="adv-icon-wrap">
<!-- Heroicons: bolt -->
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>
</svg>
</div>
<div class="adv-title">Быстро</div>
<p class="adv-desc">Лёгкий интерфейс, мгновенная обработка без очередей и ожидания серверного ответа.</p>
</div>
</div>
</div>
</section>
<!-- ════════════════════════════════════════════
FINAL CTA
════════════════════════════════════════════ -->
<section class="cta-section">
<div class="cta-glow reveal">
<p class="section-label" style="margin-bottom:16px;">Начните прямо сейчас</p>
<h2 class="cta-headline">Готовы начать?</h2>
<p class="cta-sub">
Зарегистрируйтесь бесплатно и получите доступ ко всем инструментам — без кредитной карты.
</p>
<a href="/auth/register" class="btn-primary" style="font-size:17px;padding:17px 40px;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<line x1="19" y1="8" x2="19" y2="14"/>
<line x1="22" y1="11" x2="16" y2="11"/>
</svg>
Создать аккаунт
</a>
</div>
</section>
<!-- ════════════════════════════════════════════
FOOTER
════════════════════════════════════════════ -->
<footer class="landing-footer">
<span class="footer-copy">&copy; 2024&ndash;2026 WA Dev Tools</span>
<nav class="footer-links">
<a href="/auth/login" class="footer-link">Войти</a>
<a href="/auth/register" class="footer-link">Регистрация</a>
</nav>
</footer>
<script>
/* ── Sticky nav ── */
const nav = document.getElementById('mainNav');
const onScroll = () => {
nav.classList.toggle('scrolled', window.scrollY > 40);
};
window.addEventListener('scroll', onScroll, { passive: true });
/* ── Intersection observer for reveal animations ── */
const revealEls = document.querySelectorAll('.reveal');
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' });
revealEls.forEach((el) => observer.observe(el));
} else {
// Fallback for old browsers
revealEls.forEach((el) => el.classList.add('visible'));
}
</script>
</body>
</html>