🚀 MEGA UPDATE: Объединение всех изменений для продакшена
Some checks failed
continuous-integration/drone/push Build is failing

 НОВЫЕ ФУНКЦИИ:
- 🎬 Поддержка видео в Hero баннерах и услугах
- 💊 Водная анимация пилюль маркеров банеров
- 📱 Полная главная страница с портфолио, блогом, новостями
- 🎯 HeroBanner модель с видео/изображениями
- 🎨 Современные hover-эффекты и анимации

📊 УЛУЧШЕНИЯ СТРУКТУРЫ:
- Расширенная home_modern.html с полным контентом
- Новые URL маршруты для всех секций
- Обновленные views с передачей всех данных
- CSS стили для всех новых секций
- Миграции для видео полей

🎪 HERO БАНЕР СИСТЕМА:
- Динамические банеры с видео/фото фонами
- Пилюли маркеры с водной анимацией
- Растягивание маркеров от центра
- Адаптивный дизайн для мобильных
- Glassmorphism эффекты

🎨 СОВРЕМЕННЫЙ ДИЗАЙН:
- Hover анимации для карточек
- Плавные переходы везде
- Современная типографика
- Градиенты и тени
- Отзывчивая сетка

Готов к продакшену! 🚀
This commit is contained in:
2025-11-25 11:24:19 +09:00
parent 6a576136af
commit 6f43fa4c3b
14 changed files with 1832 additions and 94 deletions

58
create_hero_banner.py Normal file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""
Создание тестового Hero баннера с видео
"""
import os
import sys
# Добавляем путь к Django проекту
sys.path.append('/home/data/smartsoltech.kr/smartsoltech')
# Настройка Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'smartsoltech.settings')
import django
django.setup()
from web.models import HeroBanner
def create_hero_banner():
"""Создает тестовый Hero баннер с видео"""
# Создаем баннер с видео
hero_video = HeroBanner.objects.create(
title="Smart Solutions для вашего бизнеса",
subtitle="Профессиональная разработка и внедрение IT-решений",
description="Мы создаем инновативные технологические решения, которые помогут вашему бизнесу достичь новых высот эффективности и успеха.",
button_text="Получить консультацию",
button_link="/contact/",
video="static/video/hero/hero-demo.mp4",
is_active=True,
order=1
)
# Создаем баннер с изображением (fallback)
hero_image = HeroBanner.objects.create(
title="Цифровые решения нового поколения",
subtitle="Автоматизация, интеграция, оптимизация",
description="Трансформируйте свой бизнес с помощью наших передовых IT-решений и экспертного подхода к каждому проекту.",
button_text="Наши услуги",
button_link="/services/",
image="static/img/about/about-1.jpg",
is_active=True,
order=2
)
print(f"✅ Создан Hero баннер с видео: {hero_video.title}")
print(f"✅ Создан Hero баннер с изображением: {hero_image.title}")
# Показываем все активные баннеры
active_banners = HeroBanner.objects.filter(is_active=True).order_by('order')
print(f"\n📋 Всего активных баннеров: {active_banners.count()}")
for banner in active_banners:
media_type = "🎬 Видео" if banner.video else "🖼️ Изображение"
print(f" {banner.order}. {banner.title} ({media_type})")
if __name__ == "__main__":
create_hero_banner()

35
hero_script.py Normal file
View File

@@ -0,0 +1,35 @@
from web.models import HeroBanner
# Создаем баннер с видео
hero_video = HeroBanner.objects.create(
title="Smart Solutions для вашего бизнеса",
subtitle="Профессиональная разработка и внедрение IT-решений",
description="Мы создаем инновативные технологические решения, которые помогут вашему бизнесу достичь новых высот эффективности и успеха.",
button_text="Получить консультацию",
button_link="/contact/",
video="static/video/hero/hero-demo.mp4",
is_active=True,
order=1
)
# Создаем баннер с изображением (fallback)
hero_image = HeroBanner.objects.create(
title="Цифровые решения нового поколения",
subtitle="Автоматизация, интеграция, оптимизация",
description="Трансформируйте свой бизнес с помощью наших передовых IT-решений и экспертного подхода к каждому проекту.",
button_text="Наши услуги",
button_link="/services/",
image="static/img/about/about-1.jpg",
is_active=True,
order=2
)
print(f"✅ Создан Hero баннер с видео: {hero_video.title}")
print(f"✅ Создан Hero баннер с изображением: {hero_image.title}")
# Показываем все активные баннеры
active_banners = HeroBanner.objects.filter(is_active=True).order_by('order')
print(f"\n📋 Всего активных баннеров: {active_banners.count()}")
for banner in active_banners:
media_type = "🎬 Видео" if banner.video else "🖼️ Изображение"
print(f" {banner.order}. {banner.title} ({media_type})")

361
original_home_modern.html Normal file
View File

@@ -0,0 +1,361 @@
{% extends 'web/base_modern.html' %}
{% load static %}
{% block title %}SmartSolTech - Современные IT-решения для вашего бизнеса{% endblock %}
{% block content %}
<!-- Hero Section -->
<section class="hero-modern" id="home">
<div class="container-modern">
<div class="row align-items-center min-vh-100">
<div class="col-lg-6">
<div class="animate-fade-in-up">
<h1 class="display-3 fw-bold mb-4">
Создаем <span class="text-gradient">будущее</span> вашего бизнеса
</h1>
<p class="lead mb-4 text-muted">
Мы разрабатываем современные веб-приложения, мобильные решения и системы автоматизации,
которые помогают компаниям расти и быть конкурентоспособными.
</p>
<div class="d-flex flex-wrap gap-3 mb-5">
<a href="{% url 'services' %}" class="btn btn-primary-modern btn-lg">
<i class="fas fa-rocket me-2"></i>
Начать проект
</a>
<a href="{% url 'about' %}" class="btn btn-secondary-modern btn-lg">
<i class="fas fa-play-circle me-2"></i>
Узнать больше
</a>
</div>
<div class="row text-center">
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">50+</h3>
<p class="small text-muted mb-0">Проектов</p>
</div>
</div>
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">3+</h3>
<p class="small text-muted mb-0">Лет опыта</p>
</div>
</div>
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">24/7</h3>
<p class="small text-muted mb-0">Поддержка</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="text-center animate-float">
<div class="position-relative">
<!-- 3D Graphic Placeholder -->
<div class="hero-graphic p-5">
<div class="position-relative">
<!-- Code Window -->
<div class="code-window bg-dark rounded-4 p-4 mb-4 shadow-lg"
style="transform: rotate(-5deg); max-width: 400px;">
<div class="d-flex gap-2 mb-3">
<div class="rounded-circle bg-danger" style="width: 12px; height: 12px;"></div>
<div class="rounded-circle bg-warning" style="width: 12px; height: 12px;"></div>
<div class="rounded-circle bg-success" style="width: 12px; height: 12px;"></div>
</div>
<div class="text-light font-monospace small">
<div class="text-info">def create_future():</div>
<div class="ms-3 text-success">return innovation + passion</div>
<div class="text-warning">// SmartSolTech</div>
</div>
</div>
<!-- Mobile App Preview -->
<div class="mobile-preview bg-light rounded-4 p-3 shadow-lg position-absolute"
style="transform: rotate(10deg); top: 50px; right: 50px; width: 200px;">
<div class="bg-gradient rounded-3 p-3 text-white text-center">
<i class="fas fa-mobile-alt fa-3x mb-2"></i>
<h6 class="mb-1">Мобильные</h6>
<p class="small mb-0 opacity-75">приложения</p>
</div>
</div>
<!-- Floating Icons -->
<div class="floating-icon position-absolute"
style="top: 20px; left: 20px; animation: float 2s ease-in-out infinite;">
<div class="bg-primary rounded-3 p-3 text-white shadow">
<i class="fab fa-react fa-2x"></i>
</div>
</div>
<div class="floating-icon position-absolute"
style="bottom: 100px; left: 100px; animation: float 3s ease-in-out infinite reverse;">
<div class="bg-success rounded-3 p-3 text-white shadow">
<i class="fab fa-python fa-2x"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Services Preview Section -->
<section class="section-padding bg-light">
<div class="container-modern">
<div class="text-center mb-5">
<h2 class="display-5 fw-bold mb-3">
Полный спектр <span class="text-gradient">IT-услуг</span>
</h2>
<p class="lead text-muted max-width-600 mx-auto">
От идеи до реализации - мы предоставляем комплексные решения для вашего цифрового успеха
</p>
</div>
<div class="services-grid">
{% for service in services %}
<div class="service-card">
<div class="service-icon">
<i class="fas fa-{% cycle 'code' 'mobile-alt' 'paint-brush' 'server' 'chart-line' 'shield-alt' %}"></i>
</div>
<h4 class="mb-3">{{ service.name }}</h4>
<p class="text-muted mb-4">{{ service.description|truncatewords:20 }}</p>
<a href="{% url 'service_detail' service.pk %}" class="btn btn-outline-primary">
Подробнее <i class="fas fa-arrow-right ms-2"></i>
</a>
</div>
{% endfor %}
</div>
<div class="text-center mt-5">
<a href="{% url 'services' %}" class="btn btn-primary-modern btn-lg">
<i class="fas fa-th-large me-2"></i>
Все услуги
</a>
</div>
</div>
</section>
<!-- Why Choose Us Section -->
<section class="section-padding">
<div class="container-modern">
<div class="row align-items-center">
<div class="col-lg-6">
<div class="pe-lg-5">
<h2 class="display-6 fw-bold mb-4">
Ваш надежный <span class="text-gradient">IT-партнер</span>
</h2>
<p class="text-muted mb-4">
Мы не просто выполняем проекты - мы создаем долгосрочные партнерские отношения
и помогаем бизнесу расти с помощью технологий.
</p>
<div class="feature-list">
<div class="d-flex align-items-start mb-4">
<div class="feature-icon bg-primary rounded-3 p-2 me-3 text-white">
<i class="fas fa-rocket"></i>
</div>
<div>
<h5 class="mb-2">Быстрая разработка</h5>
<p class="text-muted mb-0">Agile-методология и современные инструменты для быстрой доставки результата</p>
</div>
</div>
<div class="d-flex align-items-start mb-4">
<div class="feature-icon bg-success rounded-3 p-2 me-3 text-white">
<i class="fas fa-shield-alt"></i>
</div>
<div>
<h5 class="mb-2">Высокое качество</h5>
<p class="text-muted mb-0">Тщательное тестирование и code review обеспечивают надежность решений</p>
</div>
</div>
<div class="d-flex align-items-start mb-4">
<div class="feature-icon bg-warning rounded-3 p-2 me-3 text-white">
<i class="fas fa-headset"></i>
</div>
<div>
<h5 class="mb-2">24/7 Поддержка</h5>
<p class="text-muted mb-0">Постоянная техническая поддержка и сопровождение проектов</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="position-relative">
<!-- Process Steps -->
<div class="process-steps">
<div class="step-card active bg-white rounded-4 p-4 shadow mb-4">
<div class="d-flex align-items-center">
<div class="step-number bg-primary text-white rounded-circle me-3"
style="width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;">
1
</div>
<div>
<h6 class="mb-1">Анализ требований</h6>
<p class="small text-muted mb-0">Детальное изучение ваших потребностей</p>
</div>
</div>
</div>
<div class="step-card bg-white rounded-4 p-4 shadow mb-4">
<div class="d-flex align-items-center">
<div class="step-number bg-secondary text-white rounded-circle me-3"
style="width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;">
2
</div>
<div>
<h6 class="mb-1">Проектирование</h6>
<p class="small text-muted mb-0">Создание архитектуры и дизайна</p>
</div>
</div>
</div>
<div class="step-card bg-white rounded-4 p-4 shadow mb-4">
<div class="d-flex align-items-center">
<div class="step-number bg-success text-white rounded-circle me-3"
style="width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;">
3
</div>
<div>
<h6 class="mb-1">Разработка</h6>
<p class="small text-muted mb-0">Программирование и тестирование</p>
</div>
</div>
</div>
<div class="step-card bg-white rounded-4 p-4 shadow">
<div class="d-flex align-items-center">
<div class="step-number bg-warning text-white rounded-circle me-3"
style="width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;">
4
</div>
<div>
<h6 class="mb-1">Запуск и поддержка</h6>
<p class="small text-muted mb-0">Деплой и техническая поддержка</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="section-padding bg-gradient text-white">
<div class="container-modern text-center">
<div class="row justify-content-center">
<div class="col-lg-8">
<h2 class="display-6 fw-bold mb-4">
Готовы начать свой проект?
</h2>
<p class="lead mb-5 opacity-90">
Свяжитесь с нами сегодня и получите бесплатную консультацию по вашему проекту
</p>
<div class="d-flex flex-wrap gap-3 justify-content-center">
<a href="{% url 'services' %}" class="btn btn-light btn-lg text-primary">
<i class="fas fa-comments me-2"></i>
Получить консультацию
</a>
<a href="tel:+82-10-XXXX-XXXX" class="btn btn-outline-light btn-lg">
<i class="fas fa-phone me-2"></i>
Позвонить сейчас
</a>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
{% block extra_scripts %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Animate elements on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver(function(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-fade-in-up');
}
});
}, observerOptions);
// Observe service cards
document.querySelectorAll('.service-card, .step-card').forEach(card => {
observer.observe(card);
});
});
</script>
<style>
.max-width-600 {
max-width: 600px;
}
.hero-graphic {
perspective: 1000px;
}
.code-window {
transform-style: preserve-3d;
}
.floating-icon {
animation-delay: 1s;
}
.step-card {
opacity: 0;
transform: translateY(30px);
transition: all 0.6s ease;
}
.step-card.animate-fade-in-up {
opacity: 1;
transform: translateY(0);
}
.feature-icon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
}
@media (max-width: 768px) {
.hero-graphic {
margin-top: 2rem;
}
.code-window {
transform: rotate(0deg) !important;
max-width: 100% !important;
}
.mobile-preview {
position: relative !important;
transform: rotate(0deg) !important;
margin-top: 1rem;
width: 100% !important;
}
.floating-icon {
position: relative !important;
display: inline-block;
margin: 0.5rem;
}
}
</style>
{% endblock %}

View File

@@ -523,4 +523,625 @@ p {
right: 8px;
top: 38px;
}
}
/* Video Support Styles */
.hero-video {
transition: opacity 0.3s ease;
}
.service-video {
transition: transform 0.3s ease;
}
.service-video:hover {
transform: scale(1.05);
}
.carousel-item {
transition: transform 0.6s ease-in-out;
}
.hero-bg {
position: relative;
overflow: hidden;
}
.hero-bg::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, rgba(99, 102, 241, 0.3) 0%, rgba(139, 92, 246, 0.3) 100%);
z-index: 1;
}
/* Video Loading States */
.video-loading {
background: linear-gradient(45deg, #f3f4f6, #e5e7eb);
background-size: 400% 400%;
animation: shimmer 1.5s ease-in-out infinite;
}
@keyframes shimmer {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
/* Video Controls */
.video-controls {
position: absolute;
bottom: 20px;
right: 20px;
z-index: 2;
}
.video-play-btn {
background: rgba(255, 255, 255, 0.9);
border: none;
border-radius: 50%;
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
color: var(--primary-color);
font-size: 18px;
transition: all 0.3s ease;
}
.video-play-btn:hover {
background: rgba(255, 255, 255, 1);
transform: scale(1.1);
}
/* Responsive Video */
@media (max-width: 768px) {
.hero-video,
.service-video {
height: 300px !important;
}
.carousel-item {
min-height: 400px;
}
}
/* Hero Container Styles */
.hero-modern {
padding: 0;
background: var(--bg-light);
}
.hero-container {
background: var(--gradient-primary);
border-radius: 24px;
overflow: hidden;
box-shadow: 0 25px 50px -12px rgba(99, 102, 241, 0.25);
position: relative;
margin: 1.5rem auto;
max-width: 1200px;
}
.hero-bg {
position: relative;
min-height: 600px;
}
.hero-video,
.hero-bg img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
z-index: 1;
}
.hero-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%);
z-index: 2;
}
.hero-content {
position: relative;
z-index: 3;
padding: 4rem 2rem;
display: flex;
align-items: center;
min-height: 600px;
}
/* Custom Carousel Indicators - Pill System */
.carousel-indicators-container {
position: absolute;
bottom: 2.5rem;
left: 50%;
transform: translateX(-50%);
z-index: 4;
}
.outer-pill {
position: relative;
display: inline-flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem;
background: rgba(0, 0, 0, 0.3);
-webkit-backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
border-radius: 50px;
border: 1px solid rgba(255, 255, 255, 0.15);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
min-height: 50px;
transition: none;
overflow: visible;
}
/* Удаляем старую структуру inner-pill */
.pill-indicators {
display: flex;
gap: 0.75rem;
align-items: center;
flex-wrap: nowrap;
white-space: nowrap;
}
.pill-indicator {
height: 36px;
border-radius: 18px;
border: 2px solid rgba(255, 255, 255, 0.4);
background: rgba(255, 255, 255, 0.1);
position: relative;
z-index: 1;
transition: width 0.8s cubic-bezier(0.23, 1, 0.32, 1),
padding 0.8s cubic-bezier(0.23, 1, 0.32, 1),
border-color 0.3s ease;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
width: 36px;
overflow: visible;
transform-origin: center;
flex-shrink: 0;
}
.pill-indicator.active {
border: 2px solid rgba(255, 255, 255, 0.8);
background: rgba(255, 255, 255, 0.1);
width: fit-content;
min-width: 36px;
padding: 0 1rem;
border-radius: 18px;
}
.pill-indicator:not(.active):hover {
border-color: rgba(255, 255, 255, 0.7);
background: rgba(255, 255, 255, 0.2);
transform: scale(1.05);
}
.pill-indicator::before {
content: '';
width: 8px;
height: 8px;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
transition: opacity 0.4s cubic-bezier(0.23, 1, 0.32, 1),
transform 0.4s cubic-bezier(0.23, 1, 0.32, 1);
display: block;
flex-shrink: 0;
position: absolute;
transform-origin: center;
opacity: 1;
z-index: 1;
}
.pill-indicator.active::before {
opacity: 0;
transform: scale(0);
}
.pill-indicator:hover:not(.active)::before {
background: rgba(255, 255, 255, 1);
transform: scale(1.2);
}
.pill-indicator-title {
font-size: 0.875rem;
font-weight: 600;
color: rgba(255, 255, 255, 0.95);
white-space: nowrap;
opacity: 0;
transform: scale(0.8);
transition: opacity 0.6s cubic-bezier(0.23, 1, 0.32, 1) 0.2s,
transform 0.6s cubic-bezier(0.23, 1, 0.32, 1) 0.2s;
margin: 0;
position: relative;
transform-origin: center;
z-index: 2;
}
.pill-indicator.active .pill-indicator-title {
opacity: 1;
transform: scale(1);
}
/* Плавная анимация как вода */
.pill-indicator:not(.active):hover {
border-color: rgba(255, 255, 255, 0.7);
background: rgba(255, 255, 255, 0.2);
transform: scale(1.05);
transition: all 0.3s ease;
}
/* Новые стили для расширенной главной страницы */
.project-card {
transition: all 0.3s ease;
}
.project-card:hover {
transform: translateY(-10px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15) !important;
}
.project-image {
position: relative;
overflow: hidden;
height: 200px;
}
.project-image img {
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.project-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.project-card:hover .project-overlay {
opacity: 1;
}
.project-card:hover .project-image img {
transform: scale(1.1);
}
.blog-card {
transition: all 0.3s ease;
}
.blog-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1) !important;
}
.blog-image {
height: 200px;
overflow: hidden;
}
.blog-image img {
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.blog-card:hover .blog-image img {
transform: scale(1.05);
}
.news-card {
transition: all 0.3s ease;
}
.news-card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1) !important;
}
.career-feature {
transition: all 0.3s ease;
}
.career-feature:hover {
transform: translateY(-5px);
}
.career-icon {
transition: all 0.3s ease;
}
.career-feature:hover .career-icon {
transform: scale(1.1);
}
.career-stats {
transition: all 0.3s ease;
}
.career-stats:hover {
transform: scale(1.05);
}
.hover-lift {
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.hover-lift:hover {
transform: translateY(-8px);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.15);
}
/* Carousel Controls */
.hero-container {
position: relative;
}
.carousel-control-prev,
.carousel-control-next {
position: absolute;
width: 50px;
height: 50px;
background: rgba(0, 0, 0, 0.3);
-webkit-backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
opacity: 0.8;
z-index: 5;
}
.carousel-control-prev {
left: 1.5rem;
}
.carousel-control-next {
right: 1.5rem;
}
.carousel-control-prev:hover,
.carousel-control-next:hover {
background: rgba(0, 0, 0, 0.5);
transform: translateY(-50%) scale(1.1);
opacity: 1;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
/* Hero Text Styles */
.hero-title {
font-size: 3.5rem;
font-weight: 800;
background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
margin-bottom: 1.5rem;
line-height: 1.1;
}
.hero-subtitle {
font-size: 1.5rem;
font-weight: 500;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 1.5rem;
}
.hero-description {
font-size: 1.25rem;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 2.5rem;
line-height: 1.6;
}
/* Responsive Design */
@media (max-width: 768px) {
.hero-container {
border-radius: 16px;
margin: 1rem;
}
.hero-content {
padding: 2rem 1.5rem;
min-height: 500px;
}
.hero-title {
font-size: 2.5rem;
}
.hero-subtitle {
font-size: 1.25rem;
}
.hero-description {
font-size: 1.125rem;
}
.carousel-indicators-container {
bottom: 8px;
}
.outer-pill {
gap: 0.5rem;
padding: 0.5rem;
}
.pill-indicators {
gap: 0.5rem;
}
.pill-indicator.active {
padding: 0 0.75rem;
font-size: 0.8rem;
}
.pill-indicator-title {
font-size: 0.8rem;
}
.pill-indicator {
width: 32px;
height: 32px;
}
.inner-pill {
height: 32px;
width: 32px;
}
.inner-pill.active {
min-width: 100px;
}
.pill-title {
font-size: 0.75rem;
}
}
/* Дополнительные эффекты для пилюль */
.inner-pill::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(90deg,
transparent 0%,
rgba(99, 102, 241, 0.2) 50%,
transparent 100%);
border-radius: 25px;
opacity: 0;
animation: pillShimmer 3s infinite;
}
.outer-pill.expanded .inner-pill::before {
opacity: 1;
}
/* Эффект пульсации для внешней пилюли */
.outer-pill::after {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(45deg,
rgba(99, 102, 241, 0.3) 0%,
rgba(139, 92, 246, 0.3) 100%);
border-radius: 52px;
opacity: 0;
z-index: -1;
transition: opacity 0.3s ease;
}
.outer-pill.expanded::after {
opacity: 1;
animation: pillGlow 2s infinite alternate;
}
@keyframes pillShimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
@keyframes pillGlow {
0% {
opacity: 0.3;
}
100% {
opacity: 0.7;
}
}
@keyframes shimmerSlide {
0% {
transform: translateX(-100%);
opacity: 0;
}
50% {
opacity: 1;
}
100% {
transform: translateX(100%);
opacity: 0;
}
}
/* Animations */
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
@keyframes ripple {
0% {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
100% {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-in-up {
animation: fadeInUp 0.8s ease-out;
}

View File

@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW 2019 (64-Bit) -->
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="100mm" height="100mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 10000 10000"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<font id="FontID1" horiz-adv-x="596" font-variant="normal" style="fill-rule:nonzero" font-weight="400">
<font-face
font-family="Futura_Book-Normal">
<font-face-src>
<font-face-name name="Futura_Book-Normal"/>
</font-face-src>
</font-face>
<missing-glyph><path d="M0 0z"/></missing-glyph>
<glyph unicode="B" horiz-adv-x="516" d="M216.997 618.991l13.0124 0c8.66769,0 17.4875,-0.152065 26.481,-0.499642 9.01527,-0.325853 17.835,-0.825495 26.5027,-1.49892 16.0103,-1.32514 31.6729,-4.1492 47.0098,-8.49391 15.3368,-4.32299 29.6744,-11.1659 42.9909,-20.507 16.6837,-12.6648 29.8482,-28.3275 39.5151,-46.988 9.66698,-18.6605 15.8147,-37.9945 18.4867,-58.0019 0.67343,-3.99713 1.17307,-7.8422 1.49892,-11.4918 0.347577,-3.67128 0.499642,-7.51635 0.499642,-11.5135 0,-28.0017 -7.32084,-54.5044 -21.9842,-79.4865 -14.6851,-25.0038 -37.6686,-42.1871 -69.0157,-51.5065 36.6693,-7.34256 64.8448,-25.0038 84.5046,-53.0055 19.6598,-28.0017 30.8257,-58.3277 33.4977,-90.9999 0,-1.99857 0,-4.17092 0,-6.49534 0,-2.34614 0,-4.49677 0,-6.49534 0,-27.3499 -5.9957,-53.8309 -17.9871,-79.5082 -12.0131,-25.6555 -29.6744,-46.836 -53.0055,-63.4979 -14.6634,-8.66769 -30.8474,-15.163 -48.5087,-19.5077 -17.6612,-4.32299 -35.4963,-6.82119 -53.5051,-7.49462 -9.3194,-0.67343 -18.4867,-1.17307 -27.4803,-1.49892 -9.01527,-0.325853 -17.835,-0.499642 -26.5027,-0.499642l-145.005 0 0 618.991 128.994 0zm-58.0019 -553.994c4.67056,0 9.34112,-0.173788 14.0117,-0.499642 4.67056,-0.325853 9.3194,-0.499642 13.99,-0.499642 4.67056,0 9.49319,-0.173788 14.5113,-0.499642 4.99642,-0.325853 9.81904,-0.499642 14.4896,-0.499642 2.672,0 5.49606,0 8.49391,0 3.01957,0 6.16949,0 9.51491,0 36.6693,1.32514 70.3191,8.84148 100.993,22.5056 30.6736,13.6641 46.0105,44.164 46.0105,91.4996l0 2.99785c0,45.9887 -14.0117,75.989 -42.0133,90.0007 -28.0017,13.99 -59.0012,21.3325 -92.9985,22.006 -1.99857,0 -3.82334,0 -5.49606,0 -1.67271,0 -3.49749,0 -5.49606,0 -2.672,0 -5.34399,0 -8.01599,0 -2.65027,0 -5.32227,0 -7.99426,0 -3.99713,0 -7.82048,-0.173788 -11.4918,-0.499642 -3.67128,-0.347577 -7.49462,-0.499642 -11.5135,-0.499642 -6.64741,0 -12.9907,-0.173788 -18.9864,-0.499642 -5.9957,-0.347577 -12.0131,-0.499642 -18.0088,-0.499642l0 -225.012zm0 488.997l0 -206.004c3.99713,0 8.16805,0 12.5128,0 4.32299,0 8.81976,0 13.4903,0 0.67343,-0.651706 1.49892,-0.999283 2.49821,-0.999283 0.999283,0 1.8465,0 2.49821,0 3.34543,0 6.84292,0 10.5142,0 3.64956,0 7.16877,0 10.4925,0 1.99857,0 3.82334,0 5.49606,0 1.67271,0 3.49749,0 5.49606,0 33.9973,0.67343 65.1706,7.16877 93.4981,19.5077 28.3492,12.339 43.1864,40.8403 44.5115,85.5039l0 2.99785c0,37.9945 -13.0124,63.3241 -38.9938,76.0107 -26.0031,12.6648 -54.6782,19.9857 -86.0035,21.9842 -5.9957,0.67343 -12.0131,0.999283 -18.0088,0.999283 -5.9957,0 -11.9914,0 -17.9871,0l-40.0148 0z"/>
<glyph unicode="E" horiz-adv-x="464" d="M81.0071 0l0 618.991 325.984 0 0 -67.9947 -252.992 0 0 -177.003 252.992 0 0 -67.9947 -252.992 0 0 -238.003 252.992 0 0 -67.9947 -325.984 0z"/>
<glyph unicode="F" horiz-adv-x="364" d="M81.0071 0l0 618.991 325.984 0 0 -67.9947 -252.992 0 0 -177.003 252.992 0 0 -67.9947 -252.992 0 0 -305.998 -72.9911 0z"/>
<glyph unicode="G" horiz-adv-x="736" d="M427.997 319.01l256.012 0c0,-1.34686 0,-2.84578 0,-4.5185 0,-1.65099 0,-3.14991 0,-4.49677 -0.67343,-7.32084 -1.17307,-14.3375 -1.49892,-20.9849 -0.347577,-6.66913 -0.499642,-13.3383 -0.499642,-20.0074 -1.34686,-17.3354 -3.17164,-34.3449 -5.51778,-51.0069 -2.32442,-16.662 -6.16949,-32.9981 -11.4918,-48.9866 -21.3325,-61.999 -58.8274,-108.009 -112.506,-138.01 -53.6572,-30.0002 -110.486,-44.9895 -170.486,-44.9895 -1.99857,0 -4.17092,0 -6.51706,0 -2.32442,0 -4.82263,0 -7.49462,0 -59.327,2.65027 -115.656,19.334 -168.987,49.9859 -53.353,30.6736 -91.6734,74.338 -115.004,131.015 -5.9957,16.662 -11.3397,33.9973 -16.0103,51.9844 -4.67056,18.0088 -7.66841,35.9959 -8.99355,54.0047 -0.67343,5.34399 -1.17307,10.6663 -1.49892,16.0103 -0.325853,5.32227 -0.499642,10.6663 -0.499642,15.9885 0,8.66769 0.325853,17.3354 0.999283,26.0031 0.67343,8.66769 1.67271,17.3354 2.99785,26.0031 3.99713,28.6534 11.4918,57.0026 22.5056,85.0042 10.9921,28.0017 25.1559,53.6572 42.4913,76.9882 30.0002,37.9945 67.1692,66.3437 111.507,85.0042 44.3378,18.6605 89.8269,28.0017 136.489,28.0017 3.99713,0 8.01599,0 12.0131,0 3.99713,0 8.32012,-0.325853 12.9907,-0.999283 46.6622,-3.34543 91.9992,-15.8365 136.011,-37.4948 43.9902,-21.6801 79.6602,-52.18 106.988,-91.4996l-61.999 -48.009c-22.006,35.3225 -49.66,62.8245 -83.0057,82.506 -33.3239,19.6598 -70.9925,29.5006 -112.984,29.5006l-10.0146 0c-72.6653,-0.67343 -130.493,-27.3499 -173.484,-80.0078 -43.0126,-52.6579 -64.5189,-113.658 -64.5189,-182.999 0,-2.672 0.173788,-5.66985 0.521365,-8.99355 0.325853,-3.34543 0.825495,-6.34328 1.49892,-9.01527 0,-3.3237 0.152065,-6.64741 0.499642,-9.99283 0.325853,-3.3237 0.499642,-6.32155 0.499642,-8.99355 7.99426,-67.343 34.497,-118.828 79.4865,-154.498 45.0112,-35.6701 93.8457,-55.1778 146.504,-58.5015 2.672,-0.67343 5.34399,-0.999283 7.99426,-0.999283 2.672,0 5.34399,0 8.01599,0 53.3313,0 102.818,16.9878 148.48,50.9852 45.6846,34.0191 70.8405,84.3525 75.511,151l-177.003 0 0 65.0186z"/>
<glyph unicode="H" horiz-adv-x="627" d="M88.0021 0l0 618.991 71.9918 0 0 -237.981 329.003 0 0 237.981 75.0114 0 0 -618.991 -75.0114 0 0 310.994 -329.003 0 0 -310.994 -71.9918 0z"/>
<glyph unicode="I" horiz-adv-x="223" d="M86.0035 0l0 618.991 73.9904 0 0 -618.991 -73.9904 0z"/>
<glyph unicode="N" horiz-adv-x="666" d="M83.0057 0l0 642.995 452.002 -493.993 0 469.989 70.9925 0 0 -641.996 -454 487.998 0 -464.993 -68.994 0z"/>
<glyph unicode="R" horiz-adv-x="536" d="M163.991 0l-71.9918 0 0 618.991 153.998 0c6.66913,0 13.6641,-0.152065 21.0067,-0.499642 7.32084,-0.325853 14.3375,-0.825495 21.0067,-1.49892 21.9842,-1.32514 42.9909,-5.64812 62.9983,-12.9907 19.9857,-7.34256 36.9952,-19.6598 50.9852,-36.9952 8.66769,-11.3397 15.6627,-24.0045 21.0067,-38.0162 5.32227,-13.99 9.34112,-28.3275 11.9914,-42.9909 0.67343,-5.9957 1.34686,-12.1652 1.99857,-18.5085 0.67343,-6.32155 0.999283,-12.491 0.999283,-18.4867l0 -16.0103c-4.64884,-53.3313 -23.9828,-89.6531 -57.9801,-108.987 -34.0191,-19.334 -74.6856,-29.0009 -121.999,-29.0009l235.983 -295.006 -93.9978 0 -226.989 295.006 -9.01527 0 0 -295.006zm0 555.992l0 -205.983c4.67056,0 9.51491,-0.173788 14.5113,-0.499642 4.99642,-0.347577 10.4925,-0.499642 16.4882,-0.499642 4.01886,0 8.01599,-0.173788 12.0131,-0.499642 3.99713,-0.347577 7.99426,-0.521365 11.9914,-0.521365 1.99857,0 3.84507,0 5.49606,0 1.67271,0 3.17164,0 4.5185,0 2.65027,0 5.32227,0 7.99426,0 2.672,0 5.32227,0 7.99426,0 29.3268,1.34686 56.5029,7.8422 81.5067,19.5077 25.0038,11.6655 37.8207,35.4963 38.4941,71.4922l0 13.0124c0,46.6622 -13.99,75.6631 -41.9916,87.0028 -28.0017,11.318 -59.3487,16.9878 -93.9978,16.9878l-65.0186 0z"/>
<glyph unicode="S" horiz-adv-x="506" d="M327.005 343.992c33.3239,-13.99 60.6521,-32.8243 81.9847,-56.5029 21.3542,-23.6569 34.0191,-54.1568 38.0162,-91.4996 0,-1.99857 0.152065,-4.1492 0.499642,-6.49534 0.325853,-2.32442 0.499642,-4.49677 0.499642,-6.49534 0,-2.672 0.152065,-5.1702 0.499642,-7.49462 0.325853,-2.34614 0.499642,-4.49677 0.499642,-6.49534 0,-54.0047 -20.6808,-97.8429 -61.999,-131.514 -41.3399,-33.6715 -86.6769,-50.8331 -136.011,-51.4848 -0.651706,0 -1.15135,0 -1.49892,0 -0.325853,0 -0.825495,0 -1.49892,0 -7.32084,0 -14.6634,0.499642 -22.006,1.49892 -7.32084,0.999283 -14.6634,2.15063 -21.9842,3.49749 -9.34112,1.99857 -18.6822,4.49677 -28.0017,7.49462 -9.34112,2.99785 -18.3347,6.84292 -27.0024,11.4918 -23.3311,13.3383 -41.8395,30.174 -55.5037,50.5072 -13.6641,20.3332 -24.1566,42.8388 -31.4991,67.4951l65.9961 31.9988c0.67343,-1.32514 1.17307,-2.65027 1.49892,-3.99713 0.347577,-1.32514 0.499642,-2.672 0.499642,-3.99713 5.34399,-16.0103 11.8393,-31.6729 19.5077,-47.0098 7.66841,-15.3151 18.8343,-28.3275 33.4977,-38.9938 5.34399,-3.3237 10.84,-6.16949 16.5099,-8.49391 5.64812,-2.34614 11.4918,-4.17092 17.4875,-5.49606 5.34399,-1.99857 10.84,-3.34543 16.5099,-3.99713 5.66985,-0.67343 11.1659,-0.999283 16.4882,-0.999283 31.3471,0 59.8484,10.9921 85.5039,32.9981 25.6772,21.9842 38.4941,49.3342 38.4941,81.9847 0,5.34399 -0.325853,11.0138 -0.999283,17.0095 -0.651706,5.9957 -1.99857,12.339 -3.99713,19.0081 -0.67343,2.65027 -1.49892,5.64812 -2.49821,8.99355 -0.999283,3.3237 -2.17235,6.32155 -3.49749,8.99355 -8.66769,18.0088 -21.3325,32.4984 -37.9945,43.5123 -16.662,10.9921 -34.3449,20.4853 -53.0055,28.5013 -1.99857,0.651706 -4.17092,1.49892 -6.49534,2.49821 -2.34614,0.999283 -4.49677,1.82478 -6.49534,2.49821 -2.02029,0.651706 -4.17092,1.49892 -6.51706,2.49821 -2.32442,0.999283 -4.49677,2.15063 -6.49534,3.49749 -3.3237,1.32514 -6.66913,2.672 -9.99283,3.99713 -3.34543,1.32514 -6.66913,2.672 -10.0146,3.99713 -25.3297,10.6663 -49.4862,23.179 -72.4915,37.4948 -23.0052,14.3375 -41.1661,34.1711 -54.5044,59.5008 -3.99713,7.34256 -7.32084,15.3368 -9.99283,24.0045 -2.672,8.66769 -4.67056,17.3354 -5.9957,26.0031 -0.67343,3.3237 -1.17307,6.84292 -1.49892,10.4925 -0.347577,3.67128 -0.499642,7.16877 -0.499642,10.5142 0,1.99857 0,3.99713 0,5.9957 0,1.99857 0,3.99713 0,5.9957 1.99857,22.6577 8.81976,44.8374 20.4853,66.4958 11.6655,21.6801 27.502,38.8417 47.5094,51.5065 10.6663,6.66913 21.6584,11.9914 32.9981,15.9885 11.3397,4.01886 22.6577,7.34256 33.9973,10.0146 5.9957,0.67343 12.0131,1.32514 18.0088,1.99857 5.9957,0.67343 11.6655,0.999283 16.9878,0.999283 0.67343,0 1.49892,0 2.49821,0 0.999283,0 2.17235,0 3.49749,0 31.3471,-1.32514 61.5211,-9.99283 90.5003,-26.0031 29.0009,-15.9885 51.5065,-38.6679 67.5168,-67.9947l-60.0004 -38.9938c-8.66769,13.99 -18.3347,25.8293 -29.0009,35.4963 -10.6663,9.66698 -21.3325,17.1616 -31.9988,22.4839 -8.01599,4.01886 -16.1623,7.01671 -24.5042,9.01527 -8.34184,1.99857 -16.1623,2.99785 -23.5049,2.99785 -24.6562,0 -46.1625,-8.84148 -64.4972,-26.5027 -18.3347,-17.6612 -27.502,-38.1683 -27.502,-61.4994 0,-5.34399 0.67343,-10.84 1.99857,-16.5099 1.34686,-5.64812 3.34543,-11.4918 5.9957,-17.4875 6.01742,-12.0131 15.3368,-24.0045 28.0017,-35.9959 12.6648,-12.0131 29.3485,-22.3318 50.0076,-30.9995l87.0028 -38.0162z"/>
<glyph unicode="T" horiz-adv-x="454" d="M233.007 0l0 548.997 -173.006 0 0 69.9933 423.001 0 0 -69.9933 -173.006 0 0 -548.997 -76.9882 0z"/>
<glyph unicode="U" horiz-adv-x="606" d="M72.9911 618.991l74.0121 0 0 -383.985c0,-58.6753 12.339,-103.839 36.9952,-135.511 24.6779,-31.6512 67.9947,-47.4877 129.994,-47.4877 58.6753,0 100.667,15.6627 126.018,46.988 25.3297,31.3471 37.9945,74.6638 37.9945,130.015l0 389.981 74.9897 0 0 -383.985c0,-31.3471 -2.99785,-62.3466 -8.99355,-92.9985 -5.9957,-30.6736 -19.334,-58.6753 -39.993,-84.005 -23.3311,-28.6751 -51.8324,-47.6615 -85.5039,-57.0026 -33.6715,-9.34112 -68.4943,-14.3375 -104.512,-14.9892 -84.6567,0.651706 -145.656,21.8322 -182.999,63.4979 -37.3211,41.6658 -56.655,103.491 -58.0019,185.497l0 383.985z"/>
</font>
<font id="FontID0" horiz-adv-x="635" font-variant="normal" style="fill-rule:nonzero" font-weight="400">
<font-face
font-family="Corbel">
<font-face-src>
<font-face-name name="Corbel"/>
</font-face-src>
</font-face>
<missing-glyph><path d="M0 0z"/></missing-glyph>
<glyph unicode="A" horiz-adv-x="635" d="M17.5002 0l265.497 653 68.9994 0 266.499 -653 -86.4996 0 -76.6671 196.002 -275.33 0 -77.0009 -196.002 -85.4981 0zm299.496 552.005c-29.3255,-81.3405 -57.3258,-155.337 -83.829,-221.838l-25.1679 -62.1712 218.5 0 -25.1679 62.3331c-26.8269,67.6742 -54.1596,141.509 -82.3319,221.676l-2.00291 0z"/>
<glyph unicode="C" horiz-adv-x="589" d="M399.328 594.997c-36.6594,0 -70.8303,-5.82666 -102.664,-17.3282 -31.8342,-11.5016 -59.5007,-28.8399 -82.9995,-51.6711 -23.3269,-22.993 -41.8285,-51.4992 -55.333,-85.4981 -13.4944,-33.9989 -20.3326,-73.6627 -20.3326,-118.829 0,-45.0049 6.33244,-83.8391 18.8355,-116.998 12.503,-33.0076 30.3371,-60.3403 53.3301,-82.0082 23.165,-21.6679 50.8315,-37.6608 83.3333,-47.9991 32.5018,-10.5001 68.6655,-15.6591 108.501,-15.6591 11.0059,0 22.4974,0.49567 34.6666,1.65898 12.1692,1.00146 24.5003,2.67055 36.8314,4.67346 12.3412,1.9928 24.3384,4.32953 36.1738,7.00008 11.6634,2.66044 22.1636,5.49284 31.3284,8.65906l0 -69.667c-19.1693,-7.49575 -41.4947,-13.1606 -66.8346,-17.3282 -25.5017,-4.00583 -51.4992,-5.99862 -78.1642,-5.99862 -54.3316,0 -102.664,7.49575 -144.665,22.6592 -42.0005,15.1736 -77.1729,37.0033 -105.669,65.3375 -28.496,28.3341 -50.002,62.8389 -64.6698,103.666 -14.6678,40.999 -21.9916,87.3392 -21.9916,139 0,50.8315 7.6576,97.5055 23.165,140.163 15.4973,42.6681 37.8328,79.3376 66.9964,110.008 29.1636,30.4989 64.4979,54.4934 106.003,71.4979 41.6667,17.1664 88.3305,25.6636 140.002,25.6636 13.6663,0 27.3327,-0.49567 40.6652,-1.66909 13.3325,-1.16331 26.1593,-2.8324 38.3285,-4.8252 12.1692,-2.17488 23.4988,-4.67346 33.9989,-7.50587 10.3383,-2.99425 19.3413,-5.99862 26.837,-9.16485l0 -69.839c-19.8369,6.17059 -41.5048,11.5016 -64.8317,15.6693 -23.4988,4.16768 -46.9977,6.33244 -70.8404,6.33244z"/>
<glyph unicode="E" horiz-adv-x="551" d="M163.005 72.0037l334.992 0 0 -72.0037 -414.998 0 0 653 396.83 0 0 -72.0037 -316.824 0 0 -210.994 281.824 0 0 -72.0037 -281.824 0 0 -225.995z"/>
<glyph unicode="H" horiz-adv-x="667" d="M163.005 370.003l340.991 0 0 282.997 80.0053 0 0 -653 -80.0053 0 0 297.999 -340.991 0 0 -297.999 -80.0053 0 0 653 80.0053 0 0 -282.997z"/>
<glyph unicode="L" horiz-adv-x="520" d="M163.005 653l0 -580.997 318.827 0 0 -72.0037 -398.833 0 0 653 80.0053 0z"/>
<glyph unicode="M" horiz-adv-x="821" d="M429.332 0l-36.6695 0 -164.33 390.002c-22.6693,53.6639 -45.5005,112.001 -68.3317,175.164l-3.83386 0c4.5015,-90.8291 6.83823,-174.001 6.83823,-249.332l0 -315.833 -80.0053 0 0 653 114.834 0 153.83 -369.497c17.5002,-42.1725 37.0033,-93.1658 58.1654,-152.667l2.33673 0c23.4988,65.995 42.83,116.998 58.1654,152.667l153.84 369.497 114.834 0 0 -653 -80.0053 0 0 315.833c0,73.8347 2.33673,156.996 6.83823,249.332l-3.83386 0c-24.1665,-66.6626 -46.8358,-125.162 -68.3317,-175.164l-164.34 -390.002z"/>
<glyph unicode="O" horiz-adv-x="730" d="M587.997 326.495c0,44.0034 -5.82666,82.6758 -17.3282,116.169 -11.5016,33.5033 -27.3327,61.5036 -47.5034,84.001 -20.3326,22.4974 -44.1653,39.5019 -71.6699,51.0035 -27.3327,11.5016 -56.8301,17.3282 -88.4924,17.3282 -31.5004,0 -61.1698,-5.82666 -88.5025,-17.3282 -27.5047,-11.5016 -51.3373,-28.5061 -71.6699,-51.0035 -20.1606,-22.4974 -36.0019,-50.4977 -47.4933,-84.001 -11.5016,-33.4932 -17.3384,-72.1656 -17.3384,-116.169 0,-43.9933 5.83677,-82.4937 17.5002,-115.997 11.6634,-33.3313 27.6665,-61.1698 47.8373,-83.6672 20.3326,-22.4974 44.1653,-39.3299 71.6598,-50.6595 27.3327,-11.5016 57.0021,-17.1664 89.0083,-17.1664 31.5004,0 60.9978,5.66481 87.9967,17.1664 27.1607,11.3296 50.8315,28.1622 71.1641,50.6595 20.1708,22.4974 36.0019,50.3358 47.5034,83.6672 11.5016,33.5033 17.3282,72.0037 17.3282,115.997zm79.0038 0c0,-49.4962 -7.17205,-94.8248 -21.3341,-136.33 -14.162,-41.3328 -34.5047,-77.0009 -60.9978,-106.832 -26.5032,-30.0032 -58.3374,-53.3301 -95.5025,-70.1627 -37.3371,-16.8326 -79.0038,-25.1679 -125.162,-25.1679 -47.8373,0 -90.5054,8.33536 -128.338,25.1679 -37.671,16.8326 -69.667,40.1594 -95.8364,70.1627 -26.1593,29.8313 -46.158,65.4993 -59.9964,106.832 -13.8383,41.5048 -20.8283,86.8334 -20.8283,136.33 0,49.8402 7.16193,95.5025 21.4959,137.007 14.334,41.4947 34.6666,77.3347 60.9978,107.328 26.3312,29.8414 58.1654,53.1682 95.6644,70.0008 37.3371,16.8326 79.3376,25.1679 125.84,25.1679 47.4933,0 89.9996,-8.33536 127.499,-25.1679 37.6608,-16.8326 69.495,-40.1594 95.6644,-70.0008 26.1694,-29.9931 46.1682,-65.8331 59.9964,-107.328 13.8383,-41.5048 20.8384,-87.1672 20.8384,-137.007z"/>
<glyph unicode="R" horiz-adv-x="591" d="M163.005 269.999l0 -269.999 -80.0053 0 0 653 169.499 0c28.668,0 53.0064,-1.00146 73.0052,-3.16622 19.9988,-2.16476 38.3285,-5.50295 54.8272,-10.0045 45.6725,-12.3311 80.5009,-33.4932 104.506,-63.3345 24.1665,-29.6593 36.1637,-66.9964 36.1637,-111.496 0,-26.5032 -4.16768,-50.002 -12.6649,-70.8303 -8.49721,-20.8384 -20.3326,-39.0062 -35.668,-54.3316 -15.3354,-15.3354 -33.6651,-27.8385 -54.9992,-37.5091 -21.3341,-9.83248 -45.0049,-16.9944 -71.0023,-21.4959l0 -2.00291 193.332 -278.83 -79.9951 0 -200.999 269.999 -95.9982 0zm0 310.998l0 -238.994 78.6599 0c24.3384,0 45.1667,0.829489 62.5051,2.49858 17.1664,1.49713 32.6637,4.5015 46.33,8.66918 27.6665,8.49721 49.0006,21.9916 64.0022,40.4932 15.0016,18.5017 22.4974,42.8401 22.4974,72.6714 -0.333819,28.0003 -7.49575,50.4977 -21.4959,67.6641 -14.0002,17.0045 -33.3414,29.3356 -58.1654,36.8314 -11.6735,3.50004 -25.6737,6.17059 -42.0005,7.66772 -16.175,1.66909 -36.8415,2.49858 -61.9993,2.49858l-90.3334 0z"/>
<glyph unicode="S" horiz-adv-x="551" d="M147.002 480.831c0,-19.1592 3.83386,-35.0004 11.6634,-47.4933 7.83969,-12.675 18.1678,-23.0032 31.3385,-31.1665 13.1606,-8.00154 28.3341,-14.8398 45.6624,-20.0089 17.3384,-5.15902 35.4961,-9.99434 54.1697,-14.6577 25.3298,-6.17059 50.1639,-13.0088 74.6642,-20.5046 24.5003,-7.49575 46.1682,-17.834 65.3375,-31.0047 19.1592,-13.1606 34.6666,-30.3269 46.4919,-51.4992 11.8354,-21.1621 17.6722,-48.3329 17.6722,-81.6642 0,-33.827 -6.33244,-63.0007 -19.1693,-87.6629 -12.8369,-24.5003 -30.6608,-44.671 -53.3301,-60.5021 -22.6693,-15.8311 -49.3344,-27.5047 -80.3391,-35.1623 -30.9946,-7.66772 -64.8317,-11.5016 -101.501,-11.5016 -16.9944,0 -34.3328,1.00146 -51.9948,3.16622 -17.834,2.16476 -34.6666,4.99717 -50.8315,8.49721 -16.1649,3.50004 -30.6709,7.66772 -43.6696,12.1692 -12.9987,4.5015 -23.337,9.16485 -30.8327,13.6663l0 72.4994c11.6634,-5.83677 24.8341,-11.0059 39.5019,-15.8311 14.6678,-4.83532 29.8313,-9.00299 45.5005,-12.3412 15.6693,-3.32807 31.3284,-5.99862 47.3315,-7.99142 16.0031,-1.84106 31.0047,-2.8324 44.9947,-2.8324 22.6693,0 44.5092,1.9928 65.1756,5.82666 20.6664,4.00583 38.8343,10.5001 54.3316,19.5031 15.6693,9.16485 28.0003,21.6679 37.1652,37.327 9.16485,15.8412 13.6663,35.5062 13.6663,59.3388 0,19.5031 -3.99571,35.668 -11.9972,48.3329 -7.83969,12.6649 -18.5017,23.165 -31.8342,31.5004 -13.3325,8.33536 -28.668,15.0016 -46.0063,20.3326 -17.5002,5.16913 -35.6579,10.0045 -54.8272,14.4958 -25.5017,6.00874 -50.1639,12.503 -74.3405,19.8369 -24.3283,7.3339 -45.8242,17.5002 -64.8317,30.4989 -18.9973,12.9987 -34.3328,29.8313 -45.8343,50.3358 -11.4915,20.4945 -17.3282,46.8358 -17.3282,78.67 0,33.1593 5.99862,61.8273 18.1678,85.6599 12.1692,24.0046 28.668,43.8314 49.3344,59.5007 20.8283,15.4973 44.6609,27.1708 71.6598,34.6666 26.9989,7.50587 55.8388,11.1678 86.4996,11.1678 34.8386,0 67.1684,-3.32807 97.3335,-9.99434 30.1752,-6.67638 57.6697,-15.5074 82.8377,-26.1694l0 -73.8347c-26.9989,11.3296 -54.9992,20.6664 -83.829,27.8284 -28.8399,7.17205 -59.6727,10.8339 -92.5083,11.1678 -24.6621,0 -46.158,-2.66044 -64.4979,-8.00154 -18.1678,-5.33099 -33.3313,-12.9987 -45.3286,-22.993 -12.0074,-9.83248 -21.0002,-21.8398 -26.837,-36.0019 -5.83677,-14.162 -8.83103,-29.8313 -8.83103,-47.1696z"/>
<glyph unicode="T" horiz-adv-x="555" d="M317.998 0l-79.9951 0 0 580.997 -218.338 0 0 72.0037 516.671 0 0 -72.0037 -218.338 0 0 -580.997z"/>
</font>
<style type="text/css">
<![CDATA[
@font-face { font-family:"Futura_Book-Normal";font-variant:normal;font-weight:normal;src:url("#FontID1") format(svg)}
@font-face { font-family:"Corbel";font-variant:normal;font-weight:normal;src:url("#FontID0") format(svg)}
.fil7 {fill:#A1A1A1}
.fil0 {fill:#1C4983}
.fil6 {fill:#272E42}
.fil4 {fill:#FEFEFE;fill-rule:nonzero}
.fil2 {fill:url(#id6)}
.fil1 {fill:url(#id7);fill-rule:nonzero}
.fil5 {fill:url(#id8);fill-rule:nonzero}
.fil3 {fill:url(#id9);fill-rule:nonzero}
.fnt1 {font-weight:normal;font-size:460.33px;font-family:'Futura_Book-Normal'}
.fnt0 {font-weight:normal;font-size:988.56px;font-family:'Corbel'}
]]>
</style>
<mask id="id0">
<linearGradient id="id1" gradientUnits="userSpaceOnUse" x1="4213.8" y1="3203.52" x2="3637.47" y2="3895.11">
<stop offset="0" style="stop-opacity:0.266667; stop-color:white"/>
<stop offset="1" style="stop-opacity:0; stop-color:white"/>
</linearGradient>
<rect style="fill:url(#id1)" x="3384.38" y="2221.46" width="2393.29" height="1082.77"/>
</mask>
<mask id="id2">
<linearGradient id="id3" gradientUnits="userSpaceOnUse" x1="7914.83" y1="1369.16" x2="4815" y2="4077.55">
<stop offset="0" style="stop-opacity:1; stop-color:white"/>
<stop offset="1" style="stop-opacity:0; stop-color:white"/>
</linearGradient>
<rect style="fill:url(#id3)" x="3375.58" y="2036.2" width="3347.61" height="1690.14"/>
</mask>
<mask id="id4">
<linearGradient id="id5" gradientUnits="userSpaceOnUse" x1="2077.44" y1="6592.85" x2="5177.27" y2="3884.46">
<stop offset="0" style="stop-opacity:1; stop-color:white"/>
<stop offset="1" style="stop-opacity:0; stop-color:white"/>
</linearGradient>
<rect style="fill:url(#id5)" x="3269.08" y="4235.67" width="3347.61" height="1690.14"/>
</mask>
<radialGradient id="id6" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.31579 -0 -0 1.31579 -1756 -1317)" cx="5560.36" cy="4170.27" r="1072.44" fx="5560.36" fy="4170.27">
<stop offset="0" style="stop-opacity:1; stop-color:#1167B4"/>
<stop offset="1" style="stop-opacity:1; stop-color:#121445"/>
</radialGradient>
<linearGradient id="id7" gradientUnits="userSpaceOnUse" x1="4213.8" y1="3203.52" x2="3637.47" y2="3895.11">
<stop offset="0" style="stop-opacity:1; stop-color:#34262A"/>
<stop offset="1" style="stop-opacity:1; stop-color:#34262A"/>
</linearGradient>
<radialGradient id="id8" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-1.25168 -1.30198 1.30198 -1.25168 7296 20245)" cx="6324.41" cy="5333.93" r="1255.85" fx="6324.41" fy="5333.93">
<stop offset="0" style="stop-opacity:1; stop-color:#DAEFFB"/>
<stop offset="0.458824" style="stop-opacity:1; stop-color:#7DA7D2"/>
<stop offset="1" style="stop-opacity:1; stop-color:#215FAA"/>
</radialGradient>
<radialGradient id="id9" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.25168 1.30198 -1.30198 1.25168 3446 -9496)" xlink:href="#id8" cx="6537.38" cy="3910.51" r="1255.85" fx="6537.38" fy="3910.51">
</radialGradient>
</defs>
<g id="Слой_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<g id="_2169686765088">
<g>
<path class="fil0" d="M6316.91 5144.71c-37.7,-45.26 103.2,-202.59 164.65,-302.47 61.46,-99.87 141.84,-144.16 179.56,-98.9 37.7,45.26 18.44,162.93 -43.01,262.79 -61.45,99.87 -263.5,183.84 -301.2,138.58z"/>
<ellipse class="fil0" transform="matrix(0.783933 0.940964 -0.788558 1.28161 3442.43 3037.82)" rx="87.09" ry="141.11"/>
<path class="fil1" style="mask:url(#id0)" d="M4186.29 2241.74c-331.43,161.85 -608.75,417.14 -798.1,731.42 327,-253.05 741.2,33.71 890.21,314.29 199.69,-111.78 428.56,-137.1 664.5,-43.38 926.58,368.05 1539.9,-1194.63 -756.61,-1002.33z"/>
<circle class="fil2" cx="4992.79" cy="3957.43" r="1773.65"/>
<path class="fil3" d="M5284.31 3762.35c829.07,1128.43 1663.76,840.31 1609.21,-21.7 -100.37,-957.86 -910.36,-1704.45 -1894.78,-1704.45 -701.76,0 -1314.9,379.4 -1645.51,944.26 -22.81,57.92 -42.78,94.04 -44.05,160.5 415.44,-604.44 1220.9,-298.19 1975.13,621.39z"/>
<path class="fil4" style="mask:url(#id2)" d="M5359.46 2774.34c559.61,611.23 822.08,1023.4 1135.2,941.68 243.48,-63.57 334.04,-413.21 62.3,-871.05 -344.86,-489.19 -914.19,-808.77 -1558.22,-808.77 -686.27,0 -1287.74,362.85 -1623.16,907.14 508.33,-671.6 1426.21,-778.15 1983.88,-169z"/>
<path class="fil5" d="M4707.96 4199.66c-829.06,-1128.43 -1663.76,-840.31 -1609.21,21.71 100.37,957.85 910.36,1704.44 1894.78,1704.44 701.76,0 1314.9,-379.4 1645.51,-944.26 22.81,-57.92 42.78,-94.03 44.05,-160.5 -415.44,604.44 -1220.89,298.19 -1975.13,-621.39z"/>
<path class="fil4" style="mask:url(#id4)" d="M4632.81 5187.67c-559.61,-611.23 -822.08,-1023.4 -1135.2,-941.68 -243.48,63.57 -334.04,413.21 -62.3,871.05 344.86,489.19 914.19,808.77 1558.22,808.77 686.27,0 1287.74,-362.85 1623.16,-907.13 -508.33,671.6 -1426.21,778.14 -1983.88,168.99z"/>
</g>
<g transform="matrix(1.22551 0 0 1 -5480.09 2301.48)">
<text x="5000" y="5000" class="fil6 fnt0">SMARTSOLTECH</text>
</g>
<g transform="matrix(1.11844 0 0 1 -4910.74 2960.81)">
<text x="5000" y="5000" class="fil7 fnt1">FUTURE BEGINS HERE</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -1,18 +1,40 @@
from django.contrib import admin
from .models import Service, Project, Client, Order, Review, BlogPost, Category, ServiceRequest
from .models import Service, Project, Client, Order, Review, BlogPost, Category, ServiceRequest, HeroBanner
from .forms import ProjectForm
@admin.register(HeroBanner)
class HeroBannerAdmin(admin.ModelAdmin):
list_display = ('title', 'is_active', 'order', 'created_at')
list_filter = ('is_active', 'created_at')
search_fields = ('title', 'subtitle')
fields = ('title', 'subtitle', 'description', 'image', 'video', 'video_poster',
'button_text', 'button_link', 'is_active', 'order')
list_editable = ('is_active', 'order')
@admin.register(Service)
class ServiceAdmin(admin.ModelAdmin):
list_display = ('name', 'category', 'price')
list_display = ('name', 'category', 'price', 'has_video')
search_fields = ('name', 'category')
fields = ('name', 'description', 'price', 'category', 'image', 'video', 'video_poster')
def has_video(self, obj):
return bool(obj.video)
has_video.boolean = True
has_video.short_description = 'Есть видео'
@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
form = ProjectForm
list_display = ('name', 'client','service', 'status', 'order', 'description')
list_display = ('name', 'client','service', 'status', 'order', 'has_video')
list_filter = ('name', 'client','service', 'status', 'order')
search_fields = ('name', 'client','service', 'status', 'order', 'client__first_name', 'client__last_name')
fields = ('name', 'description', 'completion_date', 'client', 'service', 'order',
'category', 'image', 'video', 'video_poster', 'status')
def has_video(self, obj):
return bool(obj.video)
has_video.boolean = True
has_video.short_description = 'Есть видео'
@admin.register(Client)
class ClientAdmin(admin.ModelAdmin):
@@ -27,14 +49,26 @@ class OrderAdmin(admin.ModelAdmin):
@admin.register(Review)
class ReviewAdmin(admin.ModelAdmin):
list_display = ('client', 'service', 'rating', 'review_date')
list_display = ('client', 'service', 'rating', 'review_date', 'has_video')
list_filter = ('rating',)
search_fields = ('client__first_name', 'service__name')
fields = ('client', 'service', 'project', 'rating', 'comment', 'image', 'video', 'video_poster')
def has_video(self, obj):
return bool(obj.video)
has_video.boolean = True
has_video.short_description = 'Есть видео'
@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
list_display = ('title', 'published_date')
list_display = ('title', 'published_date', 'has_video')
search_fields = ('title',)
fields = ('title', 'content', 'image', 'video', 'video_poster')
def has_video(self, obj):
return bool(obj.video)
has_video.boolean = True
has_video.short_description = 'Есть видео'
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):

View File

@@ -0,0 +1,75 @@
# Generated by Django 5.1.1 on 2025-11-24 23:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('web', '0009_alter_servicerequest_options_and_more'),
]
operations = [
migrations.CreateModel(
name='HeroBanner',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200, verbose_name='Заголовок')),
('subtitle', models.TextField(blank=True, verbose_name='Подзаголовок')),
('description', models.TextField(blank=True, verbose_name='Описание')),
('image', models.ImageField(blank=True, null=True, upload_to='static/img/hero/', verbose_name='Фоновое изображение')),
('video', models.FileField(blank=True, help_text='Фоновое видео для баннера (MP4, WebM)', null=True, upload_to='static/video/hero/', verbose_name='Фоновое видео')),
('video_poster', models.ImageField(blank=True, help_text='Превью изображение для видео', null=True, upload_to='static/img/hero/posters/', verbose_name='Превью видео')),
('button_text', models.CharField(blank=True, max_length=100, verbose_name='Текст кнопки')),
('button_link', models.URLField(blank=True, verbose_name='Ссылка кнопки')),
('is_active', models.BooleanField(default=True, verbose_name='Активен')),
('order', models.PositiveIntegerField(default=0, verbose_name='Порядок отображения')),
('created_at', models.DateTimeField(auto_now_add=True)),
],
options={
'verbose_name': 'Hero Баннер',
'verbose_name_plural': 'Hero Баннеры',
'ordering': ['order', '-created_at'],
},
),
migrations.AddField(
model_name='blogpost',
name='video',
field=models.FileField(blank=True, help_text='Видео файл для блог поста', null=True, upload_to='static/video/blog/'),
),
migrations.AddField(
model_name='blogpost',
name='video_poster',
field=models.ImageField(blank=True, help_text='Превью изображение для видео', null=True, upload_to='static/img/blog/posters/'),
),
migrations.AddField(
model_name='project',
name='video',
field=models.FileField(blank=True, help_text='Видео презентация проекта', null=True, upload_to='static/video/project/'),
),
migrations.AddField(
model_name='project',
name='video_poster',
field=models.ImageField(blank=True, help_text='Превью изображение для видео проекта', null=True, upload_to='static/img/project/posters/'),
),
migrations.AddField(
model_name='review',
name='video',
field=models.FileField(blank=True, help_text='Видео отзыв о работе', null=True, upload_to='static/video/review/'),
),
migrations.AddField(
model_name='review',
name='video_poster',
field=models.ImageField(blank=True, help_text='Превью для видео отзыва', null=True, upload_to='static/img/review/posters/'),
),
migrations.AddField(
model_name='service',
name='video',
field=models.FileField(blank=True, help_text='Видео файл для услуги (MP4, WebM, AVI)', null=True, upload_to='static/video/services/'),
),
migrations.AddField(
model_name='service',
name='video_poster',
field=models.ImageField(blank=True, help_text='Превью изображение для видео', null=True, upload_to='static/img/services/posters/'),
),
]

View File

@@ -0,0 +1,13 @@
# Generated by Django 5.1.1 on 2025-11-25 01:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('web', '0010_herobanner_blogpost_video_blogpost_video_poster_and_more'),
]
operations = [
]

View File

@@ -3,6 +3,30 @@ from django.contrib.auth.models import AbstractUser, User
import uuid
from django.urls import reverse
class HeroBanner(models.Model):
"""Модель для главного баннера на сайте"""
title = models.CharField(max_length=200, verbose_name="Заголовок")
subtitle = models.TextField(blank=True, verbose_name="Подзаголовок")
description = models.TextField(blank=True, verbose_name="Описание")
image = models.ImageField(upload_to='static/img/hero/', blank=True, null=True, verbose_name="Фоновое изображение")
video = models.FileField(upload_to='static/video/hero/', blank=True, null=True,
help_text='Фоновое видео для баннера (MP4, WebM)', verbose_name="Фоновое видео")
video_poster = models.ImageField(upload_to='static/img/hero/posters/', blank=True, null=True,
help_text='Превью изображение для видео', verbose_name="Превью видео")
button_text = models.CharField(max_length=100, blank=True, verbose_name="Текст кнопки")
button_link = models.URLField(blank=True, verbose_name="Ссылка кнопки")
is_active = models.BooleanField(default=True, verbose_name="Активен")
order = models.PositiveIntegerField(default=0, verbose_name="Порядок отображения")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Hero Баннер'
verbose_name_plural = 'Hero Баннеры'
ordering = ['order', '-created_at']
def __str__(self):
return self.title
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(default='Описание категории')
@@ -21,6 +45,10 @@ class Service(models.Model):
price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='services')
image = models.ImageField(upload_to='static/img/services/', blank=True, null=True)
video = models.FileField(upload_to='static/video/services/', blank=True, null=True, help_text='Видео файл для услуги (MP4, WebM, AVI)')
video_poster = models.ImageField(upload_to='static/img/services/posters/', blank=True, null=True, help_text='Превью изображение для видео')
video = models.FileField(upload_to='static/video/services/', blank=True, null=True, help_text='Видео файл для услуги (MP4, WebM, AVI)')
video_poster = models.ImageField(upload_to='static/img/services/posters/', blank=True, null=True, help_text='Превью изображение для видео')
class Meta:
verbose_name = 'Услуга'
@@ -61,6 +89,8 @@ class BlogPost(models.Model):
content = models.TextField()
published_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='static/img/blog/', blank=True, null=True)
video = models.FileField(upload_to='static/video/blog/', blank=True, null=True, help_text='Видео файл для блог поста')
video_poster = models.ImageField(upload_to='static/img/blog/posters/', blank=True, null=True, help_text='Превью изображение для видео')
class Meta:
verbose_name = 'Блог'
@@ -126,6 +156,8 @@ class Project(models.Model):
order = models.OneToOneField(Order, on_delete=models.CASCADE, related_name='project', null=True, blank=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
image = models.ImageField(upload_to='static/img/project/', blank=True, null=True)
video = models.FileField(upload_to='static/video/project/', blank=True, null=True, help_text='Видео презентация проекта')
video_poster = models.ImageField(upload_to='static/img/project/posters/', blank=True, null=True, help_text='Превью изображение для видео проекта')
status = models.CharField(max_length=50, choices=[('in_progress', 'В процессе'), ('completed', 'Завершен')], default='in_progress')
class Meta:
@@ -144,6 +176,8 @@ class Review(models.Model):
comment = models.TextField()
review_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='static/img/review/', blank=True, null=True)
video = models.FileField(upload_to='static/video/review/', blank=True, null=True, help_text='Видео отзыв о работе')
video_poster = models.ImageField(upload_to='static/img/review/posters/', blank=True, null=True, help_text='Превью для видео отзыва')
class Meta:
verbose_name = 'Отзыв'

View File

@@ -9,7 +9,7 @@
<div class="row align-items-center">
<div class="col-lg-6">
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
🚀 О нас
О нас
</span>
<h1 class="display-4 fw-bold mb-4">
Мы создаем <span class="text-gradient">цифровое будущее</span>
@@ -87,7 +87,7 @@
<div class="col-lg-6">
<div class="pe-lg-4">
<span class="badge bg-primary text-white mb-3 px-3 py-2 rounded-pill">
🎯 Наша миссия
Наша миссия
</span>
<h2 class="display-6 fw-bold mb-4">
Делаем технологии <span class="text-gradient">доступными</span>
@@ -291,7 +291,7 @@
<div class="container-modern">
<div class="text-center mb-5">
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
Технологии
Технологии
</span>
<h2 class="display-6 fw-bold mb-3">
Современный <span class="text-gradient">технологический стек</span>

View File

@@ -5,104 +5,192 @@
{% block content %}
<!-- Hero Section -->
<section class="hero-modern" id="home">
<div class="container-modern">
<div class="row align-items-center min-vh-100">
<div class="col-lg-6">
<div class="animate-fade-in-up">
<h1 class="display-3 fw-bold mb-4">
Создаем <span class="text-gradient">будущее</span> вашего бизнеса
</h1>
<p class="lead mb-4 text-muted">
Мы разрабатываем современные веб-приложения, мобильные решения и системы автоматизации,
которые помогают компаниям расти и быть конкурентоспособными.
</p>
<div class="d-flex flex-wrap gap-3 mb-5">
<a href="{% url 'services' %}" class="btn btn-primary-modern btn-lg">
<i class="fas fa-rocket me-2"></i>
Начать проект
</a>
<a href="{% url 'about' %}" class="btn btn-secondary-modern btn-lg">
<i class="fas fa-play-circle me-2"></i>
Узнать больше
</a>
{% if hero_banners %}
<!-- Hero Carousel for Multiple Banners -->
<div id="heroCarousel" class="carousel slide carousel-fade" data-bs-ride="carousel">
<!-- Hero Container with rounded corners -->
<div class="hero-container">
<!-- Custom Carousel Indicators with Pills -->
<div class="carousel-indicators-container">
<div class="outer-pill">
<div class="pill-indicators">
{% for banner in hero_banners %}
<button type="button"
class="pill-indicator {% if forloop.first %}active{% endif %}"
data-bs-target="#heroCarousel"
data-bs-slide-to="{{ forloop.counter0 }}"
data-title="{{ banner.title }}"
aria-label="Slide {{ forloop.counter }}">
<span class="pill-indicator-title">{{ banner.title }}</span>
</button>
{% endfor %}
</div>
</div>
</div>
<div class="row text-center">
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">50+</h3>
<p class="small text-muted mb-0">Проектов</p>
<div class="carousel-inner">
{% for banner in hero_banners %}
<div class="carousel-item {% if forloop.first %}active{% endif %}">
<!-- Hero Background (Video or Image) -->
<div class="hero-bg">
{% if banner.video %}
<!-- Hero Video Background -->
<video class="hero-video"
autoplay muted loop
{% if banner.video_poster %}poster="{{ banner.video_poster.url }}"{% endif %}>
<source src="{{ banner.video.url }}" type="video/mp4">
{% if banner.image %}
<!-- Fallback image -->
<img src="{{ banner.image.url }}" alt="{{ banner.title }}">
{% endif %}
</video>
{% elif banner.image %}
<!-- Hero Image Background -->
<img src="{{ banner.image.url }}" alt="{{ banner.title }}">
{% endif %}
<!-- Gradient Overlay -->
<div class="hero-overlay"></div>
<!-- Hero Content -->
<div class="hero-content">
<div class="row align-items-center w-100">
<div class="col-lg-8 col-xl-7">
<div class="animate-fade-in-up">
<h1 class="hero-title">
{{ banner.title }}
</h1>
{% if banner.subtitle %}
<h2 class="hero-subtitle">
{{ banner.subtitle }}
</h2>
{% endif %}
{% if banner.description %}
<p class="hero-description">
{{ banner.description }}
</p>
{% endif %}
<div class="d-flex flex-wrap gap-3">
{% if banner.button_text and banner.button_link %}
<a href="{{ banner.button_link }}" class="btn btn-light btn-lg px-4">
<i class="fas fa-rocket me-2"></i>
{{ banner.button_text }}
</a>
{% endif %}
<a href="{% url 'services' %}" class="btn btn-outline-light btn-lg px-4">
<i class="fas fa-cogs me-2"></i>
Наши услуги
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">3+</h3>
<p class="small text-muted mb-0">Лет опыта</p>
</div>
{% endfor %}
</div>
</div>
</div>
{% else %}
<!-- Default Hero Section (fallback) -->
<div class="container-modern">
<div class="row align-items-center min-vh-100">
<div class="col-lg-6">
<div class="animate-fade-in-up">
<h1 class="display-3 fw-bold mb-4">
Создаем <span class="text-gradient">будущее</span> вашего бизнеса
</h1>
<p class="lead mb-4 text-muted">
Мы разрабатываем современные веб-приложения, мобильные решения и системы автоматизации,
которые помогают компаниям расти и быть конкурентоспособными.
</p>
<div class="d-flex flex-wrap gap-3 mb-5">
<a href="{% url 'services' %}" class="btn btn-primary-modern btn-lg">
<i class="fas fa-rocket me-2"></i>
Начать проект
</a>
<a href="{% url 'about' %}" class="btn btn-secondary-modern btn-lg">
<i class="fas fa-play-circle me-2"></i>
Узнать больше
</a>
</div>
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">24/7</h3>
<p class="small text-muted mb-0">Поддержка</p>
<div class="row text-center">
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">50+</h3>
<p class="small text-muted mb-0">Проектов</p>
</div>
</div>
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">3+</h3>
<p class="small text-muted mb-0">Лет опыта</p>
</div>
</div>
<div class="col-4">
<div class="stat-item">
<h3 class="text-gradient fw-bold mb-1">24/7</h3>
<p class="small text-muted mb-0">Поддержка</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="text-center animate-float">
<div class="position-relative">
<!-- 3D Graphic Placeholder -->
<div class="hero-graphic p-5">
<div class="position-relative">
<!-- Code Window -->
<div class="code-window bg-dark rounded-4 p-4 mb-4 shadow-lg"
style="transform: rotate(-5deg); max-width: 400px;">
<div class="d-flex gap-2 mb-3">
<div class="rounded-circle bg-danger" style="width: 12px; height: 12px;"></div>
<div class="rounded-circle bg-warning" style="width: 12px; height: 12px;"></div>
<div class="rounded-circle bg-success" style="width: 12px; height: 12px;"></div>
<div class="col-lg-6">
<div class="text-center animate-float">
<div class="position-relative">
<!-- 3D Graphic Placeholder -->
<div class="hero-graphic p-5">
<div class="position-relative">
<!-- Code Window -->
<div class="code-window bg-dark rounded-4 p-4 mb-4 shadow-lg"
style="transform: rotate(-5deg); max-width: 400px;">
<div class="d-flex gap-2 mb-3">
<div class="rounded-circle bg-danger" style="width: 12px; height: 12px;"></div>
<div class="rounded-circle bg-warning" style="width: 12px; height: 12px;"></div>
<div class="rounded-circle bg-success" style="width: 12px; height: 12px;"></div>
</div>
<div class="text-light font-monospace small">
<div class="text-info">def create_future():</div>
<div class="ms-3 text-success">return innovation + passion</div>
<div class="text-warning">// SmartSolTech</div>
</div>
</div>
<div class="text-light font-monospace small">
<div class="text-info">def create_future():</div>
<div class="ms-3 text-success">return innovation + passion</div>
<div class="text-warning">// SmartSolTech</div>
<!-- Mobile Preview -->
<div class="mobile-preview position-absolute bg-white rounded-4 p-3 shadow"
style="transform: rotate(10deg); top: 50px; right: 50px; width: 200px;">
<div class="bg-gradient rounded-3 p-3 text-white text-center">
<i class="fas fa-mobile-alt fa-3x mb-2"></i>
<h6 class="mb-1">Мобильные</h6>
<p class="small mb-0 opacity-75">приложения</p>
</div>
</div>
<!-- Floating Icons -->
<div class="floating-icon position-absolute"
style="top: 20px; left: 20px; animation: float 2s ease-in-out infinite;">
<div class="bg-primary rounded-3 p-3 text-white shadow">
<i class="fab fa-react fa-2x"></i>
</div>
</div>
<div class="floating-icon position-absolute"
style="bottom: 100px; left: 100px; animation: float 3s ease-in-out infinite reverse;">
<div class="bg-success rounded-3 p-3 text-white shadow">
<i class="fab fa-python fa-2x"></i>
</div>
</div>
</div>
<!-- Mobile App Preview -->
<div class="mobile-preview bg-light rounded-4 p-3 shadow-lg position-absolute"
style="transform: rotate(10deg); top: 50px; right: 50px; width: 200px;">
<div class="bg-gradient rounded-3 p-3 text-white text-center">
<i class="fas fa-mobile-alt fa-3x mb-2"></i>
<h6 class="mb-1">Мобильные</h6>
<p class="small mb-0 opacity-75">приложения</p>
</div>
</div>
<!-- Floating Icons -->
<div class="floating-icon position-absolute"
style="top: 20px; left: 20px; animation: float 2s ease-in-out infinite;">
<div class="bg-primary rounded-3 p-3 text-white shadow">
<i class="fab fa-react fa-2x"></i>
</div>
</div>
<div class="floating-icon position-absolute"
style="bottom: 100px; left: 100px; animation: float 3s ease-in-out infinite reverse;">
<div class="bg-success rounded-3 p-3 text-white shadow">
<i class="fab fa-python fa-2x"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Services Preview Section -->
{% endif %}
</section><!-- Services Preview Section -->
<section class="section-padding bg-light">
<div class="container-modern">
<div class="text-center mb-5">
@@ -272,11 +360,256 @@
</div>
</div>
</section>
<!-- Portfolio Section -->
<section class="section-padding bg-light" id="portfolio">
<div class="container-modern">
<div class="text-center mb-5">
<span class="badge bg-primary rounded-pill px-3 py-2 mb-3">
<i class="fas fa-briefcase me-2"></i>
💼 Портфолио
</span>
<h2 class="display-6 fw-bold mb-3">
Наши <span class="text-gradient">работы</span>
</h2>
<p class="lead text-muted max-width-600 mx-auto">
Избранные проекты, которыми мы гордимся
</p>
</div>
{% if latest_projects %}
<div class="row g-4">
{% for project in latest_projects %}
<div class="col-lg-4">
<div class="project-card bg-white rounded-4 overflow-hidden shadow hover-lift">
{% if project.image %}
<div class="project-image">
<img src="{{ project.image.url }}" alt="{{ project.name }}" class="w-100">
<div class="project-overlay">
<a href="{% url 'project_detail' project.pk %}" class="btn btn-light rounded-circle">
<i class="fas fa-eye"></i>
</a>
</div>
</div>
{% endif %}
<div class="p-4">
<h5 class="mb-3">{{ project.name }}</h5>
<p class="text-muted mb-3">{{ project.description|truncatewords:15 }}</p>
<a href="{% url 'project_detail' project.pk %}" class="text-primary fw-semibold">
Подробнее <i class="fas fa-arrow-right ms-1"></i>
</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% endif %}
<div class="text-center mt-5">
<a href="{% url 'portfolio' %}" class="btn btn-primary-modern btn-lg">
<i class="fas fa-th-large me-2"></i>
Смотреть все проекты
</a>
</div>
</div>
</section>
<!-- Blog Section -->
<section class="section-padding" id="blog">
<div class="container-modern">
<div class="text-center mb-5">
<span class="badge bg-success rounded-pill px-3 py-2 mb-3">
<i class="fas fa-blog me-2"></i>
📝 Блог
</span>
<h2 class="display-6 fw-bold mb-3">
Последние <span class="text-gradient">статьи</span>
</h2>
</div>
{% if latest_blog_posts %}
<div class="row g-4">
{% for post in latest_blog_posts %}
<div class="col-lg-6">
<article class="blog-card bg-white rounded-4 overflow-hidden shadow hover-lift">
{% if post.image %}
<div class="blog-image">
<img src="{{ post.image.url }}" alt="{{ post.title }}" class="w-100">
</div>
{% endif %}
<div class="p-4">
<div class="d-flex align-items-center mb-3">
<span class="text-muted small">{{ post.created_at|date:"d F Y" }}</span>
</div>
<h5 class="mb-3">{{ post.title }}</h5>
<p class="text-muted mb-3">{{ post.content|truncatewords:25 }}</p>
<a href="{% url 'blog_post_detail' post.pk %}" class="text-primary fw-semibold">
Читать далее <i class="fas fa-arrow-right ms-1"></i>
</a>
</div>
</article>
</div>
{% endfor %}
</div>
{% endif %}
<div class="text-center mt-5">
<a href="{% url 'blog' %}" class="btn btn-primary-modern btn-lg">
<i class="fas fa-blog me-2"></i>
Все статьи
</a>
</div>
</div>
</section>
<!-- News Section -->
<section class="section-padding bg-light" id="news">
<div class="container-modern">
<div class="text-center mb-5">
<span class="badge bg-warning rounded-pill px-3 py-2 mb-3">
<i class="fas fa-newspaper me-2"></i>
📰 Новости
</span>
<h2 class="display-6 fw-bold mb-3">
Последние <span class="text-gradient">новости</span>
</h2>
</div>
<div class="row g-4">
<div class="col-lg-12">
<div class="news-card bg-white rounded-4 p-4 shadow">
<div class="d-flex align-items-center mb-3">
<span class="badge bg-primary rounded-pill px-3 py-1 me-3">24.11.2025</span>
<h5 class="mb-0">Новый сайт</h5>
</div>
<p class="text-muted mb-3">
Поздравляем всех наших клиентов с этой знаменательной датой!
Мы переписали свой сайт! теперь у нас современный дизайн и улучшенная функциональность...
</p>
<a href="{% url 'news' %}" class="text-primary fw-semibold">
Узнать больше <i class="fas fa-arrow-right ms-1"></i>
</a>
</div>
</div>
</div>
<div class="text-center mt-4">
<a href="{% url 'news' %}" class="btn btn-primary-modern btn-lg">
<i class="fas fa-newspaper me-2"></i>
Все новости
</a>
</div>
</div>
</section>
<!-- Career Section -->
<section class="section-padding" id="career">
<div class="container-modern">
<div class="text-center mb-5">
<span class="badge bg-info rounded-pill px-3 py-2 mb-3">
<i class="fas fa-rocket me-2"></i>
🚀 Карьера
</span>
<h2 class="display-6 fw-bold mb-3">
Присоединяйтесь к нашей <span class="text-gradient">команде</span>
</h2>
<p class="lead text-muted max-width-600 mx-auto">
Мы ищем талантливых специалистов, которые разделяют нашу страсть к технологиям и инновациям.
</p>
</div>
<div class="row g-4 mb-5">
<div class="col-lg-4">
<div class="career-feature text-center p-4">
<div class="career-icon bg-primary rounded-3 p-3 mx-auto mb-3 text-white" style="width: fit-content;">
<i class="fas fa-chart-line fa-2x"></i>
</div>
<h6 class="mb-2">Профессиональный рост</h6>
<p class="text-muted small mb-0">Возможности для развития и обучения</p>
</div>
</div>
<div class="col-lg-4">
<div class="career-feature text-center p-4">
<div class="career-icon bg-success rounded-3 p-3 mx-auto mb-3 text-white" style="width: fit-content;">
<i class="fas fa-users fa-2x"></i>
</div>
<h6 class="mb-2">Команда профессионалов</h6>
<p class="text-muted small mb-0">Работайте с лучшими специалистами</p>
</div>
</div>
<div class="col-lg-4">
<div class="career-feature text-center p-4">
<div class="career-icon bg-warning rounded-3 p-3 mx-auto mb-3 text-white" style="width: fit-content;">
<i class="fas fa-clock fa-2x"></i>
</div>
<h6 class="mb-2">Гибкий график</h6>
<p class="text-muted small mb-0">Удаленная работа и гибкое расписание</p>
</div>
</div>
</div>
<div class="text-center">
<div class="career-stats bg-gradient rounded-4 p-4 text-white mb-4" style="max-width: 300px; margin: 0 auto;">
<h3 class="display-4 fw-bold mb-2">0</h3>
<h6 class="mb-2">Открыто вакансий</h6>
<p class="small mb-0 opacity-75">Найдите свою идеальную позицию</p>
</div>
<a href="{% url 'career' %}" class="btn btn-primary-modern btn-lg me-3">
<i class="fas fa-briefcase me-2"></i>
Смотреть вакансии
</a>
<a href="{% url 'career' %}" class="btn btn-outline-primary btn-lg">
Посмотреть все
</a>
</div>
</div>
</section>
{% endblock %}
{% block extra_scripts %}
<script>
document.addEventListener('DOMContentLoaded', function() {
const carousel = document.getElementById('heroCarousel');
const indicators = document.querySelectorAll('.pill-indicator');
let currentActiveIndex = 0;
function updatePillState(index) {
// Обновляем классы индикаторов
indicators.forEach((indicator, i) => {
if (i === index) {
indicator.classList.add('active');
} else {
indicator.classList.remove('active');
}
});
currentActiveIndex = index;
}
// Обработчики событий для индикаторов
indicators.forEach((indicator, index) => {
indicator.addEventListener('click', function() {
currentActiveIndex = index;
updatePillState(index);
});
});
// Bootstrap carousel события
if (carousel) {
carousel.addEventListener('slide.bs.carousel', function(event) {
const nextIndex = event.to;
currentActiveIndex = nextIndex;
updatePillState(nextIndex);
});
// Инициализируем первое состояние
updatePillState(0);
}
// Animate elements on scroll
const observerOptions = {
threshold: 0.1,

View File

@@ -9,7 +9,7 @@
<div class="row justify-content-center text-center">
<div class="col-lg-8">
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
Полный спектр услуг
Полный спектр услуг
</span>
<h1 class="display-4 fw-bold mb-4">
Наши <span class="text-gradient">IT-услуги</span>
@@ -51,7 +51,28 @@
<div class="col-lg-4 col-md-6 service-item" data-category="{{ service.category.name|lower }}">
<div class="card-modern h-100">
<div class="position-relative overflow-hidden" style="height: 200px;">
{% if service.image %}
{% if service.video %}
<!-- Video Content -->
<video class="w-100 h-100 service-video"
style="object-fit: cover;"
muted
loop
{% if service.video_poster %}poster="{{ service.video_poster.url }}"{% endif %}
onmouseover="this.play()"
onmouseout="this.pause()">
<source src="{{ service.video.url }}" type="video/mp4">
{% if service.image %}
<!-- Fallback image if video not supported -->
<img src="{{ service.image.url }}" class="w-100 h-100" style="object-fit: cover;" alt="{{ service.name }}">
{% endif %}
Ваш браузер не поддерживает видео.
</video>
<div class="position-absolute top-0 end-0 p-2">
<span class="badge bg-success">
<i class="fas fa-play"></i> Видео
</span>
</div>
{% elif service.image %}
<img src="{{ service.image.url }}" class="w-100 h-100" style="object-fit: cover;" alt="{{ service.name }}">
{% else %}
<div class="w-100 h-100 bg-gradient d-flex align-items-center justify-content-center">

View File

@@ -11,6 +11,10 @@ urlpatterns = [
path('client/<int:pk>/', views.client_detail, name='client_detail'),
path('blog/<int:pk>/', views.blog_post_detail, name='blog_post_detail'),
path('services/', views.services_view, name='services'),
path('portfolio/', views.portfolio_view, name='portfolio'),
path('blog/', views.blog_view, name='blog'),
path('news/', views.news_view, name='news'),
path('career/', views.career_view, name='career'),
# path('create_order/<int:pk>/', views.create_order, name='create_order'),
path('about/', views.about_view, name="about"),
path('service/generate_qr_code/<int:service_id>/', views.generate_qr_code, name='generate_qr_code'),

View File

@@ -1,5 +1,5 @@
from django.shortcuts import render, get_object_or_404, redirect
from .models import Service, Project, Client, BlogPost, Review, Order, ServiceRequest
from .models import Service, Project, Client, BlogPost, Review, Order, ServiceRequest, HeroBanner
from django.db.models import Avg
from comunication.models import TelegramSettings
import qrcode
@@ -34,7 +34,20 @@ except Exception as e:
def home(request):
services = Service.objects.all()[:6] # Показываем только первые 6 услуг на главной
return render(request, 'web/home_modern.html', {'services': services})
hero_banners = HeroBanner.objects.filter(is_active=True).order_by('order', '-created_at')[:3] # Получаем активные баннеры
# Добавляем данные для полной главной страницы
latest_projects = Project.objects.all()[:3] # Последние проекты для портфолио
latest_blog_posts = BlogPost.objects.all()[:2] # Последние статьи блога
reviews = Review.objects.all()[:3] # Отзывы клиентов
return render(request, 'web/home_modern.html', {
'services': services,
'hero_banners': hero_banners,
'latest_projects': latest_projects,
'latest_blog_posts': latest_blog_posts,
'reviews': reviews,
})
def service_detail(request, pk):
service = get_object_or_404(Service, pk=pk)
@@ -69,6 +82,21 @@ def services_view(request):
def about_view(request):
return render(request, 'web/about_modern.html')
def portfolio_view(request):
projects = Project.objects.all()
return render(request, 'web/portfolio.html', {'projects': projects})
def blog_view(request):
blog_posts = BlogPost.objects.all().order_by('-created_at')
return render(request, 'web/blog.html', {'blog_posts': blog_posts})
def news_view(request):
# Можно создать модель News или использовать BlogPost с категорией
return render(request, 'web/news.html')
def career_view(request):
return render(request, 'web/career.html')
def create_service_request(request, service_id):
if request.method == 'POST':
try: