Files
web-petting/templates/landing.html
T

501 lines
22 KiB
HTML
Raw Normal View History

2026-04-29 17:49:07 +03:00
<!DOCTYPE html>
<html lang="{{ lang.code() }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="{{ t.landing_meta_description }}">
<title>{{ t.nav_title }} — {{ t.landing_hero_title }}</title>
<!-- Open Graph -->
<meta property="og:title" content="{{ t.nav_title }} — {{ t.landing_hero_title }}">
<meta property="og:description" content="{{ t.landing_meta_description }}">
<meta property="og:type" content="website">
<!-- Structured Data -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "{{ t.nav_title }}",
"description": "{{ t.landing_meta_description }}",
"serviceType": "Pet Sitting",
"@id": "#business"
}
</script>
<style>
/* ── Reset & Base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
color: #2d2b55; line-height: 1.6; overflow-x: hidden;
background: linear-gradient(160deg, #e8e4ff 0%, #fce4ec 25%, #fff3e0 50%, #e0f7fa 75%, #ede7f6 100%);
background-attachment: fixed;
}
a { color: inherit; }
/* ── Floating SVG background ── */
.bg-deco {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
pointer-events: none; z-index: 0; overflow: hidden;
}
.bg-deco svg {
position: absolute; opacity: 0.22;
will-change: transform;
}
/* ── Header ── */
.site-header {
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
background: rgba(255,255,255,0.6); backdrop-filter: blur(16px);
border-bottom: 1px solid rgba(180,170,220,0.2);
}
.header-inner {
max-width: 1100px; margin: 0 auto; padding: 0.8rem 1.5rem;
display: flex; justify-content: space-between; align-items: center;
}
.logo { font-size: 1.25rem; font-weight: 700; text-decoration: none; color: #2d2b55; }
.header-secret { flex: 1; align-self: stretch; margin: 0 0.75rem; }
.header-right { display: flex; align-items: center; gap: 1.25rem; }
.header-right a { text-decoration: none; font-size: 0.9rem; color: #666; transition: color 0.2s; }
.header-right a:hover { color: #2d2b55; }
.header-cta {
display: inline-block; padding: 0.45rem 1.1rem; border-radius: 8px;
background: linear-gradient(135deg, #7c6cff, #b06cff); color: #fff !important;
font-weight: 600; font-size: 0.9rem; text-decoration: none;
transition: transform 0.2s, box-shadow 0.2s;
}
.header-cta:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(124,108,255,0.35); }
/* ── Content z-index above bg ── */
.site-header, .hero, .section, .form-section, .site-footer {
position: relative; z-index: 1;
}
/* ── Hero ── */
.hero {
padding: 8rem 1.5rem 4.5rem;
text-align: center;
background: radial-gradient(ellipse at 50% 0%, rgba(255,255,255,0.6) 0%, transparent 70%);
}
.hero h1 {
font-size: clamp(2rem, 5vw, 3.2rem); font-weight: 800;
line-height: 1.2; max-width: 750px; margin: 0 auto 1.25rem;
color: #2d2b55;
}
.hero p {
font-size: clamp(1.05rem, 2.5vw, 1.25rem);
color: #5a5680; max-width: 640px; margin: 0 auto 2rem;
}
.hero-cta {
display: inline-block; padding: 0.9rem 2.5rem; border-radius: 14px;
background: linear-gradient(135deg, #7c6cff, #b06cff);
color: #fff; font-size: 1.1rem; font-weight: 700;
text-decoration: none; transition: transform 0.2s, box-shadow 0.2s;
box-shadow: 0 4px 20px rgba(124,108,255,0.35);
}
.hero-cta:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(124,108,255,0.45); }
.hero-emoji { font-size: 4rem; margin-bottom: 1rem; display: block; }
2026-05-11 11:34:11 +01:00
.hero-desc {
font-size: clamp(0.9rem, 2vw, 1.05rem);
color: #7a7599; max-width: 640px; margin: 0 auto 2rem;
line-height: 1.7;
}
.guarantee {
text-align: center; padding: 2rem 1.5rem;
font-size: 1.1rem; font-weight: 600; color: #2d2b55;
font-style: italic;
}
/* ── Testimonials ── */
.testimonials-grid {
display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.testimonial-card {
background: rgba(255,255,255,0.55); backdrop-filter: blur(10px);
border-radius: 18px; padding: 1.75rem;
border: 1px solid rgba(180,170,220,0.2);
transition: transform 0.2s, box-shadow 0.2s;
}
.testimonial-card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 30px rgba(124,108,255,0.1);
}
.testimonial-text {
font-size: 0.95rem; line-height: 1.7; color: #5a5680;
font-style: italic; margin-bottom: 1rem;
}
.testimonial-text::before { content: "\201C"; font-size: 1.5rem; color: #b06cff; margin-right: 0.2rem; }
.testimonial-text::after { content: "\201D"; font-size: 1.5rem; color: #b06cff; margin-left: 0.2rem; }
.testimonial-footer {
display: flex; align-items: center; gap: 0.75rem;
}
.testimonial-avatar {
width: 44px; height: 44px; border-radius: 50%; object-fit: cover;
border: 2px solid rgba(180,170,220,0.3);
}
.testimonial-note {
font-size: 0.85rem; color: #7a7599; font-weight: 600;
}
/* ── Pricing ── */
.pricing-block {
max-width: 600px; margin: 0 auto;
background: rgba(255,255,255,0.55); backdrop-filter: blur(10px);
border-radius: 18px; padding: 2rem 2.5rem;
border: 1px solid rgba(180,170,220,0.2);
text-align: center;
}
.pricing-text {
font-size: clamp(1.1rem, 2.5vw, 1.3rem);
color: #2d2b55; font-weight: 700; line-height: 1.7;
white-space: pre-line;
}
2026-04-29 17:49:07 +03:00
/* ── Section common ── */
.section { padding: 5rem 1.5rem; background: transparent; }
.section-inner { max-width: 1100px; margin: 0 auto; }
.section-title {
text-align: center; font-size: clamp(1.6rem, 3.5vw, 2.2rem);
font-weight: 800; margin-bottom: 3rem; color: #2d2b55;
}
.section-alt {
background: rgba(255,255,255,0.3); backdrop-filter: blur(4px);
border-top: 1px solid rgba(180,170,220,0.15);
border-bottom: 1px solid rgba(180,170,220,0.15);
}
/* ── Services grid ── */
.services-grid {
display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
}
.service-card {
background: rgba(255,255,255,0.55); backdrop-filter: blur(10px);
border-radius: 18px; padding: 2rem 1.75rem;
border: 1px solid rgba(180,170,220,0.2);
transition: transform 0.2s, box-shadow 0.2s;
}
.service-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 36px rgba(124,108,255,0.12);
}
.service-icon { font-size: 2.5rem; margin-bottom: 0.75rem; display: block; }
.service-card h3 { font-size: 1.2rem; font-weight: 700; margin-bottom: 0.5rem; color: #2d2b55; }
.service-card p { color: #5a5680; font-size: 0.95rem; line-height: 1.6; }
/* ── Steps ── */
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 2rem; }
.step { text-align: center; padding: 1.5rem; }
.step-num {
width: 3.5rem; height: 3.5rem; border-radius: 50%;
background: linear-gradient(135deg, #7c6cff, #b06cff);
color: #fff; font-size: 1.4rem; font-weight: 800;
display: inline-flex; align-items: center; justify-content: center;
margin-bottom: 1rem; box-shadow: 0 4px 14px rgba(124,108,255,0.3);
}
.step h3 { font-size: 1.1rem; font-weight: 700; margin-bottom: 0.4rem; color: #2d2b55; }
.step p { color: #5a5680; font-size: 0.95rem; }
/* ── Form section ── */
.form-section {
padding: 5rem 1.5rem;
background: radial-gradient(ellipse at 50% 100%, rgba(255,255,255,0.5) 0%, transparent 70%);
}
.form-wrapper {
max-width: 540px; margin: 0 auto;
background: rgba(255,255,255,0.6); backdrop-filter: blur(14px);
border-radius: 22px; padding: 2.5rem 2rem;
box-shadow: 0 8px 40px rgba(124,108,255,0.12);
border: 1px solid rgba(180,170,220,0.25);
}
.form-wrapper h2 {
text-align: center; font-size: 1.6rem; font-weight: 800;
margin-bottom: 0.4rem; color: #2d2b55;
}
.form-wrapper .form-sub {
text-align: center; color: #7a7599; margin-bottom: 1.75rem; font-size: 0.95rem;
}
.form-field { margin-bottom: 1.25rem; }
.form-field label {
display: block; font-size: 0.85rem; font-weight: 600;
color: #4a4570; margin-bottom: 0.35rem;
}
.form-field input,
.form-field textarea {
width: 100%; padding: 0.75rem 1rem;
border: 1.5px solid rgba(180,170,220,0.35);
border-radius: 10px; font-size: 1rem; font-family: inherit;
transition: border-color 0.2s, box-shadow 0.2s;
background: rgba(255,255,255,0.65);
}
.form-field input:focus,
.form-field textarea:focus {
outline: none; border-color: #7c6cff;
box-shadow: 0 0 0 3px rgba(124,108,255,0.15);
background: rgba(255,255,255,0.85);
}
.form-field textarea { resize: vertical; min-height: 90px; }
.form-submit {
width: 100%; padding: 0.85rem; border: none; border-radius: 12px;
background: linear-gradient(135deg, #7c6cff, #b06cff);
color: #fff; font-size: 1.1rem; font-weight: 700;
cursor: pointer; transition: transform 0.2s, box-shadow 0.2s;
margin-top: 0.5rem;
box-shadow: 0 4px 16px rgba(124,108,255,0.3);
}
.form-submit:hover { transform: translateY(-1px); box-shadow: 0 6px 24px rgba(124,108,255,0.4); }
/* ── Footer ── */
.site-footer {
text-align: center; padding: 2rem 1.5rem;
color: #8a85a8; font-size: 0.85rem;
border-top: 1px solid rgba(180,170,220,0.15);
background: rgba(255,255,255,0.3);
}
/* ── Mobile ── */
@media (max-width: 600px) {
.hero { padding: 6.5rem 1rem 3rem; }
.section { padding: 3rem 1rem; }
.form-section { padding: 3rem 1rem; }
.form-wrapper { padding: 1.75rem 1.25rem; }
.header-cta { display: none; }
.bg-deco svg { opacity: 0.15; }
}
</style>
</head>
<body>
<!-- Floating decorative SVG background -->
<div class="bg-deco" id="bgDeco" aria-hidden="true"></div>
<!-- Header -->
<header class="site-header">
<div class="header-inner">
<a href="/?lang={{ lang.code() }}" class="logo">🐾 {{ t.nav_title }}</a>
<a href="/admin" class="header-secret" aria-hidden="true"></a>
<div class="header-right">
<a href="?lang={{ lang.other().code() }}">{{ lang.other().label() }}</a>
<a href="#form" class="header-cta">{{ t.landing_hero_cta }}</a>
</div>
</div>
</header>
<!-- Hero -->
<section class="hero">
2026-05-11 11:34:11 +01:00
<span class="hero-emoji" role="img" aria-label="pets">🐱🐹🦎</span>
2026-04-29 17:49:07 +03:00
<h1>{{ t.landing_hero_title }}</h1>
<p>{{ t.landing_hero_subtitle }}</p>
2026-05-11 11:34:11 +01:00
<p class="hero-desc">{{ t.landing_hero_description }}</p>
2026-04-29 17:49:07 +03:00
<a href="#form" class="hero-cta">{{ t.landing_hero_cta }}</a>
</section>
<!-- Services -->
<section class="section section-alt" id="services">
<div class="section-inner">
<h2 class="section-title">{{ t.landing_services_title }}</h2>
<div class="services-grid">
<article class="service-card">
<span class="service-icon" role="img" aria-label="cat">🐱</span>
<h3>{{ t.landing_service_cats_title }}</h3>
<p>{{ t.landing_service_cats_text }}</p>
</article>
<article class="service-card">
2026-05-11 11:34:11 +01:00
<span class="service-icon" role="img" aria-label="rodents and reptiles">🐹🦎</span>
<h3>{{ t.landing_service_exotic_title }}</h3>
<p>{{ t.landing_service_exotic_text }}</p>
2026-04-29 17:49:07 +03:00
</article>
<article class="service-card">
2026-05-11 11:34:11 +01:00
<span class="service-icon" role="img" aria-label="plants and fish">🌿🐟</span>
<h3>{{ t.landing_service_bonus_title }}</h3>
<p>{{ t.landing_service_bonus_text }}</p>
2026-04-29 17:49:07 +03:00
</article>
</div>
</div>
</section>
2026-05-11 11:34:11 +01:00
<!-- Pricing -->
{% if !pricing_info.is_empty() %}
<section class="section" id="pricing">
<div class="section-inner">
<h2 class="section-title">{{ t.landing_pricing_title }}</h2>
<div class="pricing-block">
<p class="pricing-text">{{ pricing_info }}</p>
</div>
</div>
</section>
{% endif %}
2026-04-29 17:49:07 +03:00
<!-- How it works -->
<section class="section" id="how">
<div class="section-inner">
<h2 class="section-title">{{ t.landing_how_title }}</h2>
<div class="steps">
<div class="step">
<span class="step-num">1</span>
<h3>{{ t.landing_how_step1_title }}</h3>
<p>{{ t.landing_how_step1_text }}</p>
</div>
<div class="step">
<span class="step-num">2</span>
<h3>{{ t.landing_how_step2_title }}</h3>
<p>{{ t.landing_how_step2_text }}</p>
</div>
<div class="step">
<span class="step-num">3</span>
<h3>{{ t.landing_how_step3_title }}</h3>
<p>{{ t.landing_how_step3_text }}</p>
</div>
</div>
</div>
</section>
2026-05-11 11:34:11 +01:00
<!-- Testimonials -->
{% if !testimonials.is_empty() %}
<section class="section section-alt" id="testimonials">
<div class="section-inner">
<h2 class="section-title">{{ t.landing_testimonials_title }}</h2>
<div class="testimonials-grid">
{% for item in &testimonials %}
<article class="testimonial-card">
<div class="testimonial-text">{{ item.text }}</div>
{% if item.image_path.is_some() || item.author_note.is_some() %}
<div class="testimonial-footer">
{% if item.image_path.is_some() %}
<img class="testimonial-avatar" src="/testimonial-image/{{ item.id.unwrap() }}" alt="">
{% endif %}
{% if let Some(note) = item.author_note.as_deref() %}
<span class="testimonial-note">{{ note }}</span>
{% endif %}
</div>
{% endif %}
</article>
{% endfor %}
</div>
</div>
</section>
{% endif %}
<!-- Guarantee -->
<div class="guarantee" style="position:relative;z-index:1;">
<p>{{ t.landing_guarantee }}</p>
</div>
2026-04-29 17:49:07 +03:00
<!-- Lead Form -->
<section class="form-section" id="form">
<div class="form-wrapper">
<h2>{{ t.landing_form_title }}</h2>
<p class="form-sub">{{ t.landing_form_subtitle }}</p>
<form method="post" action="/submit">
<div class="form-field">
<label for="name">{{ t.landing_form_name }}</label>
<input type="text" id="name" name="name" required autocomplete="name">
</div>
<div class="form-field">
<label for="phone">{{ t.landing_form_phone }}</label>
<input type="tel" id="phone" name="phone" autocomplete="tel">
</div>
<div class="form-field">
<label for="comment">{{ t.landing_form_comment }}</label>
<textarea id="comment" name="comment" placeholder="{{ t.landing_form_comment_placeholder }}"></textarea>
</div>
<button type="submit" class="form-submit">{{ t.landing_form_submit }}</button>
</form>
{% if !contact_info.is_empty() %}
<div style="text-align:center;margin-top:1.5rem;padding-top:1.25rem;border-top:1px solid rgba(180,170,220,0.25);">
<p style="color:#7a7599;font-size:0.9rem;margin-bottom:0.4rem;">{{ t.landing_contact_label }}</p>
<p style="font-size:1.1rem;font-weight:600;color:#2d2b55;">{{ contact_info }}</p>
</div>
{% endif %}
</div>
</section>
<!-- Footer -->
<footer class="site-footer">
<p>{{ t.landing_footer_text }}</p>
</footer>
<script>
(function() {
var icons = [
// Cat face
'<svg viewBox="0 0 80 80" width="W" height="W"><path d="M20 15 L10 2 L18 18 M60 15 L70 2 L62 18 M40 70 C18 70 8 52 8 38 C8 20 22 8 40 8 C58 8 72 20 72 38 C72 52 62 70 40 70Z" fill="none" stroke="C" stroke-width="3" stroke-linecap="round"/><circle cx="28" cy="36" r="3.5" fill="C"/><circle cx="52" cy="36" r="3.5" fill="C"/><ellipse cx="40" cy="48" rx="4" ry="2.5" fill="C"/><path d="M36 48 Q32 54 28 52 M44 48 Q48 54 52 52" fill="none" stroke="C" stroke-width="2" stroke-linecap="round"/></svg>',
2026-05-11 11:34:11 +01:00
// Leaf
'<svg viewBox="0 0 60 70" width="W2" height="W"><path d="M30 65 C30 65 10 45 10 25 C10 10 25 2 30 2 C35 2 50 10 50 25 C50 45 30 65 30 65Z" fill="C" opacity="0.3"/><path d="M30 60 L30 20 M30 35 Q20 30 15 25 M30 45 Q40 40 45 35" fill="none" stroke="C" stroke-width="2" stroke-linecap="round"/></svg>',
2026-04-29 17:49:07 +03:00
// Bowl
'<svg viewBox="0 0 80 50" width="W" height="H2"><path d="M8 18 Q8 46 40 46 Q72 46 72 18 Z" fill="C" opacity="0.2"/><ellipse cx="40" cy="18" rx="34" ry="10" fill="none" stroke="C" stroke-width="3"/><path d="M8 18 Q8 46 40 46 Q72 46 72 18" fill="none" stroke="C" stroke-width="3" stroke-linejoin="round"/></svg>',
// Paw print
'<svg viewBox="0 0 60 70" width="W2" height="W"><ellipse cx="30" cy="46" rx="16" ry="18" fill="C" opacity="0.55"/><ellipse cx="14" cy="22" rx="8" ry="10" fill="C" opacity="0.55" transform="rotate(-10 14 22)"/><ellipse cx="46" cy="22" rx="8" ry="10" fill="C" opacity="0.55" transform="rotate(10 46 22)"/><ellipse cx="24" cy="8" rx="6" ry="8" fill="C" opacity="0.55" transform="rotate(-5 24 8)"/><ellipse cx="38" cy="8" rx="6" ry="8" fill="C" opacity="0.55" transform="rotate(5 38 8)"/></svg>',
// Fish
'<svg viewBox="0 0 80 40" width="W" height="H"><path d="M60 20 Q48 2 28 8 Q10 14 10 20 Q10 26 28 32 Q48 38 60 20Z" fill="C" opacity="0.25"/><path d="M60 20 Q48 2 28 8 Q10 14 10 20 Q10 26 28 32 Q48 38 60 20Z" fill="none" stroke="C" stroke-width="2.5"/><path d="M60 20 L74 6 L74 34 Z" fill="C" opacity="0.25" stroke="C" stroke-width="2.5" stroke-linejoin="round"/><circle cx="24" cy="18" r="2.5" fill="C"/></svg>',
// Heart
'<svg viewBox="0 0 60 55" width="W2" height="W2"><path d="M30 50 C10 35 0 22 0 14 C0 5 7 0 15 0 C21 0 26 3 30 9 C34 3 39 0 45 0 C53 0 60 5 60 14 C60 22 50 35 30 50Z" fill="C" opacity="0.5"/></svg>',
// Mouse toy
'<svg viewBox="0 0 70 50" width="W" height="H2"><ellipse cx="32" cy="28" rx="22" ry="16" fill="C" opacity="0.2"/><ellipse cx="32" cy="28" rx="22" ry="16" fill="none" stroke="C" stroke-width="2.5"/><path d="M12 22 Q2 10 10 6 M12 34 Q2 40 6 46" fill="none" stroke="C" stroke-width="2.5" stroke-linecap="round"/><circle cx="22" cy="24" r="2" fill="C"/><path d="M54 28 Q68 18 64 32 Q60 40 56 30" fill="none" stroke="C" stroke-width="2.5" stroke-linecap="round"/></svg>'
];
var colors = ['#7c6cff','#ff5287','#ff8c26','#00c9a7','#b06cff','#ff6eb4','#22c993','#4da6ff','#ffb340','#ff6b6b'];
var container = document.getElementById('bgDeco');
if (!container) return;
var count = Math.min(30, Math.floor(window.innerWidth / 50));
var items = [];
var seed = 42;
function rng() { seed = (seed * 16807 + 0) % 2147483647; return seed / 2147483647; }
for (var i = 0; i < count; i++) {
var iconIdx = Math.floor(rng() * icons.length);
var color = colors[Math.floor(rng() * colors.length)];
var size = 44 + Math.floor(rng() * 56);
var x = rng() * 100;
var y = rng() * 100;
var rotation = Math.floor(rng() * 360);
var speed = 0.15 + rng() * 0.35;
var rotSpeed = (rng() - 0.5) * 0.04;
var svg = icons[iconIdx]
.replace(/W2/g, String(Math.round(size * 0.75)))
.replace(/H2/g, String(Math.round(size * 0.6)))
.replace(/W/g, String(size))
.replace(/H/g, String(Math.round(size * 0.5)))
.replace(/C/g, color);
var wrapper = document.createElement('div');
wrapper.innerHTML = svg;
var el = wrapper.firstChild;
el.style.left = x + '%';
el.style.top = y + '%';
el.style.transform = 'rotate(' + rotation + 'deg)';
container.appendChild(el);
items.push({ el: el, baseY: y, rotation: rotation, speed: speed, rotSpeed: rotSpeed });
}
var ticking = false;
function onScroll() {
if (ticking) return;
ticking = true;
requestAnimationFrame(function() {
var scrollY = window.pageYOffset || document.documentElement.scrollTop;
for (var i = 0; i < items.length; i++) {
var it = items[i];
var offsetY = scrollY * it.speed;
var rot = it.rotation + scrollY * it.rotSpeed;
it.el.style.transform = 'translateY(' + (-offsetY) + 'px) rotate(' + rot + 'deg)';
}
ticking = false;
});
}
window.addEventListener('scroll', onScroll, { passive: true });
})();
</script>
</body>
</html>