[html]<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>Архив эпизодов | Гримуар</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #e8e2d8;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 40px 20px;
font-family: 'Times New Roman', Georgia, serif;
}
/* ГЛАВНЫЙ КОНТЕЙНЕР — скруглённый, без рамки */
.archive {
max-width: 1300px;
width: 100%;
background: #fefaf5;
border-radius: 32px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.05);
padding: 32px 30px 42px 30px;
position: relative;
}
/* ШАПКА — по центру */
.header {
text-align: center;
border-bottom: 1px solid #ece2d4;
padding-bottom: 24px;
margin-bottom: 48px;
}
.header-line {
width: 100%;
height: 1px;
background: #ece2d4;
margin: 10px auto 0 auto;
margin-bottom: 15px;
}
.header h1 {
font-size: 26px;
letter-spacing: 4px;
color: #2a2a2a;
font-weight: 400;
margin-bottom: 12px;
}
.header p {
font-size: 15px;
color: #6f6a60;
line-height: 1.5;
max-width: 700px;
margin: 0 auto;
}
/* СЕТКА КАРТОЧЕК — ЦЕНТР */
.themes-grid {
display: flex;
flex-wrap: wrap;
gap: 40px;
justify-content: center;
align-items: flex-start;
}
.theme-card {
width: 200px;
flex-shrink: 0;
text-align: center;
}
.theme-art {
width: 100%;
height: 250px;
object-fit: cover;
border-radius: 24px;
cursor: pointer;
transition: opacity 0.25s ease, transform 0.2s, box-shadow 0.2s;
display: block;
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.08);
}
.theme-art:hover {
opacity: 0.7;
transform: scale(0.98);
}
.theme-label {
margin-top: 10px;
font-size: 12px;
color: #aa9b84;
letter-spacing: 1px;
}
/* ===== МОДАЛЬНОЕ ОКНО (ПО ЦЕНТРУ) ===== */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2000;
justify-content: center;
align-items: center;
}
.modal.active {
display: flex;
}
/* фон затемнения */
.modal-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(3px);
}
/* горизонтальное окно */
.modal-container {
position: relative;
width: 600px;
max-width: 90vw;
background: #fffef8;
border-radius: 28px;
box-shadow: 0 25px 45px rgba(0, 0, 0, 0.25);
padding: 24px 26px;
border: 1px solid #eaddcd;
animation: modalFadeIn 0.2s ease;
max-height: 80vh;
display: flex;
flex-direction: column;
}
@keyframes modalFadeIn {
from {
opacity: 0;
transform: scale(0.96);
}
to {
opacity: 1;
transform: scale(1);
}
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: baseline;
border-bottom: 1px solid #f0e6da;
padding-bottom: 14px;
margin-bottom: 20px;
}
.modal-header h3 {
font-size: 22px;
font-weight: 500;
color: #3a3024;
letter-spacing: 1px;
}
.modal-close {
background: transparent !important;
border: none;
font-size: 28px;
cursor: pointer;
color: #000000;
line-height: 1;
padding: 0;
margin: 0;
width: auto;
height: auto;
box-shadow: none;
outline: none;
}
.modal-close:hover {
opacity: 1;
}
/* список эпизодов — прокрутка, если много */
.modal-episodes {
overflow-y: auto;
padding-right: 8px;
display: flex;
flex-direction: column;
gap: 20px;
max-height: 55vh;
}
.modal-episode {
border-bottom: 1px solid #f3ecdf;
padding-bottom: 14px;
}
.modal-episode:last-child {
border-bottom: none;
padding-bottom: 0;
}
.episode-title {
font-size: 17px;
font-weight: bold;
margin-bottom: 6px;
}
.episode-title a {
text-decoration: none;
color: #2c2c2c;
transition: color 0.15s;
}
.episode-title a:hover {
color: #9b6e42;
text-decoration: underline;
}
.episode-desc {
font-size: 13px;
line-height: 1.45;
color: #6b5f4f;
margin: 8px 0 6px;
}
.episode-participants {
font-size: 11px;
color: #b2a082;
font-family: monospace;
}
/* адаптив */
@media (max-width: 650px) {
.archive {
padding: 20px;
}
.modal-container {
padding: 18px;
width: 95vw;
}
.modal-header h3 {
font-size: 18px;
}
.episode-title {
font-size: 15px;
}
.episode-desc {
font-size: 12px;
}
}
</style>
</head>
<body>
<div class="archive">
<div class="header">
<div style="display: flex; justify-content: center; flex-direction: column; align-items: center; width: 100%;">
<h1>АРХИВ ЭПИЗОДОВ</h1>
<p>
Здесь будет учет эпизодов, в некоторых из которых вы сможете найти материалы теоретического и практического характера по дисциплине "Алхимия".<br>
При нажатии на арт открывается список эпизодов.
</p>
<div class="header-line"></div>
</div>
<div class="themes-grid">
<!-- АЛХИМИЯ -->
<div class="theme-card" data-theme="alchemy">
<img class="theme-art" src="https://upforme.ru/uploads/001c/82/f2/115/666826.jpg" alt="алхимия">
<div class="theme-label">Алхимия</div>
</div>
<!-- ПРОЧЕЕ -->
<div class="theme-card" data-theme="other">
<img class="theme-art" src="https://upforme.ru/uploads/001c/82/f2/115/511872.jpg" alt="прочее">
<div class="theme-label">Прочее</div>
</div>
<!-- ЛИЧНОЕ -->
<div class="theme-card" data-theme="personal">
<img class="theme-art" src="https://upforme.ru/uploads/001c/82/f2/115/975746.jpg" alt="личное">
<div class="theme-label">Личное</div>
</div>
</div>
</div>
<!-- МОДАЛЬНОЕ ОКНО -->
<div id="episodeModal" class="modal">
<div class="modal-overlay"></div>
<div class="modal-container">
<div class="modal-header">
<h3 id="modalTitle"></h3>
<button class="modal-close" id="modalCloseBtn">✕</button>
</div>
<div id="modalEpisodesList" class="modal-episodes"></div>
</div>
</div>
<script>
// ДАННЫЕ ЭПИЗОДОВ
const episodesData = {
alchemy: {
title: "Преподавание · Алхимические эпизоды",
list: [
{
name: "Similis Simili Gaudet",
url: "https://kindredspirits.ru/viewtopic.php?id=622",
desc: "Введение в алхимические этапы: nigredo, albedo, rubedo. Демонстрация на примере превращения личинки жука в имаго.",
participants: "Маттиас, Сайрен Ноктелл"
}
]
},
personal: {
title: "Отношеньки · Личные хроники",
list: [
{
name: "αὐτός katalysis",
url: "https://kindredspirits.ru/viewtopic.php?id=661",
desc: "Первая встреча после долгой разлуки",
participants: "Маттиас, Лукас Холм"
}
]
}, // ← закрыли personal и поставили запятую
other: {
title: "Прочее · Квесты",
list: [
{
name: "Carpe Demon",
url: "https://kindredspirits.ru/viewtopic.php?id=665",
desc: "Нужно забрать из Фасги древние фолианты и иные важные бумаги. Очевидно, что новости лгут. Вокруг снуют работники Инквизиции. В воздухе пахнет Скверной.",
participants: "Маттиас, Мстислав Винтерхальтер, Никодемус Берка, Лукас Холм"
},
{
name: "Do the evolution",
url: "https://kindredspirits.ru/viewtopic.php?id=673",
desc: "Маттиас приглашен инквизицией в качестве специалиста для секретного расследования. Клайд приглашен в качестве специалиста по прикрытию чужих задниц.",
participants: "Маттиас, Клайд Стил"
}
]
}
};
const modal = document.getElementById('episodeModal');
const modalTitle = document.getElementById('modalTitle');
const modalEpisodesList = document.getElementById('modalEpisodesList');
const modalCloseBtn = document.getElementById('modalCloseBtn');
let currentTheme = null;
function closeModal() {
modal.classList.remove('active');
currentTheme = null;
}
function openModal(themeKey) {
const data = episodesData[themeKey];
if (!data) return;
modalTitle.innerHTML = data.title;
modalEpisodesList.innerHTML = '';
data.list.forEach(ep => {
const episodeDiv = document.createElement('div');
episodeDiv.className = 'modal-episode';
episodeDiv.innerHTML = `
<div class="episode-title">
<a href="${ep.url}" target="_blank">${ep.name}</a>
</div>
<div class="episode-desc">${ep.desc}</div>
<div class="episode-participants">👥 ${ep.participants}</div>
`;
modalEpisodesList.appendChild(episodeDiv);
});
modal.classList.add('active');
currentTheme = themeKey;
}
// Клик по картинке
document.querySelectorAll('.theme-art').forEach(img => {
img.addEventListener('click', (e) => {
e.stopPropagation();
const card = img.closest('.theme-card');
const theme = card.getAttribute('data-theme');
// Если модалка уже открыта для этой темы — закрываем, иначе открываем
if (modal.classList.contains('active') && currentTheme === theme) {
closeModal();
} else {
openModal(theme);
}
});
});
// Закрытие по крестику
modalCloseBtn.addEventListener('click', closeModal);
// Закрытие по клику на оверлей
const modalOverlay = document.querySelector('.modal-overlay');
modalOverlay.addEventListener('click', closeModal);
// Закрытие по Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && modal.classList.contains('active')) {
closeModal();
}
});
</script>
</body>
</html>[/html]
Отредактировано Matthias Kiefer (19-04-2026 22:58:59)




















