This repository has been archived on 2026-11-14. You can view files and clone it, but cannot push or open issues or pull requests.
sokol-camp/index.html

709 lines
28 KiB
HTML
Raw Permalink 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.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Детский лагерь «Сокол» — лето 2025</title>
<meta name="description" content="Детский лагерь «Сокол»: смены, цены, расписание, запись онлайн." />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&display=swap" rel="stylesheet" />
<style>
/* ========== RESET / BASE ========== */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: 'Nunito', -apple-system, BlinkMacSystemFont, sans-serif;
font-weight: 400;
color: #1f2937;
background: #fff;
line-height: 1.6;
}
h1, h2, h3 { margin: 0 0 12px; font-weight: 800; color: #0f172a; line-height: 1.2; }
h2 { font-size: 2rem; }
p { margin: 0 0 12px; }
a { color: #FF6B35; text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; display: block; }
.container { width: 100%; max-width: 1140px; margin: 0 auto; padding: 0 20px; }
:root {
--orange: #FF6B35;
--orange-dark: #e55522;
--blue: #00AAFF;
--gray-bg: #f8fafc;
--border: #e5e7eb;
--shadow: 0 4px 12px rgba(0,0,0,0.08);
--shadow-hover: 0 8px 24px rgba(0,0,0,0.12);
}
/* ========== BUTTONS ========== */
.btn {
display: inline-block;
padding: 14px 28px;
border-radius: 999px;
font-weight: 700;
font-size: 1rem;
cursor: pointer;
border: none;
transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
text-align: center;
}
.btn:hover { transform: translateY(-2px); text-decoration: none; box-shadow: var(--shadow-hover); }
.btn--primary { background: var(--orange); color: #fff; }
.btn--primary:hover { background: var(--orange-dark); color: #fff; }
.btn--secondary { background: #fff; color: var(--orange); border: 2px solid var(--orange); }
.btn--secondary:hover { background: var(--orange); color: #fff; }
.btn--small { padding: 10px 20px; font-size: 0.95rem; }
.btn--ghost { background: transparent; color: var(--blue); border: 2px solid var(--blue); }
.btn--ghost:hover { background: var(--blue); color: #fff; }
/* ========== HEADER ========== */
.header {
position: sticky; top: 0; z-index: 50;
background: #fff;
border-bottom: 1px solid var(--border);
}
.header__inner {
display: flex; align-items: center; justify-content: space-between;
height: 70px;
}
.logo { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 1.3rem; color: #0f172a; }
.logo:hover { text-decoration: none; }
.logo__mark { font-size: 1.6rem; }
.nav { display: flex; gap: 24px; }
.nav a { color: #334155; font-weight: 600; }
.nav a:hover { color: var(--orange); text-decoration: none; }
.nav__cta { margin-left: 16px; }
.burger { display: none; background: none; border: none; cursor: pointer; padding: 8px; }
.burger span { display: block; width: 26px; height: 3px; background: #0f172a; margin: 5px 0; border-radius: 2px; transition: 0.3s; }
/* ========== HERO ========== */
.hero { position: relative; min-height: 80vh; display: flex; align-items: center; color: #fff; overflow: hidden; }
.hero__bg {
position: absolute; inset: 0;
background:
linear-gradient(135deg, rgba(255,107,53,0.65) 0%, rgba(0,170,255,0.55) 100%),
url('images/photo_08.jpg') center / cover no-repeat,
linear-gradient(180deg, #4a90e2 0%, #2c5282 100%);
z-index: -1;
}
.hero__bg::after {
content: ''; position: absolute; inset: 0;
background-image:
radial-gradient(circle at 20% 80%, rgba(255,255,255,0.1) 0%, transparent 30%),
radial-gradient(circle at 80% 20%, rgba(255,255,255,0.15) 0%, transparent 40%);
}
.hero__content { position: relative; padding: 80px 20px; }
.hero__title { font-size: 3rem; color: #fff; max-width: 700px; text-shadow: 0 2px 12px rgba(0,0,0,0.3); }
.hero__subtitle { font-size: 1.25rem; max-width: 600px; text-shadow: 0 1px 6px rgba(0,0,0,0.3); }
.hero__buttons { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 24px; }
/* ========== SECTION ========== */
.section { padding: 80px 0; }
.section--gray { background: var(--gray-bg); }
.section__title { text-align: center; }
.section__lead { text-align: center; color: #64748b; margin-bottom: 40px; font-size: 1.1rem; }
/* ========== ABOUT ========== */
.about { display: grid; grid-template-columns: 1.2fr 1fr; gap: 48px; align-items: center; }
.about__points { list-style: none; padding: 0; margin: 20px 0 0; }
.about__points li { padding: 8px 0; font-size: 1.05rem; }
.about__photo {
height: 360px; border-radius: 20px;
background: url('images/photo_05.jpg') center / cover no-repeat;
box-shadow: var(--shadow);
}
/* ========== SHIFTS ========== */
.shifts {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
.shift {
background: #fff;
border-radius: 16px;
padding: 28px;
box-shadow: var(--shadow);
display: flex; flex-direction: column;
transition: transform 0.2s ease, box-shadow 0.2s ease;
border-top: 4px solid var(--orange);
}
.shift:nth-child(even) { border-top-color: var(--blue); }
.shift:hover { transform: translateY(-4px); box-shadow: var(--shadow-hover); }
.shift__name { font-size: 1.25rem; }
.shift__dates { color: #64748b; font-weight: 600; margin-bottom: 12px; }
.shift__desc { flex-grow: 0; color: #334155; }
.shift__includes { list-style: none; padding: 0; margin: 12px 0; font-size: 0.95rem; color: #475569; }
.shift__includes li { padding: 3px 0; }
.shift__includes li::before { content: '✓ '; color: var(--orange); font-weight: 700; }
.shift__price-row {
display: flex; align-items: baseline; justify-content: space-between;
margin: 16px 0 12px; padding-top: 16px; border-top: 1px solid var(--border);
}
.shift__price { font-size: 1.6rem; font-weight: 800; color: #0f172a; }
.shift__price small { font-size: 0.9rem; color: #64748b; font-weight: 600; }
.shift__spots { font-size: 0.9rem; color: #16a34a; font-weight: 700; }
.shift__spots--low { color: #dc2626; }
.shift__buttons { display: flex; gap: 8px; margin-top: auto; }
.shift__buttons .btn { flex: 1; padding: 12px 16px; font-size: 0.95rem; }
/* ========== SCHEDULE ========== */
.schedule {
width: 100%; max-width: 700px; margin: 0 auto;
border-collapse: collapse;
background: #fff; border-radius: 16px; overflow: hidden;
box-shadow: var(--shadow);
}
.schedule th, .schedule td { padding: 14px 20px; text-align: left; border-bottom: 1px solid var(--border); }
.schedule th { background: var(--orange); color: #fff; font-weight: 700; }
.schedule tbody tr:last-child td { border-bottom: none; }
.schedule tbody tr:hover { background: #fff7ed; }
.schedule td:first-child { font-weight: 700; color: var(--orange); width: 100px; }
/* ========== GALLERY ========== */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 12px;
}
.gallery__item {
aspect-ratio: 1 / 1;
border-radius: 12px;
cursor: pointer;
overflow: hidden;
position: relative;
transition: transform 0.2s ease, box-shadow 0.2s ease;
padding: 0;
border: none;
background: #e5e7eb;
}
.gallery__item img {
width: 100%; height: 100%; object-fit: cover; display: block;
transition: transform 0.3s ease;
}
.gallery__item:hover { transform: scale(1.03); box-shadow: var(--shadow-hover); }
.gallery__item:hover img { transform: scale(1.06); }
/* ========== SIGNUP / FORM ========== */
.signup { display: grid; grid-template-columns: 1fr 1.3fr; gap: 48px; align-items: start; }
.signup__info h2 { text-align: left; }
.signup__note { color: #64748b; font-size: 0.95rem; font-style: italic; }
.form {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
background: #fff;
padding: 32px;
border-radius: 16px;
box-shadow: var(--shadow);
}
.form__field { display: flex; flex-direction: column; gap: 6px; font-weight: 600; font-size: 0.95rem; color: #334155; }
.form__field--wide { grid-column: 1 / -1; }
.form__field input, .form__field select, .form__field textarea {
padding: 12px 14px;
border: 2px solid var(--border);
border-radius: 10px;
font-family: inherit;
font-size: 1rem;
font-weight: 400;
transition: border-color 0.15s ease;
background: #fff;
}
.form__field input:focus, .form__field select:focus, .form__field textarea:focus {
outline: none; border-color: var(--orange);
}
.form__field input:invalid:not(:placeholder-shown) { border-color: #dc2626; }
.form__submit { grid-column: 1 / -1; }
.form__success {
grid-column: 1 / -1;
background: #dcfce7;
color: #166534;
padding: 14px 18px;
border-radius: 10px;
font-weight: 700;
text-align: center;
margin: 0;
}
/* ========== PAYMENT ========== */
.payment-simple {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 20px;
}
.pay-card {
background: #fff;
padding: 28px 24px;
border-radius: 14px;
text-align: center;
box-shadow: var(--shadow);
}
.pay-card__icon { font-size: 2.5rem; margin-bottom: 8px; }
.pay-card h3 { font-size: 1.15rem; }
.pay-card p { margin: 6px 0; color: #334155; }
.pay-card__big { font-size: 1.25rem; font-weight: 700; color: #0f172a; }
.pay-card__hint { font-size: 0.9rem; color: #64748b; font-style: italic; }
.pay-card a { font-weight: 700; }
/* ========== CONTACTS ========== */
.contacts__grid {
display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px;
margin-top: 32px;
}
.contact-card {
background: #fff;
padding: 24px;
border-radius: 14px;
text-align: center;
box-shadow: var(--shadow);
}
.contact-card__icon { font-size: 2.5rem; margin-bottom: 8px; }
.contact-card h3 { font-size: 1.1rem; }
.contact-card a { display: block; font-weight: 700; padding: 4px 0; font-size: 1.05rem; }
.contact-card__sub { font-size: 0.9rem; color: #64748b; margin-top: 6px; }
/* ========== FOOTER ========== */
.footer { background: #0f172a; color: #cbd5e1; padding: 32px 0; }
.footer__inner { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px; }
.footer strong { color: #fff; font-size: 1.1rem; }
.footer p { margin: 4px 0 0; font-size: 0.9rem; }
.footer__nav { display: flex; gap: 20px; flex-wrap: wrap; }
.footer__nav a { color: #cbd5e1; font-weight: 600; }
.footer__nav a:hover { color: var(--orange); }
/* ========== LIGHTBOX ========== */
.lightbox {
display: none;
position: fixed; inset: 0; z-index: 100;
background: rgba(0,0,0,0.92);
align-items: center; justify-content: center;
padding: 20px;
}
.lightbox.is-open { display: flex; }
.lightbox__img {
width: min(90vw, 900px); max-height: 85vh;
display: flex; align-items: center; justify-content: center;
}
.lightbox__img img {
max-width: 100%; max-height: 85vh;
border-radius: 12px; object-fit: contain;
box-shadow: 0 10px 40px rgba(0,0,0,0.5);
}
.lightbox__close {
position: absolute; top: 16px; right: 24px;
background: none; border: none; color: #fff; font-size: 3rem; cursor: pointer; line-height: 1;
}
/* ========== MOBILE ========== */
@media (max-width: 860px) {
.nav, .nav__cta { display: none; }
.nav.is-open {
display: flex; flex-direction: column;
position: absolute; top: 70px; left: 0; right: 0;
background: #fff; padding: 20px; gap: 16px;
box-shadow: var(--shadow);
border-top: 1px solid var(--border);
}
.burger { display: block; }
.hero__title { font-size: 2.2rem; }
.hero__subtitle { font-size: 1.1rem; }
.about, .signup { grid-template-columns: 1fr; }
.form { grid-template-columns: 1fr; padding: 24px; }
.section { padding: 56px 0; }
h2 { font-size: 1.6rem; }
}
</style>
</head>
<body>
<!-- [1] HEADER -->
<header class="header" id="top">
<div class="container header__inner">
<a href="#top" class="logo">
<span class="logo__mark">🦅</span>
<span class="logo__text">Сокол</span>
</a>
<nav class="nav" id="nav">
<a href="#about">О лагере</a>
<a href="#shifts">Смены</a>
<a href="#schedule">Расписание</a>
<a href="#gallery">Галерея</a>
<a href="#contacts">Контакты</a>
</nav>
<a href="#signup" class="btn btn--primary btn--small nav__cta">Записаться</a>
<button class="burger" id="burger" aria-label="Меню">
<span></span><span></span><span></span>
</button>
</div>
</header>
<!-- [2] HERO -->
<section class="hero">
<div class="hero__bg"></div>
<div class="container hero__content">
<h1 class="hero__title">Лето, которое запомнится навсегда</h1>
<p class="hero__subtitle">Детский лагерь «Сокол» — спорт, друзья, приключения и творчество для детей 7–15 лет.</p>
<div class="hero__buttons">
<a href="#signup" class="btn btn--primary">Записаться</a>
<a href="#shifts" class="btn btn--secondary">Узнать цены</a>
</div>
</div>
</section>
<!-- [3] ABOUT -->
<section class="section" id="about">
<div class="container about">
<div class="about__text">
<h2>О лагере</h2>
<p>«Сокол» — детский лагерь с 30-летней историей. Корпуса в сосновом лесу, своё озеро, спортивные площадки и опытные вожатые.</p>
<p>Каждая смена — отдельная тема: спорт, творчество, природа. Дети возвращаются домой с новыми друзьями и яркими историями.</p>
<ul class="about__points">
<li>✅ Лицензированные педагоги и медики</li>
<li>✅ Соотношение 1 вожатый на 8 детей</li>
<li>✅ Питание 3 раза в день + полдник</li>
<li>✅ Круглосуточная охрана территории</li>
</ul>
</div>
<div class="about__photo" aria-label="Команда лагеря"></div>
</div>
</section>
<!-- [4] SHIFTS -->
<section class="section section--gray" id="shifts">
<div class="container">
<h2 class="section__title">Смены и цены</h2>
<p class="section__lead">Выбирайте удобные даты. Места ограничены.</p>
<div class="shifts" id="shifts-grid">
<!-- shift cards rendered by script -->
</div>
</div>
</section>
<!-- [5] SCHEDULE -->
<section class="section" id="schedule">
<div class="container">
<h2 class="section__title">Расписание дня</h2>
<p class="section__lead">Чем занят ребёнок с утра до вечера.</p>
<table class="schedule">
<thead>
<tr><th>Время</th><th>Активность</th></tr>
</thead>
<tbody>
<tr><td>08:00</td><td>Подъём, зарядка на свежем воздухе</td></tr>
<tr><td>09:00</td><td>Завтрак</td></tr>
<tr><td>10:00</td><td>Кружки и мастер-классы</td></tr>
<tr><td>12:30</td><td>Спорт и игры на улице</td></tr>
<tr><td>14:00</td><td>Обед</td></tr>
<tr><td>15:00</td><td>Тихий час</td></tr>
<tr><td>16:30</td><td>Полдник</td></tr>
<tr><td>17:00</td><td>Командные игры, бассейн</td></tr>
<tr><td>19:00</td><td>Ужин</td></tr>
<tr><td>20:00</td><td>Вечернее мероприятие, дискотека</td></tr>
<tr><td>22:00</td><td>Отбой</td></tr>
</tbody>
</table>
</div>
</section>
<!-- [6] GALLERY -->
<section class="section section--gray" id="gallery">
<div class="container">
<h2 class="section__title">Галерея</h2>
<p class="section__lead">Так выглядит лето в «Соколе».</p>
<div class="gallery" id="gallery-grid">
<!-- gallery items rendered by script -->
</div>
</div>
</section>
<!-- [7] SIGNUP -->
<section class="section" id="signup">
<div class="container signup">
<div class="signup__info">
<h2>Запись в лагерь</h2>
<p>Оставьте заявку — администратор перезвонит в течение часа, расскажет о свободных местах и поможет с оплатой.</p>
<p class="signup__note">Заявка ни к чему не обязывает. Оплата — только после подтверждения.</p>
</div>
<form class="form" id="signup-form" novalidate>
<label class="form__field">
<span>Имя ребёнка *</span>
<input type="text" name="child_name" required />
</label>
<label class="form__field">
<span>Возраст ребёнка *</span>
<input type="number" name="child_age" min="5" max="17" required />
</label>
<label class="form__field">
<span>Имя родителя *</span>
<input type="text" name="parent_name" required />
</label>
<label class="form__field">
<span>Телефон *</span>
<input type="tel" name="phone" placeholder="+7 ___ ___ __ __" required />
</label>
<label class="form__field">
<span>Смена *</span>
<select name="shift" id="shift-select" required>
<option value="">— выберите смену —</option>
</select>
</label>
<label class="form__field form__field--wide">
<span>Комментарий</span>
<textarea name="comment" rows="3" placeholder="Особенности, аллергии, пожелания..."></textarea>
</label>
<button type="submit" class="btn btn--primary form__submit">Отправить заявку</button>
<p class="form__success" id="form-success" hidden>
🎉 Заявка принята! Мы позвоним вам в течение часа.
</p>
</form>
</div>
</section>
<!-- [7.5] PAYMENT -->
<section class="section section--gray" id="payment">
<div class="container">
<h2 class="section__title">Оплата</h2>
<p class="section__lead">После подтверждения заявки администратором.</p>
<div class="payment-simple">
<div class="pay-card">
<div class="pay-card__icon">💳</div>
<h3>Kaspi перевод</h3>
<p class="pay-card__big">+7 700 123 45 67</p>
<p>Получатель: Сокол ИП</p>
<p class="pay-card__hint">В комментарии: имя ребёнка и номер смены</p>
</div>
<div class="pay-card">
<div class="pay-card__icon">🏦</div>
<h3>Банковский счёт</h3>
<p>АО «Народный Банк»</p>
<p>ИИК: KZ123456789012345678</p>
<p>БИН: 123456789012</p>
</div>
<div class="pay-card">
<div class="pay-card__icon">📱</div>
<h3>Подтверждение</h3>
<p>Пришлите скриншот оплаты в WhatsApp:</p>
<p class="pay-card__big">
<a href="https://wa.me/77001234567" target="_blank" rel="noopener">+7 700 123 45 67</a>
</p>
</div>
</div>
</div>
</section>
<!-- [8] CONTACTS -->
<section class="section section--gray" id="contacts">
<div class="container contacts">
<h2 class="section__title">Контакты</h2>
<div class="contacts__grid">
<div class="contact-card">
<div class="contact-card__icon">📞</div>
<h3>Телефон</h3>
<a href="tel:+77001234567">+7 700 123 45 67</a>
<p class="contact-card__sub">Ежедневно с 9:00 до 21:00</p>
</div>
<div class="contact-card">
<div class="contact-card__icon">💬</div>
<h3>Мессенджеры</h3>
<a href="https://wa.me/77001234567" target="_blank" rel="noopener">WhatsApp</a>
<a href="https://t.me/sokol_camp" target="_blank" rel="noopener">Telegram</a>
</div>
<div class="contact-card">
<div class="contact-card__icon">📍</div>
<h3>Адрес</h3>
<p>Курортная зона Шалкар-Имантау, 70 км от г. Кокшетау</p>
</div>
<div class="contact-card">
<div class="contact-card__icon">📷</div>
<h3>Инстаграм</h3>
<a href="https://www.instagram.com/doc.sokol_/" target="_blank" rel="noopener">@doc.sokol_</a>
<p class="contact-card__sub">Фото и видео со смен</p>
</div>
</div>
</div>
</section>
<!-- [9] FOOTER -->
<footer class="footer">
<div class="container footer__inner">
<div>
<strong>🦅 Лагерь «Сокол»</strong>
<p>© 2025. Все права защищены.</p>
</div>
<nav class="footer__nav">
<a href="#about">О лагере</a>
<a href="#shifts">Смены</a>
<a href="#signup">Запись</a>
<a href="#contacts">Контакты</a>
</nav>
</div>
</footer>
<!-- Lightbox -->
<div class="lightbox" id="lightbox">
<button class="lightbox__close" id="lightbox-close" aria-label="Закрыть">×</button>
<div class="lightbox__img" id="lightbox-img"></div>
</div>
<script>
// ========== DATA ==========
const MOCK_SHIFTS = [
{ id: 1, name: 'Смена 1 — «Старт лета»', dates: '1 июня — 21 июня 2025', price: 120000, currency: 'тенге', spots_left: 12,
description: 'Спорт, творчество, командные игры. Возраст: 7–12 лет.',
includes: ['3-разовое питание', 'проживание в корпусе', 'все мероприятия'] },
{ id: 2, name: 'Смена 2 — «Приключения»', dates: '25 июня — 15 июля 2025', price: 135000, currency: 'тенге', spots_left: 8,
description: 'Походы, квесты, природа. Возраст: 10–15 лет.',
includes: ['3-разовое питание', 'проживание в корпусе', 'все мероприятия', 'поход выходного дня'] },
{ id: 3, name: 'Смена 3 — «Творческая лаборатория»', dates: '19 июля — 8 августа 2025', price: 130000, currency: 'тенге', spots_left: 15,
description: 'Музыка, театр, рисование, мультипликация. Возраст: 8–14 лет.',
includes: ['3-разовое питание', 'проживание в корпусе', 'мастер-классы', 'итоговый концерт'] },
{ id: 4, name: 'Смена 4 — «Прощание с летом»', dates: '12 августа — 30 августа 2025', price: 125000, currency: 'тенге', spots_left: 20,
description: 'Спорт, дискотеки, костры, кино под открытым небом. Возраст: 9–15 лет.',
includes: ['3-разовое питание', 'проживание в корпусе', 'все мероприятия', 'выпускной'] },
];
const GALLERY_ITEMS = [
{ src: 'images/photo_01.jpg', alt: 'Арт-объект I love Sokol' },
{ src: 'images/photo_02.jpg', alt: 'Армрестлинг на стадионе' },
{ src: 'images/photo_03.jpg', alt: 'Зарядка отряда' },
{ src: 'images/photo_04.jpg', alt: 'Гигантские шахматы' },
{ src: 'images/photo_05.jpg', alt: 'Построение лагеря' },
{ src: 'images/photo_06.jpg', alt: 'Пенная вечеринка' },
{ src: 'images/photo_07.jpg', alt: 'Английская телефонная будка' },
{ src: 'images/photo_08.jpg', alt: 'Дружный круг на газоне' },
{ src: 'images/photo_09.jpg', alt: 'Ребята в форме лагеря' },
{ src: 'images/photo_10.jpg', alt: 'Пенная вечеринка на улице' },
{ src: 'images/photo_11.jpg', alt: 'Юный шахматист' },
{ src: 'images/photo_12.jpg', alt: 'Фоторамка у озера' },
{ src: 'images/photo_13.jpg', alt: 'Телефонная будка во дворе' },
];
// ========== HELPERS ==========
const $ = (sel) => document.querySelector(sel);
const fmtPrice = (n) => n.toLocaleString('ru-RU');
async function loadShifts() {
try {
const r = await fetch('data/shifts.json');
if (!r.ok) throw new Error('fetch failed');
return await r.json();
} catch (_) {
return MOCK_SHIFTS;
}
}
// ========== RENDER: SHIFTS ==========
function renderShifts(shifts) {
const grid = $('#shifts-grid');
const select = $('#shift-select');
grid.innerHTML = shifts.map((s) => {
const lowSpots = s.spots_left <= 10;
const includes = s.includes.map((i) => `<li>${i}</li>`).join('');
return `
<article class="shift" data-id="${s.id}">
<h3 class="shift__name">${s.name}</h3>
<div class="shift__dates">📅 ${s.dates}</div>
<p class="shift__desc">${s.description}</p>
<ul class="shift__includes">${includes}</ul>
<div class="shift__price-row">
<div class="shift__price">${fmtPrice(s.price)} <small>${s.currency}</small></div>
<div class="shift__spots ${lowSpots ? 'shift__spots--low' : ''}">
Мест: ${s.spots_left}
</div>
</div>
<div class="shift__buttons">
<button class="btn btn--primary" data-action="signup" data-shift="${s.id}">Выбрать смену</button>
</div>
</article>
`;
}).join('');
select.innerHTML = '<option value="">— выберите смену —</option>' +
shifts.map((s) => `<option value="${s.id}">${s.name} (${s.dates})</option>`).join('');
grid.addEventListener('click', (e) => {
const btn = e.target.closest('button[data-action]');
if (!btn) return;
const shiftId = btn.dataset.shift;
if (btn.dataset.action === 'signup') {
select.value = shiftId;
$('#signup').scrollIntoView({ behavior: 'smooth' });
setTimeout(() => $('input[name="child_name"]').focus(), 600);
}
});
}
// ========== RENDER: GALLERY ==========
function renderGallery() {
const grid = $('#gallery-grid');
grid.innerHTML = GALLERY_ITEMS.map((g, i) => `
<button class="gallery__item" data-i="${i}" aria-label="${g.alt}">
<img src="${g.src}" alt="${g.alt}" loading="lazy" />
</button>
`).join('');
grid.addEventListener('click', (e) => {
const item = e.target.closest('.gallery__item');
if (!item) return;
const g = GALLERY_ITEMS[Number(item.dataset.i)];
const lb = $('#lightbox-img');
lb.innerHTML = `<img src="${g.src}" alt="${g.alt}" />`;
$('#lightbox').classList.add('is-open');
});
}
// ========== LIGHTBOX ==========
function initLightbox() {
const lb = $('#lightbox');
const close = () => lb.classList.remove('is-open');
$('#lightbox-close').addEventListener('click', close);
lb.addEventListener('click', (e) => { if (e.target === lb) close(); });
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') close(); });
}
// ========== BURGER MENU ==========
function initBurger() {
const nav = $('#nav');
const burger = $('#burger');
burger.addEventListener('click', () => nav.classList.toggle('is-open'));
nav.addEventListener('click', (e) => {
if (e.target.tagName === 'A') nav.classList.remove('is-open');
});
}
// ========== FORM ==========
function initForm() {
const form = $('#signup-form');
const success = $('#form-success');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const data = Object.fromEntries(new FormData(form).entries());
console.log('Заявка:', data);
success.hidden = false;
form.querySelectorAll('input, select, textarea').forEach((el) => { el.value = ''; });
success.scrollIntoView({ behavior: 'smooth', block: 'center' });
setTimeout(() => { success.hidden = true; }, 8000);
});
}
// ========== INIT ==========
(async function init() {
const shifts = await loadShifts();
renderShifts(shifts);
renderGallery();
initLightbox();
initBurger();
initForm();
})();
</script>
</body>
</html>