astro_avtourist/frontend/src/components/home/WhyUs.astro

485 lines
No EOL
12 KiB
Text
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.

---
const sectionData = {
subtitle: "Почему мы?",
title: "Локальная экспертиза в Сургуте",
floatingText:
"Знаем специфику судов Сургута и регламенты местной полиции изнутри.",
imageUrl:
"/images/home/dogovor.avif",
};
const features = [
{
title: "Местный опыт",
desc: "Мы работаем только в Сургуте и ХМАО. Это позволяет нам знать практику каждого судьи и особенности работы местных отделов ГИБДД.",
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>`,
},
{
title: "92% Успешных дел",
desc: "Высокий процент выигранных дел по возврату прав и страховым спорам. Работаем на результат, а не на процесс.",
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path><path d="m9 12 2 2 4-4"></path></svg>`,
},
{
title: "Срочный выезд",
desc: "Оперативно выезжаем на место ДТП или задержания в любой район города для фиксации нарушений.",
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path><path d="M12 7v5l4 2"></path></svg>`,
},
];
---
<!-- КРИТИЧНО: Инлайн-скрипт скрывает элементы ДО рендера, но только если JS работает -->
<script is:inline>
(function() {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const style = document.createElement('style');
style.textContent = '.animate-on-scroll{opacity:0}' +
'[data-animation="fade-in"]{opacity:0}' +
'[data-animation="fade-up"]{opacity:0;transform:translateY(30px)}' +
'[data-animation="slide-up"]{opacity:0;transform:translateY(40px)}' +
'[data-animation="slide-right"]{opacity:0;transform:translateX(-40px)}' +
'[data-animation="scale-in"]{opacity:0;transform:scale(0.95)}' +
'[data-animation="stagger-item"]{opacity:0;transform:translateX(-30px)}';
document.head.appendChild(style);
})();
</script>
<section class="why-us-section" id="why-us">
<div class="site-container">
<!-- Левая колонка: Изображение -->
<div class="image-column">
<div class="image-wrapper animate-on-scroll" data-animation="scale-in">
<img
src={sectionData.imageUrl}
alt="Юридическая практика"
class="main-image"
loading="lazy"
width="440"
height="340"
/>
<!-- Плавающая бежевая плашка -->
<div
class="floating-card animate-on-scroll"
data-animation="slide-up"
data-delay="300"
>
<p>{sectionData.floatingText}</p>
</div>
</div>
</div>
<!-- Правая колонка: Текст и особенности -->
<div class="content-column">
<div class="section-header">
<span class="subtitle animate-on-scroll" data-animation="fade-up"
>{sectionData.subtitle}</span
>
<h2
class="title animate-on-scroll"
data-animation="slide-right"
data-delay="100"
>
{sectionData.title}
</h2>
</div>
<div class="features-list">
{
features.map((feature, index) => (
<div
class="feature-item animate-on-scroll"
data-animation="stagger-item"
data-delay={index * 150 + 200}
>
<div class="icon-box" set:html={feature.icon} />
<div class="feature-text">
<h3 class="feature-title">{feature.title}</h3>
<p class="feature-desc">{feature.desc}</p>
</div>
</div>
))
}
</div>
</div>
</div>
</section>
<style>
/* Общие стили секции */
.why-us-section {
padding: 6rem 2rem;
background-color: #f4f6f9;
font-family:
system-ui,
-apple-system,
sans-serif;
overflow: hidden;
}
.site-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6rem;
align-items: center;
max-width: 1200px;
margin: 0 auto;
}
/* --- Базовые стили анимаций - ИСПРАВЛЕНО: opacity:1 по умолчанию --- */
.animate-on-scroll {
opacity: 1;
will-change: opacity, transform;
}
/* Fade In */
[data-animation="fade-in"] {
transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Fade Up */
[data-animation="fade-up"] {
transform: translateY(0);
transition:
opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Slide Up (снизу вверх) */
[data-animation="slide-up"] {
transform: translateY(0);
transition:
opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Slide Right (справа налево) */
[data-animation="slide-right"] {
transform: translateX(0);
transition:
opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Scale In (с увеличением) */
[data-animation="scale-in"] {
transform: scale(1);
transition:
opacity 1s cubic-bezier(0.4, 0, 0.2, 1),
transform 1s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Stagger Item (для списка) */
[data-animation="stagger-item"] {
transform: translateX(0);
transition:
opacity 0.6s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Активное состояние анимаций */
.animate-on-scroll.is-visible {
opacity: 1;
transform: translate(0) scale(1);
}
/* --- Левая колонка (Изображение) --- */
.image-column {
position: relative;
padding-bottom: 2rem;
padding-right: 2rem;
}
.image-wrapper {
position: relative;
border-radius: 12px;
overflow: visible;
}
.main-image {
width: 100%;
height: auto;
aspect-ratio: 4/4.5;
object-fit: cover;
border-radius: 12px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}
/* Бежевая плавающая плашка */
.floating-card {
position: absolute;
bottom: -30px;
right: -30px;
background-color: #fce1a8;
padding: 1.8rem;
border-radius: 6px;
max-width: 320px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
z-index: 2;
transition: box-shadow 0.5s ease 0.5s;
}
.floating-card.is-visible {
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.floating-card p {
font-family: Georgia, "Times New Roman", Times, serif;
font-size: 0.95rem;
font-weight: 700;
line-height: 1.5;
color: #1e3050;
margin: 0;
}
/* --- Правая колонка (Контент) --- */
.section-header {
margin-bottom: 3rem;
}
.subtitle {
display: inline-block;
color: #d4af37;
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 3px;
margin-bottom: 1rem;
padding: 0.5rem 1rem;
background: rgba(212, 175, 55, 0.1);
border-radius: 6px;
}
.title {
color: #1e3050;
font-size: clamp(2rem, 4vw, 3rem);
font-weight: 800;
margin: 0;
line-height: 1.2;
letter-spacing: -0.02em;
}
/* Список особенностей */
.features-list {
display: flex;
flex-direction: column;
gap: 2.5rem;
}
.feature-item {
display: flex;
gap: 1.5rem;
align-items: flex-start;
}
.icon-box {
flex-shrink: 0;
width: 46px;
height: 46px;
background-color: #122138;
color: #ffffff;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
padding: 10px;
box-shadow: 0 4px 10px rgba(18, 33, 56, 0.2);
transition:
transform 0.3s ease,
box-shadow 0.3s ease;
}
.feature-item:hover .icon-box {
transform: translateY(-2px);
box-shadow: 0 6px 15px rgba(18, 33, 56, 0.3);
}
.feature-text {
flex-grow: 1;
padding-top: 0.2rem;
}
.feature-title {
font-family: Georgia, "Times New Roman", Times, serif;
font-size: 1.2rem;
font-weight: 700;
color: #1e3050;
margin: 0 0 0.5rem 0;
transition: color 0.3s ease;
}
.feature-item:hover .feature-title {
color: #122138;
}
.feature-desc {
font-family: Georgia, "Times New Roman", Times, serif;
font-size: 0.95rem;
line-height: 1.6;
color: #6c7a8c;
margin: 0;
}
/* --- Адаптивность --- */
@media (max-width: 1024px) {
.site-container {
gap: 3rem;
}
.floating-card {
right: -10px;
max-width: 280px;
}
}
@media (max-width: 768px) {
.why-us-section {
padding: 4rem 1.5rem;
}
.site-container {
grid-template-columns: 1fr;
gap: 3rem;
}
.section-header {
text-align: center;
margin-bottom: 2.5rem;
}
.subtitle {
font-size: 0.7rem;
padding: 0.4rem 0.8rem;
}
.title {
font-size: clamp(1.5rem, 5vw, 2rem);
}
[data-animation="slide-right"] {
transform: translateY(0);
}
[data-animation="stagger-item"] {
transform: translateY(0);
}
.image-column {
padding-right: 0;
padding-bottom: 0;
}
.feature-item {
gap: 1rem;
justify-content: center;
text-align: center;
}
.feature-text {
text-align: center;
}
.feature-title {
font-size: 1.1rem;
}
.feature-desc {
font-size: 0.85rem;
}
.floating-card {
bottom: -20px;
right: 20px;
left: 20px;
max-width: none;
}
.icon-box {
width: 40px;
height: 40px;
}
}
@media (max-width: 480px) {
.why-us-section {
padding: 3rem 1rem;
}
.subtitle {
font-size: 0.65rem;
letter-spacing: 2px;
padding: 0.35rem 0.7rem;
}
.title {
font-size: 1.4rem;
}
.feature-item {
gap: 0.75rem;
}
.icon-box {
width: 36px;
height: 36px;
padding: 7px;
}
.feature-title {
font-size: 1rem;
}
.feature-desc {
font-size: 0.8rem;
line-height: 1.5;
}
.floating-card {
padding: 1.2rem;
}
.floating-card p {
font-size: 0.85rem;
}
}
/* Уважаем prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
.animate-on-scroll {
opacity: 1 !important;
transform: none !important;
transition: none !important;
}
}
</style>
<script>
// Intersection Observer для анимаций при скроллинге
const observerOptions = {
root: null,
rootMargin: "0px",
threshold: 0.15,
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const delay = (entry.target as HTMLElement).dataset.delay || "0";
setTimeout(
() => {
entry.target.classList.add("is-visible");
},
parseInt(delay as string),
);
observer.unobserve(entry.target);
}
});
}, observerOptions);
document.querySelectorAll(".animate-on-scroll").forEach((el) => {
observer.observe(el);
});
</script>