diff --git a/assets/css/custom.css b/assets/css/custom.css index eeac63a..55de913 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,12 +1,12 @@ :root { color-scheme: light; - --bg: #f8fafc; - --surface: #ffffff; - --border: #e2e8f0; - --text: #0f172a; - --muted: #64748b; - --accent: #1f2937; - --accent-soft: #e5e7eb; + --bg: #fff8f2; + --surface: #fffdf9; + --border: #eadfce; + --text: #2e2118; + --muted: #7a6151; + --accent: #a54f2a; + --accent-soft: #f6e7d8; } * { @@ -15,7 +15,7 @@ body { font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif; - background: var(--bg); + background: radial-gradient(circle at top right, #ffe8d3 0, var(--bg) 45%); color: var(--text); letter-spacing: -0.01em; } @@ -31,17 +31,17 @@ a { border: 1px solid var(--border); border-radius: 10px; padding: 2rem; - box-shadow: 0 12px 30px rgba(15, 23, 42, 0.06); + box-shadow: 0 12px 30px rgba(102, 58, 28, 0.08); } .stat-stack { border: 1px solid var(--border); border-radius: 10px; - background: #f9fafb; + background: #fff4e8; } .score-badge { - background: #f9fafb; + background: #fff4e8; border: 1px solid var(--border); border-radius: 10px; padding: 0.75rem 1rem; @@ -53,7 +53,7 @@ a { border: 1px solid var(--border); border-radius: 12px; padding: 1.5rem; - background: #f8fafc; + background: #fff8f0; } .option-list { @@ -63,27 +63,35 @@ a { gap: 0.75rem; } +#quiz #questionText { + font-size: clamp(1.5rem, 2.3vw, 2.25rem); + line-height: 1.25; + font-weight: 700; +} + .option-item { border: 1px solid var(--border); - background: #ffffff; + background: #fffdfa; border-radius: 10px; - padding: 0.85rem 1rem; + padding: 1rem 1.15rem; display: flex; align-items: center; gap: 0.75rem; font-weight: 600; + font-size: 1.12rem; + min-height: 74px; cursor: pointer; transition: 0.2s ease; } .option-item:hover { - border-color: #94a3b8; + border-color: #d39a72; transform: translateY(-1px); } .option-item-selected { - border-color: #2563eb; - background: #eff6ff; + border-color: #c06a3a; + background: #fff1e7; } .option-item-correct { @@ -97,18 +105,19 @@ a { } .option-index { - width: 36px; - height: 36px; - border-radius: 8px; + width: 42px; + height: 42px; + border-radius: 10px; background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; font-weight: 700; + flex: 0 0 42px; } .answer-pill { - background: #111827; + background: #7a3f1f; color: #fff; border-radius: 999px; padding: 0.25rem 0.75rem; @@ -122,6 +131,15 @@ a { max-width: 360px; } +.answer-image-trigger { + border: none; + background: transparent; + padding: 0; + width: 100%; + text-align: left; + cursor: zoom-in; +} + .answer-image, .summary-image { width: 100%; @@ -131,6 +149,23 @@ a { object-fit: cover; } +.zoom-hint { + display: inline-block; + margin-top: 0.5rem; + font-size: 0.85rem; + color: var(--muted); +} + +.fact-list { + margin: 0; + padding-left: 1.1rem; + color: var(--muted); +} + +.fact-list li + li { + margin-top: 0.3rem; +} + .summary-image { margin-bottom: 0.75rem; aspect-ratio: 16 / 9; @@ -145,7 +180,7 @@ a { border: 1px solid var(--border); border-radius: 10px; padding: 1rem; - background: #ffffff; + background: #fffdfa; } .summary-item p { @@ -153,29 +188,29 @@ a { } .btn-primary { - background: #111827; - border-color: #111827; + background: #a54f2a; + border-color: #a54f2a; } .btn-primary:hover, .btn-primary:focus { - background: #0f172a; - border-color: #0f172a; + background: #8f4321; + border-color: #8f4321; } .btn-dark { - background: #1f2937; - border-color: #1f2937; + background: #7a3f1f; + border-color: #7a3f1f; } .btn-dark:hover, .btn-dark:focus { - background: #111827; - border-color: #111827; + background: #663419; + border-color: #663419; } code { - background: #f1f5f9; + background: #fbe9da; padding: 0.1rem 0.35rem; border-radius: 6px; } @@ -187,3 +222,106 @@ code { padding: 1.5rem; } } + +body.quiz-live .tv-extra { + display: none !important; +} + +body.quiz-live main.container { + max-width: 100%; + margin-top: 0 !important; + margin-bottom: 0 !important; + padding-top: 1rem; + padding-bottom: 1rem; +} + +body.quiz-live #quiz { + border: none; + box-shadow: none; + background: transparent; + padding: 0; +} + +body.quiz-live #quiz .quiz-meta, +body.quiz-live #quiz #revealBtn { + display: none !important; +} + +body.quiz-live #quiz .quiz-actions { + display: flex; + justify-content: center; +} + +body.quiz-live #quiz .question-area { + min-height: 52vh; + padding: 2rem; + display: flex; + flex-direction: column; + justify-content: center; +} + +body.quiz-live #quiz #questionText { + font-size: clamp(2rem, 3.8vw, 3.1rem); + margin-bottom: 1.25rem !important; +} + +body.quiz-live #quiz .option-list { + gap: 1rem; +} + +body.quiz-live #quiz .option-item { + font-size: clamp(1.3rem, 2.2vw, 1.9rem); + padding: 1.2rem 1.4rem; + min-height: 92px; + border-radius: 14px; +} + +body.quiz-live #quiz .option-index { + width: 56px; + height: 56px; + flex-basis: 56px; + border-radius: 12px; + font-size: 1.25rem; +} + +body.quiz-live #quiz #answerArea { + margin-top: 1rem !important; +} + +body.lightbox-open { + overflow: hidden; +} + +.image-lightbox { + position: fixed; + inset: 0; + background: rgba(41, 22, 11, 0.92); + z-index: 1060; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; +} + +.image-lightbox-img { + max-width: min(96vw, 1700px); + max-height: 90vh; + border-radius: 12px; + border: 1px solid rgba(255, 255, 255, 0.18); + box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5); + object-fit: contain; +} + +.image-lightbox-close { + position: absolute; + top: 0.8rem; + right: 1rem; + border: none; + background: rgba(255, 255, 255, 0.14); + color: #fff; + font-size: 2rem; + line-height: 1; + width: 2.4rem; + height: 2.4rem; + border-radius: 999px; +} diff --git a/assets/js/main.js b/assets/js/main.js index 3abb3db..e3a2658 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -4,6 +4,11 @@ const quizData = [ options: ["Гродно", "Минск", "Витебск", "Гомель"], answer: 1, fact: "Минск — самый большой город страны и её главный культурный центр.", + facts: [ + "Минск впервые упоминается в летописях в 1067 году.", + "В городе находится Национальная библиотека с необычной формой ромбокубооктаэдра.", + "В Минске более 2 миллионов жителей — это крупнейший город Беларуси." + ], imagePath: "assets/pasted-20260305-185724-631e7f99.webp", imageAlt: "Панорама Минска" }, @@ -12,6 +17,11 @@ const quizData = [ options: ["Синий и жёлтый", "Белый и красный", "Красный и зелёный", "Белый и зелёный"], answer: 2, fact: "Красный и зелёный — основные цвета флага, а сбоку есть орнамент.", + facts: [ + "Красный цвет на флаге символизирует мужество и историческую память.", + "Зелёный цвет связан с природой, лесами и полями страны.", + "Белорусский орнамент на флаге основан на традиционном народном узоре." + ], imagePath: "assets/images/quiz/q02-flag.jpg", imageAlt: "Флаг Беларуси" }, @@ -20,6 +30,11 @@ const quizData = [ options: ["Нарочь", "Свитязь", "Дривяты", "Кромань"], answer: 0, fact: "Озеро Нарочь — любимое место отдыха и часть Нарачанского парка.", + facts: [ + "Площадь озера Нарочь — около 80 км², это крупнейшее озеро Беларуси.", + "Озеро входит в территорию Национального парка «Нарочанский».", + "Нарочь известна чистой водой и популярна для летнего отдыха." + ], imagePath: "assets/pasted-20260305-185926-dd9a5c42.webp", imageAlt: "Озеро в Беларуси" }, @@ -28,7 +43,12 @@ const quizData = [ options: ["Зубр", "Лось", "Медведь", "Лиса"], answer: 0, fact: "Зубр — редкое и сильное животное, живёт в Беловежской пуще.", - imagePath: "assets/images/quiz/q04-bison.jpg", + facts: [ + "Зубр — самое тяжёлое наземное животное Европы.", + "После почти полного исчезновения популяцию зубров удалось восстановить.", + "В Беловежской пуще находится одна из самых известных популяций зубра." + ], + imagePath: "assets/pasted-20260305-193021-7ef32b53.jpg", imageAlt: "Зубр" }, { @@ -36,6 +56,11 @@ const quizData = [ options: ["Беловежская пуща", "Березинский парк", "Браславские озёра", "Припятский парк"], answer: 0, fact: "Беловежская пуща — старинный лес, который охраняется ЮНЕСКО.", + facts: [ + "Беловежская пуща — один из самых древних лесов Европы.", + "Часть территории заповедника внесена в список Всемирного наследия ЮНЕСКО.", + "В пуще можно увидеть зубров, оленей и редкие виды птиц." + ], imagePath: "assets/pasted-20260305-190111-63cd8baa.jpg", imageAlt: "Лес Беловежской пущи" }, @@ -44,6 +69,11 @@ const quizData = [ options: ["Витебск", "Гомель", "Брест", "Полоцк"], answer: 0, fact: "Витебск — родина художника Марка Шагала.", + facts: [ + "В Витебске ежегодно проходит международный фестиваль «Славянский базар».", + "Город связан с именем художника Марка Шагала.", + "Витебск стоит на реке Западная Двина и имеет богатую историю." + ], imagePath: "assets/images/quiz/q06-vitebsk.jpg", imageAlt: "Город Витебск" }, @@ -52,6 +82,11 @@ const quizData = [ options: ["Цимбалы", "Скрипка", "Дудка", "Сопилка"], answer: 0, fact: "Цимбалы — струнный инструмент, по ним ударяют молоточками.", + facts: [ + "Цимбалы относятся к струнным ударным инструментам.", + "Музыкант играет на цимбалах двумя маленькими молоточками.", + "Звук цимбал часто можно услышать в белорусской народной музыке." + ], imagePath: "assets/pasted-20260305-190344-ec46e879.jpg", imageAlt: "Традиционный музыкальный инструмент" }, @@ -60,6 +95,11 @@ const quizData = [ options: ["Мирский замок", "Несвижский замок", "Лидский замок", "Гродненский замок"], answer: 0, fact: "Мирский замок — объект Всемирного наследия ЮНЕСКО.", + facts: [ + "Мирский замок начали строить в начале XVI века.", + "Замок сочетает элементы готики, ренессанса и барокко.", + "Комплекс Мирского замка входит в список Всемирного наследия ЮНЕСКО." + ], imagePath: "assets/images/quiz/q08-castle.jpg", imageAlt: "Мирский замок" }, @@ -68,6 +108,11 @@ const quizData = [ options: ["Западная Двина", "Днепр", "Нёман", "Припять"], answer: 1, fact: "Днепр проходит через южные регионы страны и впадает в Чёрное море.", + facts: [ + "Днепр — одна из крупнейших рек Европы.", + "Река протекает через Беларусь, Россию и Украину.", + "В Беларуси Днепр важен для судоходства и водоснабжения." + ], imagePath: "assets/pasted-20260305-190627-76b2a1c1.jpg", imageAlt: "Река Днепр" }, @@ -76,6 +121,11 @@ const quizData = [ options: ["Орнамент", "Гжель", "Петриковская роспись", "Хохлома"], answer: 0, fact: "Белорусский орнамент часто украшает флаг и народные костюмы.", + facts: [ + "Орнамент передавался из поколения в поколение в народной вышивке.", + "В узорах часто встречаются ромбы, кресты и растительные элементы.", + "Белорусский орнамент используется в национальной символике и сувенирах." + ], imagePath: "assets/pasted-20260305-190855-a269e4b8.png", imageAlt: "Белорусский орнамент" }, @@ -84,6 +134,11 @@ const quizData = [ options: ["Полоцк", "Минск", "Брест", "Могилёв"], answer: 0, fact: "Полоцк впервые упоминается в летописях в 862 году.", + facts: [ + "Полоцк — один из старейших городов восточных славян, известен с 862 года.", + "В городе находится Софийский собор — важный исторический памятник.", + "Полоцк был крупным культурным и торговым центром в Средние века." + ], imagePath: "assets/images/quiz/q11-polotsk.jpg", imageAlt: "Город Полоцк" }, @@ -92,6 +147,11 @@ const quizData = [ options: ["Пастила", "Печенье", "Козинаки", "Зефир"], answer: 2, fact: "Козинаки часто готовят из мёда и орехов.", + facts: [ + "Козинаки делают из орехов или семечек, скреплённых мёдом или сиропом.", + "Эта сладость получается хрустящей и очень питательной.", + "Козинаки часто подают к чаю как традиционное лакомство." + ], imagePath: "assets/pasted-20260305-191522-fbd0d85f.jpg", imageAlt: "Козинаки" } @@ -108,19 +168,24 @@ const classScore = document.getElementById("classScore"); const revealBtn = document.getElementById("revealBtn"); const nextBtn = document.getElementById("nextBtn"); const answerArea = document.getElementById("answerArea"); +const answerImageTrigger = document.getElementById("answerImageTrigger"); const answerImage = document.getElementById("answerImage"); const correctAnswer = document.getElementById("correctAnswer"); -const factText = document.getElementById("factText"); +const factList = document.getElementById("factList"); const answerResult = document.getElementById("answerResult"); const finalScore = document.getElementById("finalScore"); const summaryList = document.getElementById("summaryList"); const restartBtn = document.getElementById("restartBtn"); +const imageLightbox = document.getElementById("imageLightbox"); +const lightboxImage = document.getElementById("lightboxImage"); +const closeImageLightbox = document.getElementById("closeImageLightbox"); const state = { index: 0, score: 0, revealed: false, - selectedOption: null + selectedOption: null, + locked: false }; totalQuestions.textContent = quizData.length.toString(); @@ -155,21 +220,30 @@ function renderQuestion() { }); classScore.textContent = state.score.toString(); - answerArea.classList.toggle("d-none", !state.revealed); - revealBtn.classList.toggle("d-none", state.revealed); - nextBtn.classList.toggle("d-none", !state.revealed); - revealBtn.disabled = state.selectedOption === null; + answerArea.classList.add("d-none"); + answerResult.classList.remove("text-success", "text-danger"); + nextBtn.classList.add("d-none"); +} - if (state.revealed) { - answerImage.src = current.imagePath; - answerImage.alt = current.imageAlt; - correctAnswer.textContent = current.options[current.answer]; - factText.textContent = current.fact; - answerResult.textContent = state.selectedOption === current.answer - ? "Верно! +1 балл." - : "Немного не так. В следующий раз получится!"; - answerResult.className = `mt-3 mb-0 fw-semibold ${state.selectedOption === current.answer ? "text-success" : "text-danger"}`; - } +function renderAnswer() { + const current = quizData[state.index]; + answerImage.src = current.imagePath; + answerImage.alt = current.imageAlt; + correctAnswer.textContent = current.options[current.answer]; + factList.innerHTML = ""; + const facts = Array.isArray(current.facts) && current.facts.length ? current.facts.slice(0, 4) : [current.fact]; + facts.forEach((fact) => { + const li = document.createElement("li"); + li.textContent = fact; + factList.appendChild(li); + }); + + const isCorrect = state.selectedOption === current.answer; + answerResult.textContent = isCorrect ? "Верно!" : "Неверно. Правильный ответ показан выше."; + answerResult.classList.toggle("text-success", isCorrect); + answerResult.classList.toggle("text-danger", !isCorrect); + + answerArea.classList.remove("d-none"); } function showSummary() { @@ -192,63 +266,99 @@ function showSummary() { } startBtn.addEventListener("click", () => { + document.body.classList.add("quiz-live"); quizSection.classList.remove("d-none"); summarySection.classList.add("d-none"); state.index = 0; state.score = 0; state.revealed = false; state.selectedOption = null; + state.locked = false; renderQuestion(); quizSection.scrollIntoView({ behavior: "smooth" }); }); -revealBtn.addEventListener("click", () => { - if (state.selectedOption === null) return; - const current = quizData[state.index]; - if (state.selectedOption === current.answer) { - state.score += 1; - } - state.revealed = true; - renderQuestion(); -}); - -nextBtn.addEventListener("click", () => { +function goToNextQuestion() { if (state.index < quizData.length - 1) { state.index += 1; state.revealed = false; state.selectedOption = null; + state.locked = false; renderQuestion(); } else { showSummary(); summarySection.scrollIntoView({ behavior: "smooth" }); } -}); +} restartBtn.addEventListener("click", () => { state.index = 0; state.score = 0; state.revealed = false; state.selectedOption = null; + state.locked = false; summarySection.classList.add("d-none"); quizSection.classList.remove("d-none"); renderQuestion(); quizSection.scrollIntoView({ behavior: "smooth" }); }); +function closeLightbox() { + imageLightbox.classList.add("d-none"); + document.body.classList.remove("lightbox-open"); +} + +answerImageTrigger.addEventListener("click", () => { + if (!answerImage.src) return; + lightboxImage.src = answerImage.src; + lightboxImage.alt = answerImage.alt; + imageLightbox.classList.remove("d-none"); + document.body.classList.add("lightbox-open"); +}); + +closeImageLightbox.addEventListener("click", closeLightbox); + +imageLightbox.addEventListener("click", (event) => { + if (event.target === imageLightbox) { + closeLightbox(); + } +}); + +document.addEventListener("keydown", (event) => { + if (event.key === "Escape" && !imageLightbox.classList.contains("d-none")) { + closeLightbox(); + } +}); + +function selectOption(index) { + if (state.revealed || state.locked) return; + const current = quizData[state.index]; + state.selectedOption = index; + if (state.selectedOption === current.answer) { + state.score += 1; + } + state.revealed = true; + state.locked = true; + renderQuestion(); + renderAnswer(); + nextBtn.classList.remove("d-none"); +} + optionList.addEventListener("click", (event) => { - if (state.revealed) return; const option = event.target.closest(".option-item"); if (!option) return; - state.selectedOption = Number(option.dataset.index); - renderQuestion(); + selectOption(Number(option.dataset.index)); }); optionList.addEventListener("keydown", (event) => { - if (state.revealed) return; if (event.key !== "Enter" && event.key !== " ") return; const option = event.target.closest(".option-item"); if (!option) return; event.preventDefault(); - state.selectedOption = Number(option.dataset.index); - renderQuestion(); + selectOption(Number(option.dataset.index)); +}); + +nextBtn.addEventListener("click", () => { + if (!state.revealed) return; + goToNextQuestion(); }); diff --git a/assets/pasted-20260305-193021-7ef32b53.jpg b/assets/pasted-20260305-193021-7ef32b53.jpg new file mode 100644 index 0000000..932452f Binary files /dev/null and b/assets/pasted-20260305-193021-7ef32b53.jpg differ diff --git a/index.php b/index.php index 9ab78f2..ef42acf 100644 --- a/index.php +++ b/index.php @@ -30,7 +30,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; -
+
-
+

Интерактив для 5‑го класса

@@ -75,7 +75,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
-
+

Прогресс

Вопрос 1 из 12

@@ -96,19 +96,23 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
- +
Правильный ответ

-

+

Интересные факты:

+

    -
    +
    @@ -128,7 +132,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
    -
    +
    @@ -155,13 +159,18 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
    -