astro_avtourist/frontend/src/pages/404.astro
2026-04-11 22:20:44 +05:00

612 lines
15 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.

---
import Layout from '@layouts/Layout.astro';
import Button from '@components/base/Button.astro';
import { SITE_URL } from '@constants';
const breadcrumbs = [
{ label: 'Главная', href: '/' },
{ label: 'Страница не найдена' },
];
---
<Layout
title="Страница не найдена — 404"
description="Запрашиваемая страница не найдена. Вернитесь на главную или перейдите к услугам."
canonicalLink={`${SITE_URL}404`}
breadcrumbs={breadcrumbs}
>
<section class="not-found-section">
<!-- Анимированные фоновые элементы -->
<div class="floating-elements">
<div class="floating-shape shape-1"></div>
<div class="floating-shape shape-2"></div>
<div class="floating-shape shape-3"></div>
<div class="floating-shape shape-4"></div>
<div class="floating-shape shape-5"></div>
</div>
<div class="site-container not-found-content">
<!-- Анимированная цифра 404 -->
<div class="error-code animate-fade-in" data-delay="200">
<span class="error-digit digit-1">4</span>
<span class="error-digit digit-2">0</span>
<span class="error-digit digit-3">4</span>
</div>
<!-- Светящийся эффект -->
<div class="glow-effect"></div>
<!-- Заголовок и описание -->
<h1 class="error-title animate-fade-in" data-delay="400">
Упс! Страница <span class="text-gold">не найдена</span>
</h1>
<p class="error-description animate-fade-in" data-delay="600">
Похоже, мы свернули не на тот поворот. Запрашиваемая страница могла быть удалена,
переименована или временно недоступна. Давайте вернёмся на правильный маршрут!
</p>
<!-- Предупреждающий знак -->
<div class="warning-sign animate-fade-in" data-delay="800">
<div class="warning-triangle">
<svg viewBox="0 0 100 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M50 10L90 80H10L50 10Z" stroke="currentColor" stroke-width="3" stroke-linejoin="round"/>
<line x1="50" y1="35" x2="50" y2="55" stroke="currentColor" stroke-width="4" stroke-linecap="round"/>
<circle cx="50" cy="67" r="3" fill="currentColor"/>
</svg>
</div>
</div>
<!-- Кнопки действий -->
<div class="error-actions animate-fade-in" data-delay="1000">
<Button variant="gold" size="lg" href="/">
<span class="btn-content">
<svg class="btn-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
На главную
</span>
</Button>
<Button variant="outline" size="lg" href="/services" class="btn-services">
<span class="btn-content">
<svg class="btn-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<polyline points="12 6 12 12 16 14"></polyline>
</svg>
Наши услуги
</span>
</Button>
</div>
<!-- Дополнительная помощь -->
<div class="additional-help animate-fade-in" data-delay="1200">
<p class="help-text">Или свяжитесь с нами для консультации:</p>
<a href="tel:+79222538375" class="phone-link">
<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="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
</svg>
+7 (922) 253-83-75
</a>
</div>
</div>
</section>
</Layout>
<script>
// Анимация при загрузке страницы
document.addEventListener('DOMContentLoaded', () => {
const animatedElements = document.querySelectorAll('.animate-fade-in');
animatedElements.forEach((el) => {
const delay = parseInt((el as HTMLElement).dataset.delay || '0');
setTimeout(() => {
el.classList.add('is-visible');
}, delay);
});
});
// Для Astro View Transitions
document.addEventListener('astro:page-load', () => {
const animatedElements = document.querySelectorAll('.animate-fade-in');
animatedElements.forEach((el) => {
const delay = parseInt((el as HTMLElement).dataset.delay || '0');
setTimeout(() => {
el.classList.add('is-visible');
}, delay);
});
});
</script>
<style>
.not-found-section {
position: relative;
width: 100%;
min-height: calc(100vh - 300px);
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #0a2540 0%, #1e3a5f 50%, #0a2540 100%);
padding: 4rem 1rem;
overflow: hidden;
}
/* ===== ПЛАВАЮЩИЕ ФОНОВЫЕ ЭЛЕМЕНТЫ ===== */
.floating-elements {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
overflow: hidden;
}
.floating-shape {
position: absolute;
border-radius: 50%;
opacity: 0.1;
animation: float 20s ease-in-out infinite;
}
.shape-1 {
width: 300px;
height: 300px;
background: linear-gradient(135deg, #eac26e, #f5d799);
top: 10%;
left: -5%;
animation-delay: 0s;
animation-duration: 25s;
}
.shape-2 {
width: 200px;
height: 200px;
background: linear-gradient(135deg, #ffffff, #e5e5e5);
top: 60%;
right: 10%;
animation-delay: 2s;
animation-duration: 20s;
}
.shape-3 {
width: 150px;
height: 150px;
background: linear-gradient(135deg, #eac26e, #d4a843);
bottom: 10%;
left: 20%;
animation-delay: 4s;
animation-duration: 22s;
}
.shape-4 {
width: 250px;
height: 250px;
background: linear-gradient(135deg, #ffffff, #f0f0f0);
top: 20%;
right: -5%;
animation-delay: 6s;
animation-duration: 28s;
}
.shape-5 {
width: 180px;
height: 180px;
background: linear-gradient(135deg, #eac26e, #f5d799);
bottom: 20%;
right: 30%;
animation-delay: 8s;
animation-duration: 24s;
}
@keyframes float {
0%, 100% {
transform: translate(0, 0) rotate(0deg) scale(1);
}
25% {
transform: translate(30px, -40px) rotate(90deg) scale(1.1);
}
50% {
transform: translate(-20px, -80px) rotate(180deg) scale(0.95);
}
75% {
transform: translate(-40px, -40px) rotate(270deg) scale(1.05);
}
}
/* ===== ОСНОВНОЙ КОНТЕНТ ===== */
.not-found-content {
position: relative;
z-index: 2;
text-align: center;
max-width: 900px;
}
/* ===== АНИМАЦИЯ ПОЯВЛЕНИЯ ===== */
.animate-fade-in {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
.animate-fade-in.is-visible {
opacity: 1;
transform: translateY(0);
}
/* ===== ЦИФРА 404 ===== */
.error-code {
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
margin-bottom: 2rem;
position: relative;
}
.error-digit {
font-size: clamp(6rem, 15vw, 12rem);
font-weight: 900;
color: transparent;
background: linear-gradient(180deg, #ffffff 0%, #eac26e 100%);
-webkit-background-clip: text;
background-clip: text;
line-height: 1;
position: relative;
animation: digitGlow 3s ease-in-out infinite;
text-shadow: 0 0 40px rgba(234, 194, 110, 0.5);
}
.digit-1 {
animation-delay: 0s;
}
.digit-2 {
animation-delay: 0.3s;
}
.digit-3 {
animation-delay: 0.6s;
}
@keyframes digitGlow {
0%, 100% {
filter: drop-shadow(0 0 20px rgba(234, 194, 110, 0.6));
transform: translateY(0);
}
50% {
filter: drop-shadow(0 0 40px rgba(234, 194, 110, 1));
transform: translateY(-10px);
}
}
/* ===== СВЕЧЕНИЕ ===== */
.glow-effect {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
height: 400px;
background: radial-gradient(circle, rgba(234, 194, 110, 0.3) 0%, transparent 70%);
border-radius: 50%;
animation: glowPulse 4s ease-in-out infinite;
pointer-events: none;
z-index: -1;
}
@keyframes glowPulse {
0%, 100% {
opacity: 0.5;
transform: translate(-50%, -50%) scale(1);
}
50% {
opacity: 0.8;
transform: translate(-50%, -50%) scale(1.2);
}
}
/* ===== ЗАГОЛОВОК И ОПИСАНИЕ ===== */
.error-title {
font-size: clamp(1.8rem, 4vw, 3rem);
font-weight: 800;
color: #ffffff;
margin: 0 0 1.5rem 0;
line-height: 1.2;
}
.error-title .text-gold {
color: #eac26e;
position: relative;
display: inline-block;
}
.error-title .text-gold::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
width: 100%;
height: 3px;
background: linear-gradient(90deg, transparent, #eac26e, transparent);
animation: underlineGlow 2s ease-in-out infinite;
}
@keyframes underlineGlow {
0%, 100% {
opacity: 0.5;
}
50% {
opacity: 1;
}
}
.error-description {
font-size: clamp(1rem, 2vw, 1.25rem);
color: rgba(255, 255, 255, 0.85);
line-height: 1.6;
margin: 0 auto 3rem;
max-width: 700px;
}
/* ===== ПРЕДУПРЕЖДАЮЩИЙ ЗНАК ===== */
.warning-sign {
margin-bottom: 3rem;
}
.warning-triangle {
display: inline-block;
color: #eac26e;
animation: warningPulse 2s ease-in-out infinite;
}
.warning-triangle svg {
width: 60px;
height: 54px;
filter: drop-shadow(0 5px 15px rgba(234, 194, 110, 0.5));
}
@keyframes warningPulse {
0%, 100% {
transform: scale(1);
opacity: 0.8;
}
50% {
transform: scale(1.1);
opacity: 1;
}
}
/* ===== КНОПКИ ===== */
.error-actions {
display: flex;
gap: 1.5rem;
justify-content: center;
align-items: center;
flex-wrap: wrap;
margin-bottom: 3rem;
}
.error-actions > * {
display: flex;
align-items: center;
}
.btn-content {
display: flex;
align-items: center;
gap: 0.5rem;
}
.btn-icon {
flex-shrink: 0;
}
/* Кастомные стили для кнопки "Наши услуги" */
.btn-services {
background: transparent !important;
border: 2px solid #ffffff !important;
color: #ffffff !important;
padding: 0.875rem 1.5rem !important;
font-size: 1.125rem !important;
line-height: 1.75rem !important;
position: relative;
overflow: hidden;
z-index: 1;
height: auto !important;
min-height: 3.25rem !important;
transition: all 0.3s ease;
}
.btn-services::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s ease;
z-index: -1;
}
.btn-services::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 0;
height: 100%;
background: linear-gradient(90deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.2));
transition: width 0.4s ease;
z-index: -1;
}
.btn-services:hover {
background: rgba(255, 255, 255, 0.1) !important;
border-color: #eac26e !important;
color: #eac26e !important;
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(234, 194, 110, 0.3);
}
.btn-services:hover::before {
left: 100%;
}
.btn-services:hover::after {
width: 100%;
}
.btn-services:active {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(234, 194, 110, 0.2);
}
/* ===== ДОПОЛНИТЕЛЬНАЯ ПОМОЩЬ ===== */
.additional-help {
text-align: center;
}
.help-text {
color: rgba(255, 255, 255, 0.7);
font-size: 1rem;
margin: 0 0 0.75rem 0;
}
.phone-link {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: #eac26e;
font-size: 1.25rem;
font-weight: 700;
text-decoration: none;
transition: all 0.3s ease;
position: relative;
}
.phone-link::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
width: 0;
height: 2px;
background: #eac26e;
transition: width 0.3s ease;
}
.phone-link:hover {
color: #f5d799;
transform: translateY(-2px);
}
.phone-link:hover::after {
width: 100%;
}
.phone-link svg {
animation: phoneRing 2s ease-in-out infinite;
}
@keyframes phoneRing {
0%, 100% {
transform: rotate(0deg);
}
10% {
transform: rotate(15deg);
}
20% {
transform: rotate(-15deg);
}
30% {
transform: rotate(10deg);
}
40% {
transform: rotate(-10deg);
}
50% {
transform: rotate(0deg);
}
}
/* ===== АДАПТИВНОСТЬ ===== */
@media (max-width: 768px) {
.not-found-section {
min-height: calc(100vh - 250px);
padding: 3rem 1rem;
}
.error-code {
gap: 0.25rem;
}
.error-digit {
font-size: clamp(4rem, 18vw, 8rem);
}
.glow-effect {
width: 300px;
height: 300px;
}
.error-actions {
flex-direction: column;
}
.error-actions > * {
width: 100%;
}
.warning-triangle svg {
width: 50px;
height: 45px;
}
}
@media (max-width: 480px) {
.not-found-section {
padding: 2rem 1rem;
}
.error-title {
font-size: clamp(1.5rem, 6vw, 2rem);
}
.error-description {
font-size: 1rem;
margin-bottom: 2rem;
}
.phone-link {
font-size: 1.1rem;
}
}
/* Уважаем prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
.animate-fade-in {
opacity: 1;
transform: none;
transition: none;
}
.floating-shape,
.error-digit,
.glow-effect,
.warning-triangle,
.phone-link svg {
animation: none;
}
.error-title .text-gold::after {
animation: none;
opacity: 1;
}
}
</style>