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

467 lines
No EOL
16 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.

---
interface FaqItem {
question: string;
answer: string;
}
const {
sectionSubtitle = "ОТВЕТЫ НА ВОПРОСЫ",
sectionTitle = "Часто задаваемые вопросы",
faqItems = [
{
question: "Сколько стоит первичная консультация?",
answer: "Первичная консультация проводится бесплатно. Мы оценим вашу ситуацию, расскажем о перспективах дела и предложим оптимальную стратегию защиты. Это ни к чему вас не обязывает."
},
{
question: "Какие документы нужны для начала работы?",
answer: "Для анализа ситуации потребуются: протокол об административном правонарушении, постановление по делу, материалы ДТП (если есть), страховой полис ОСАГО/КАСКО, а также любые другие документы, относящиеся к вашему делу."
},
{
question: "Каковы шансы на успех моего дела?",
answer: "После изучения документов мы честно расскажем о реальных перспективах. По статистике, около 98% дел завершаются успешно. Если видим, что шансов нет — так и скажем, чтобы вы не тратили время и деньги."
},
{
question: "Сколько времени занимает рассмотрение дела?",
answer: "Сроки зависят от сложности: простые консультации и составление жалоб — 1-3 дня, представление интересов в суде — от 2 недель до 2 месяцев. Точные сроки назовем после анализа вашей ситуации."
},
{
question: "Работаете ли вы с делами, где уже вынесено решение?",
answer: "Да, мы помогаем обжаловать постановления и решения судов. Срок на обжалование обычно составляет 10 дней с момента вынесения постановления, но есть возможности восстановления срока и в более поздний период."
},
{
question: "Можно ли решить вопрос без суда?",
answer: "Во многих случаях — да. Мы ведём переговоры со страховыми компаниями, ГИБДД, автосалонами и другими участниками. Досудебное урегулирование часто быстрее и выгоднее для клиента."
}
] as FaqItem[]
} = Astro.props;
---
<section class="faq-section" id="faq">
<!-- КРИТИЧНО: Инлайн-скрипт скрывает элементы ДО рендера, но только если JS работает -->
<script is:inline>
(function() {
// Проверяем prefers-reduced-motion
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
// Создаем стиль немедленно, чтобы избежать мигания (FOUC)
const style = document.createElement('style');
style.textContent = '.animate-on-scroll{opacity:0;transform:translateY(30px)}';
document.head.appendChild(style);
})();
</script>
<div class="site-container">
<!-- Заголовок секции -->
<div class="section-header">
<div class="subtitle-wrapper animate-on-scroll" data-animation="fade-up">
<div class="subtitle-line"></div>
<span class="subtitle">{sectionSubtitle}</span>
<div class="subtitle-line"></div>
</div>
<h2 class="title animate-on-scroll" data-animation="fade-up" data-delay="100">{sectionTitle}</h2>
<p class="section-description animate-on-scroll" data-animation="fade-up" data-delay="150">
Собрали ответы на самые частые вопросы наших клиентов. Не нашли ответ? Позвоните — проконсультируем бесплатно
</p>
</div>
<!-- Аккордеон FAQ -->
<div class="faq-container">
{faqItems.map((item: FaqItem, index: number) => (
<div class="faq-item animate-on-scroll" data-animation="fade-up" data-delay={index * 80 + 200}>
<button class="faq-question" aria-expanded="false" data-faq-toggle>
<span class="question-text">{item.question}</span>
<span class="faq-icon">
<svg class="icon-plus" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 5V19M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</span>
</button>
<div class="faq-answer" data-faq-content>
<div class="answer-inner">
<p class="answer-text">{item.answer}</p>
</div>
</div>
</div>
))}
</div>
</div>
</section>
<style>
:root {
--color-primary: #0a2540;
--color-primary-light: #1e3050;
--color-accent: #eac26e;
--color-accent-dark: #ce9f40;
--color-accent-glow: rgba(234, 194, 110, 0.3);
--color-light: #ffffff;
--color-gray: #94a3b8;
--color-gray-dark: #64748b;
--gradient-bg: linear-gradient(135deg, #0a2540 0%, #1e3050 100%);
--gradient-accent: linear-gradient(135deg, #eac26e 0%, #ce9f40 100%);
--shadow-sm: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--shadow-md: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
--shadow-glow: 0 0 40px rgba(234, 194, 110, 0.2);
}
.faq-section {
padding: 6rem 1.5rem;
background: var(--gradient-bg);
position: relative;
overflow: hidden;
font-family: 'Inter', system-ui, -apple-system, sans-serif;
}
.faq-section::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 80%;
height: 150%;
background: radial-gradient(circle, rgba(234, 194, 110, 0.03) 0%, transparent 70%);
pointer-events: none;
border-radius: 50%;
}
.faq-section::after {
content: '';
position: absolute;
bottom: -30%;
left: -10%;
width: 60%;
height: 100%;
background: radial-gradient(circle, rgba(234, 194, 110, 0.02) 0%, transparent 70%);
pointer-events: none;
}
.site-container {
max-width: var(--site-max-width, 1400px);
margin: 0 auto;
position: relative;
z-index: 2;
}
/* Заголовок секции */
.section-header {
margin-bottom: 4rem;
text-align: center;
}
.subtitle-wrapper {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin-bottom: 1rem;
}
.subtitle-line {
width: 40px;
height: 1px;
background: linear-gradient(90deg, transparent, var(--color-accent), transparent);
}
.subtitle {
color: var(--color-accent);
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 4px;
}
.title {
color: var(--color-light);
font-size: clamp(2rem, 4vw, 3.5rem);
font-weight: 800;
margin: 0 0 1rem 0;
line-height: 1.2;
letter-spacing: -0.02em;
background: linear-gradient(135deg, #ffffff 0%, #e2e8f0 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.section-description {
color: var(--color-gray);
font-size: 1.1rem;
max-width: 700px;
margin: 0 auto;
line-height: 1.6;
}
/*
ИСПРАВЛЕНИЕ LCP:
opacity: 1 по умолчанию!
Если JS не загрузится - контент виден.
Если JS загрузится - инлайн-скрипт выше добавит opacity:0 и анимация сработает.
*/
.animate-on-scroll {
opacity: 1;
transform: translateY(0);
will-change: opacity, transform;
transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Класс is-visible добавляется через JS при появлении в viewport */
.animate-on-scroll.is-visible {
opacity: 1;
transform: translateY(0);
}
/* Контейнер FAQ */
.faq-container {
max-width: 900px;
margin: 0 auto 4rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
/* Элемент FAQ */
.faq-item {
background: rgba(255, 255, 255, 0.03);
backdrop-filter: blur(10px);
border-radius: 16px;
border: 1px solid rgba(255, 255, 255, 0.05);
overflow: hidden;
transition: border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1),
background 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.faq-item:hover {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(234, 194, 110, 0.2);
}
.faq-item.active {
border-color: rgba(234, 194, 110, 0.3);
box-shadow: var(--shadow-glow);
}
/* Вопрос */
.faq-question {
width: 100%;
padding: 1.5rem 2rem;
background: transparent;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1.5rem;
transition: background 0.3s ease;
}
.faq-question:hover {
background: rgba(234, 194, 110, 0.05);
}
.question-text {
color: var(--color-light);
font-size: 1.125rem;
font-weight: 600;
text-align: left;
line-height: 1.4;
flex: 1;
}
.faq-icon {
flex-shrink: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
color: var(--color-accent);
transition: transform 0.3s ease, color 0.3s ease;
}
.faq-item.active .faq-icon {
transform: rotate(45deg);
color: var(--color-light);
}
.icon-plus {
width: 100%;
height: 100%;
}
.faq-answer {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.faq-answer.open {
grid-template-rows: 1fr;
}
.answer-inner {
overflow: hidden;
}
.answer-text {
padding: 0 2rem 1.5rem;
color: var(--color-gray);
font-size: 1rem;
line-height: 1.7;
margin: 0;
}
/* Адаптивность */
@media (max-width: 1024px) {
.faq-container {
gap: 1rem;
}
.faq-question {
padding: 1.25rem 1.5rem;
}
.answer-text {
padding: 0 1.5rem 1.25rem;
}
}
@media (max-width: 768px) {
.faq-section {
padding: 4rem 1rem;
}
.section-header {
margin-bottom: 2rem;
}
.subtitle-wrapper {
gap: 0.5rem;
}
.subtitle-line {
width: 30px;
}
.section-description {
font-size: 1rem;
}
.question-text {
font-size: 1rem;
}
.faq-question {
padding: 1rem 1.25rem;
gap: 1rem;
}
.faq-icon {
width: 28px;
height: 28px;
}
.answer-text {
padding: 0 1.25rem 1rem;
font-size: 0.95rem;
}
}
/* Уважаем prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
.animate-on-scroll {
opacity: 1 !important;
transform: none !important;
transition: none !important;
}
.faq-item,
.faq-question,
.faq-answer,
.faq-icon {
transition: none;
}
.faq-answer {
transition: none;
grid-template-rows: none;
}
.faq-answer.open {
grid-template-rows: none;
}
}
</style>
<script>
// Intersection Observer для анимаций при скроллинге
const observerOptions = {
root: null,
rootMargin: '50px', // Немного раньше начинаем анимацию
threshold: 0.1
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target as HTMLElement;
const delay = parseInt(el.dataset.delay || '0');
// Используем requestAnimationFrame для плавности
setTimeout(() => {
requestAnimationFrame(() => {
el.classList.add('is-visible');
});
}, delay);
observer.unobserve(el);
}
});
}, observerOptions);
// Инициализация после загрузки DOM
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.animate-on-scroll').forEach((el) => {
observer.observe(el);
});
});
} else {
document.querySelectorAll('.animate-on-scroll').forEach((el) => {
observer.observe(el);
});
}
// Аккордеон FAQ - улучшенная версия
document.querySelectorAll('[data-faq-toggle]').forEach((button) => {
button.addEventListener('click', () => {
const faqItem = button.closest('.faq-item');
const answer = faqItem?.querySelector('[data-faq-content]');
const isExpanded = button.getAttribute('aria-expanded') === 'true';
if (isExpanded) {
faqItem?.classList.remove('active');
button.setAttribute('aria-expanded', 'false');
answer?.classList.remove('open');
return;
}
document.querySelectorAll('.faq-item.active').forEach((item) => {
if (item !== faqItem) {
item.classList.remove('active');
const otherButton = item.querySelector('[data-faq-toggle]');
const otherAnswer = item.querySelector('[data-faq-content]');
if (otherButton) otherButton.setAttribute('aria-expanded', 'false');
if (otherAnswer) otherAnswer.classList.remove('open');
}
});
faqItem?.classList.add('active');
button.setAttribute('aria-expanded', 'true');
answer?.classList.add('open');
});
});
</script>