[hideprofile][html]<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Хронология событий</title>
<style>
/* ===== СТИЛИ ИЗ ПИТОМНИКА ===== */
:root {
--text: #232d24;
--link: #39423c;
--link-hover: #aeafa8;
--link-light: #d5d4d1;
--link-light-hover: #aeafaa;
--zelen: #b8bbb9;
--scroll: #2f3229;
--respect: #edeeed;
--back: #848a87;
--noblack: #39423c;
--zelenlight: #cfcfca;
--addition-area: #aeafa8;
--addition-area-hover: #676a52;
--accent: #aeafa8;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: #e8e7e3;
font-family: 'Arial', 'Book Antiqua', sans-serif;
font-size: 12px;
color: var(--text);
min-height: 100vh;
padding: 30px 20px;
}
/* главный контейнер */
.forum-window {
max-width: 1000px;
margin: 0 auto;
background: transparent;
}
.inner-panel {
background: var(--link-light);
border-radius: 5px;
padding: 25px 20px 20px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
/* заголовок как в питомнике */
.role-tabs {
display: flex;
gap: 25px;
color: var(--link);
font-size: 18px;
border-bottom: 1px solid var(--link);
padding: 10px;
margin-bottom: 25px;
justify-content: center;
}
.role-tabs span {
padding: 0 15px;
cursor: default;
position: relative;
font-family: 'Book Antiqua', serif;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
color: #39423c; /* было var(--link-hover) */
font-weight: 700;
font-size: 22px;
}
.role-tabs span::before {
position: absolute;
content: '';
left: 0;
bottom: -11px;
display: block;
width: 100%;
height: 5px;
background: var(--link);
}
/* ===== ХРОНОЛОГИЯ ===== */
.timeline-container {
position: relative;
width: 100%;
margin: 0 0 20px 0;
padding: 0;
}
/* вертикальная линия ПО ЦЕНТРУ */
.timeline-line {
position: absolute;
left: 50%;
top: 0;
transform: translateX(-50%);
width: 2px;
height: 100%;
background: var(--accent);
border-radius: 2px;
box-shadow: 0 0 0 1px var(--addition-area-hover);
z-index: 1;
}
/* контейнер для всех событий */
.timeline-events {
position: relative;
z-index: 2;
min-height: 400px;
margin-bottom: 20px;
}
/* отдельное событие */
.timeline-event {
position: relative;
width: 100%;
height: 0;
margin: 0;
padding: 0;
}
/* квадратик на линии - без обводки */
.event-marker {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 24px;
height: 24px;
background: var(--accent);
border: none;
border-radius: 3px;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
z-index: 10;
transition: all 0.2s ease;
cursor: pointer;
}
/* подсветка маркера при наведении */
.event-marker:hover {
transform: translateX(-50%) scale(1.2);
background: var(--link-hover);
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
}
/* сноска с описанием - без обводки */
.event-card {
position: absolute;
width: 45%;
min-width: 280px;
padding: 15px;
background: #e3e2de;
border: none;
border-radius: 5px;
box-shadow: 0 3px 10px rgba(0,0,0,0.15);
transition: all 0.2s ease;
pointer-events: auto;
}
/* подсветка карточки при наведении на маркер */
.timeline-event:hover .event-card {
background: #d6d5d0;
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
transform: translateY(-2px);
}
/* карточка слева от линии */
.event-card.left {
left: 0;
}
/* карточка справа от линии */
.event-card.right {
right: 0;
}
/* треугольник-указатель - без обводки, длинный */
.event-card::after {
content: '';
position: absolute;
top: 15px;
width: 0;
height: 0;
border-style: solid;
filter: drop-shadow(2px 2px 3px rgba(0,0,0,0.1));
transition: all 0.2s ease;
}
/* треугольник для карточки слева */
.event-card.left::after {
right: -16px;
border-width: 12px 0 12px 16px;
border-color: transparent transparent transparent #e3e2de;
}
/* при наведении - треугольник темнее */
.timeline-event:hover .event-card.left::after {
border-color: transparent transparent transparent #d6d5d0;
}
/* треугольник для карточки справа */
.event-card.right::after {
left: -16px;
border-width: 12px 16px 12px 0;
border-color: transparent #e3e2de transparent transparent;
}
.timeline-event:hover .event-card.right::after {
border-color: transparent #d6d5d0 transparent transparent;
}
/* содержимое карточки */
.event-header {
margin-bottom: 16px; /* Увеличено для большего отступа от описания */
}
.event-title {
font-size: 16px;
font-weight: 700;
color: var(--accent);
font-family: 'Book Antiqua', serif;
margin-bottom: 6px; /* Немного увеличен отступ под дату */
display: block;
text-align: left; /* Выравнивание по левому краю */
}
.event-title a {
color: #39423c; /* было var(--accent) */
text-decoration: none !important;
border-bottom: none !important;
}
.event-title a:hover {
color: var(--link-hover); /* оставляем как есть или тоже можете заменить на #39423c если нужно */
border-bottom: none !important;
}
/* Дата ПОД названием - без иконки */
.event-date {
font-size: 11px;
color: var(--link);
font-style: italic;
display: block;
line-height: 1.4;
text-align: left; /* Выравнивание по левому краю */
}
/* описание с выравниванием по ширине */
.event-description {
line-height: 1.5;
color: var(--noblack);
text-align: justify;
width: 100%;
hyphens: auto;
}
/* статистика */
.events-stats {
margin-top: 30px;
margin-bottom: 10px;
padding: 15px;
background: var(--zelenlight);
border-radius: 5px;
display: flex;
justify-content: space-between;
align-items: center;
font-family: 'Book Antiqua', serif;
border: 1px solid var(--addition-area);
position: relative;
z-index: 3;
clear: both;
}
.stats-item {
display: flex;
align-items: center;
gap: 10px;
}
.stats-number {
background: var(--accent);
color: white;
padding: 5px 15px;
border-radius: 30px;
font-weight: 700;
}
/* адаптивность */
@media (max-width: 700px) {
.event-card {
width: 90%;
min-width: auto;
}
.event-card.left, .event-card.right {
left: 5%;
right: auto;
}
.event-card.left::after,
.event-card.right::after {
display: none;
}
.event-marker {
position: relative;
left: 50%;
margin: 10px 0;
}
}
</style>
</head>
<body>
<div class="forum-window">
<div class="inner-panel">
<!-- заголовок как в питомнике -->
<div class="role-tabs">
<span>Хронология событий</span>
</div>
<!-- ХРОНОЛОГИЯ -->
<div class="timeline-container">
<!-- вертикальная линия -->
<div class="timeline-line"></div>
<!-- события -->
<div class="timeline-events" id="timelineEvents"></div>
</div>
<!-- статистика -->
<div class="events-stats">
<div class="stats-item">
<span>📅 Всего событий:</span>
<span class="stats-number" id="totalEvents">0</span>
</div>
<div class="stats-item">
<span>📌 Последнее:</span>
<span id="lastEvent">—</span>
</div>
</div>
</div>
</div>
<script>
(function() {
// ===== ФИКСИРОВАННЫЙ НАБОР СОБЫТИЙ =====
const events = [
{
id: 1,
title: "Победа над лисами",
date: "6 луна 2009",
link: "https://cwotgoloski.ru/viewtopic.php?id=1311#p30391",
description: "Четыре племени котов-воителей сильно пострадали от поселившегося рядом с ними племенем лис. Битва была неизбежна, и в финальном столкновении коты одержали победу, однако во время схватки с вожаком лис погиб предводитель Грозового племени Звёздный Снег.",
side: 'right',
position: 1
},
{
id: 2,
title: "Великое Путешествие",
date: "11 луна 2009",
link: "https://cwotgoloski.ru/viewtopic.php?id=2383#p93205",
description: "Племена покидают старые земли. Начало поисков нового дома. Это был долгий и трудный путь через высокие горы и бурные реки, но вера в Звёздное племя придавала котам сил.",
side: 'left',
position: 2
},
{
id: 3,
title: "Лунное озеро",
date: "12 луна 2009",
link: "https://cwotgoloski.ru/viewtopic.php?id=1040#p21825",
description: "Коты-воители нашли Лунное Озеро и новый дом.",
side: 'right',
position: 3
},
{
id: 4,
title: "Дележка земель Грозового племени",
date: "2 луна 2011",
link: "https://cwotgoloski.ru/viewtopic.php?id=1041&p=38#p55332",
description: "Племя Теней и племя Ветра объединилось против Грозового племени. Они напали на Грозовой лагерь и после неравного боя отняли часть их земель, сдвинув границу внутрь территории.",
side: 'left',
position: 4
},
{
id: 5,
title: "Маленький Сон",
date: "10 луна 2011",
link: "https://cwotgoloski.ru/viewtopic.php?id=1944#p65747",
description: "В лесу начинается мистика: пропадают коты. Во всем оказывается замешан Маленький Сон, и только пророчество Звёздного племени подсказало, как спасти его жертв.",
side: 'right',
position: 5
},
{
id: 6,
title: "Сражение с Четверкой",
date: "9 луна 2012",
link: "https://cwotgoloski.ru/viewtopic.php?id=1404&p=67#p97432",
description: "Коты-воители сражаются с Четверкой (восставшими из темного леса котами - Раной, Кровавым Месяцем, Ужасом и Черит). Великое сражение, унесшее множество жизней.",
side: 'left',
position: 6
},
{
id: 7,
title: "Нападение одиночек",
date: "5 луна 2013",
link: "https://cwotgoloski.ru/viewtopic.php?id=2665&p=13#p118472",
description: "На Речное племя нападает свора одиночек, которых натравила на свое племя Ива.",
side: 'right',
position: 7
},
{
id: 8,
title: "Уход племени Теней",
date: "7 луна 2013",
link: "https://cwotgoloski.ru/viewtopic.php?id=2533&p=44#p126800",
description: "Из-за неправильного толкования пророчества племя Теней покидает лес и уходит в горы. Остальные три племени не знают о том, куда делось племя Теней.",
side: 'left',
position: 8
},
{
id: 9,
title: "Битва Ветра и Реки",
date: "3 луна 2014",
link: "https://cwotgoloski.ru/viewtopic.php?id=3308#p160615",
description: "Шелест Звёзд объявляет войну Речному племени и нападает на них в их же лагере.",
side: 'right',
position: 9
},
{
id: 10,
title: "Возвращение племени Теней",
date: "9 луна 2014",
link: "https://cwotgoloski.ru/viewtopic.php?id=2583&p=26#p183342",
description: "Племя Теней вернулось на свои земли под руководством нового предводителя - Жабозвёзда. Их первый Совет, породивший новые конфликты и поднявший старые вопросы.",
side: 'left',
position: 10
},
{
id: 11,
title: "Битва за Небесный дуб",
date: "10 луна 2014",
link: "https://cwotgoloski.ru/viewtopic.php?id=955&p=24#p190426",
description: "Грозовое племя претендует на Небесный дуб, которое было отнято племенем Теней во времена правления Рыжей Кометы и Холода Звезд. Они готовы сражаться за земли, которые когда-то принадлежали им.",
side: 'right',
position: 11
},
{
id: 12,
title: "Битва Темного леса и Звездного племени",
date: "3 луна 2015",
link: "https://cwotgoloski.ru/viewtopic.php?id=26&p=15#p219248",
description: "Темный лес смог пробраться на Серебряный пояс и напасть на предков котов-воителей. Многие были убиты навсегда, а Звездное племя изгнано со своих мест.",
side: 'left',
position: 12
},
{
id: 13,
title: "Небесные предки",
date: "8 луна 2015",
link: "https://cwotgoloski.ru/viewtopic.php?id=3900#p251217",
description: "У Лунного камня, где обосновалось Звездное племя, появился предок Небесного племени. Предки Небесных объединяются со Звёздным племенем и решают, что Небесному племени необходимо присоединиться к четырем племенам.",
side: 'right',
position: 13
},
{
id: 14,
title: "Мастер",
date: "12 луна 2015",
link: "https://cwotgoloski.ru/viewtopic.php?id=3935&p=17#p265029",
description: "Мастер захватывает Грозовое племя, запудрив мозг Кристальной Звезде. Кристальная Звезда отправляется на поиски своей внучки Диковинки, а племя остается на самозванца.",
side: 'left',
position: 14
},
{
id: 15,
title: "Совет с Мастером",
date: "1 луна 2016",
link: "https://cwotgoloski.ru/viewtopic.php?id=2583&p=71#p266486",
description: "Мастер приводит Грозовое племя на Совет. После возмущений других племен он с легкостью отнимает жизнь Острозвёзда, заставив всех себя слушать.",
side: 'right',
position: 15
},
{
id: 16,
title: "Свержение Мастера",
date: "2 луна 2016",
link: "https://cwotgoloski.ru/viewtopic.php?id=4629&p=19#p269162",
description: "Мастер дошел до точки кипения Грозовых, заставив целительниц биться насмерть. Подоспевший из Речного племени Кедр, у которого были свои счеты с серым самозванцем, помог с ним расправиться. (навсегда ли?)",
side: 'left',
position: 16
},
{
id: 17,
title: "Небесное племя",
date: "5 луна 2016",
link: "https://cwotgoloski.ru/viewtopic.php?id=2583&p=76#p281586",
description: "Небесное племя появляется в лесу, своим появлением также возвращая на небеса Звёздное племя в новом составе (предки Небесных также присоединились, забыв о старых конфликтах). Равновесие восстановлено.",
side: 'right',
position: 17
},
{
id: 18,
title: "Свержение Острозвёзда",
date: "2 луна 2017",
link: "https://cwotgoloski.ru/viewtopic.php?id=5080&p=33#p355626",
description: "Новая попытка Ивы в своюзе с Мастером натравить одиночек на Речное племя - на сей раз удачное. Острозвезда свергли и ослепили, Ива объявляет себя Ивовой Звездой. Глашатай Осинник объявлен в розыск.",
side: 'left',
position: 18
},
{
id: 19,
title: "Уход Небесного племени",
date: "2 луна 2017",
link: "https://cwotgoloski.ru/viewtopic.php?id=4425&p=77#p387864",
description: "Небесное племя исчезло с земель котов-воителей. Часть оставшихся перешло в племя Теней, а один кот (Олений) в Речное племя на должность целителя ввиду отсустствия такового после разгрома племени Ивой и Мастером.",
side: 'right',
position: 19
},
{
id: 20,
title: "Сражение за Речное племя",
date: "12 луна 2017",
link: "https://cwotgoloski.ru/viewtopic.php?id=5080&p=51#p406681",
description: "Осозвёзд получил дар девяти жизней у Лунного Озера и пошел свергать тиранию Мастера и Ивовой Звезды. Ивовая Звезда после этого считается мертвой, однако тела ее не нашли.",
side: 'left',
position: 20
},
{
id: 21,
title: "Финальная битва за Небесный дуб",
date: "11 луна 2019",
link: "https://cwotgoloski.ru/viewtopic.php?id=955&p=46#p429727",
description: "Племя Теней сражается с Грозовым племенем за Небесный дуб. Финальная битва, в итоге которой дуб раскалывает надвое стихией.",
side: 'right',
position: 21
},
{
id: 22,
title: "Раскол племени Ветра",
date: "4 луна 2022",
link: "https://cwotgoloski.ru/viewtopic.php?id=945&p=59#p453822",
description: "После ухода Звёздной Сойки из племени, Ветер разделился на два лагеря - одни за Звездное племя и туннели, другое против всего перечисленного.",
side: 'left',
position: 22
},
{
id: 23,
title: "Алозвёзд и объединение",
date: "4 луна 2023",
link: "https://cwotgoloski.ru/viewtopic.php?id=6305&p=51#p479191",
description: "Обманутый кознями Ивы и Мастера Алозвезд приводит одиночек на Остров Советов и говорит о том, что он будет рад всем, кто хочет вступить в Единое племя.",
side: 'right',
position: 23
},
{
id: 24,
title: "Битва за лес",
date: "12 луна 2023",
link: "https://cwotgoloski.ru/viewtopic.php?id=1813&p=9#p489064",
description: "Племена сражаются с Темным лесом и их приспешниками. В этой битве лес теряет множество котов, среди которых предводитель Речного племени, Осозвёзд, чье тело Кречет уносит на Озеро предков и исчезает сам.",
side: 'left',
position: 24
},
{
id: 25,
title: "Суд над Алозвездом",
date: "8 луна 2024",
link: "https://cwotgoloski.ru/viewtopic.php?id=6305&p=64#p501531",
description: "Племена вершат суд над Алозвёздом, которого считают виновным в происшедшей битве.",
side: 'right',
position: 25
},
{
id: 26,
title: "Раскол Звёздного племени",
date: "2 луна 2025",
link: "https://cwotgoloski.ru/viewtopic.php?id=2838&p=2#p509119",
description: "Битва между Звездным Снегом и Острозвездом и их дальнейший договор, решивший исход племен - отныне будет два племени: Тигриное и Львиное.",
side: 'left',
position: 26
},
{
id: 27,
title: "Тигриное племя",
date: "2 луна 2025",
link: "https://cwotgoloski.ru/viewtopic.php?id=6883&p=85#p508989",
description: "Метеор со своим отрядом приходит в племя Ветра, чтобы отныне присоединить остатки воителей и создать Тигриное племя по заветам своего предка Острозвёзда.",
side: 'right',
position: 27
},
];
// Константы для позиционирования
const MARKER_SIZE = 24;
const MIN_MARKER_DISTANCE = 25;
const MARKER_TOP_OFFSET = 15;
const INITIAL_TOP = 30;
const CARD_GAP = 8;
// Получаем контейнер
const timelineEvents = document.getElementById('timelineEvents');
// Функция для расчета высоты карточки
function getCardHeight(description) {
const baseHeight = 80; // padding (30px) + заголовок (20px) + дата (15px) + отступ (15px)
const lines = Math.ceil(description.length / 45);
return baseHeight + lines * 15;
}
// Функция для проверки пересечения карточек
function cardsOverlap(card1, card2) {
if (card1.side === card2.side) {
const card1Bottom = card1.top + card1.height;
const card2Bottom = card2.top + card2.height;
return (card1Bottom + CARD_GAP) > card2.top;
}
return false;
}
// Функция для размещения событий
function layoutEvents() {
// Копируем массив для расчётов, чтобы не изменять исходные данные
const eventsCopy = events.map(e => ({...e}));
// Сортируем по позиции
eventsCopy.sort((a, b) => a.position - b.position);
// Рассчитываем высоты
eventsCopy.forEach(event => {
event.cardHeight = getCardHeight(event.description);
});
let currentTop = INITIAL_TOP;
const placedCards = [];
for (let i = 0; i < eventsCopy.length; i++) {
const event = eventsCopy[i];
event.markerTop = currentTop;
let cardTop = event.markerTop - MARKER_TOP_OFFSET;
let maxOverlap = false;
let maxTop = cardTop;
for (let j = 0; j < placedCards.length; j++) {
const placedCard = placedCards[j];
if (placedCard.side === event.side) {
const placedBottom = placedCard.top + placedCard.height;
if ((placedBottom + CARD_GAP) > cardTop) {
maxOverlap = true;
const newTop = placedBottom + CARD_GAP;
if (newTop > maxTop) {
maxTop = newTop;
}
}
}
}
if (maxOverlap) {
cardTop = maxTop;
event.markerTop = cardTop + MARKER_TOP_OFFSET;
}
placedCards.push({
side: event.side,
top: cardTop,
height: event.cardHeight
});
let nextMarkerBase = event.markerTop + MARKER_SIZE + MIN_MARKER_DISTANCE;
if (i < eventsCopy.length - 1) {
const extraSpace = (eventsCopy[i].side !== eventsCopy[i + 1].side) ? 8 : 0;
currentTop = nextMarkerBase + extraSpace;
} else {
currentTop = nextMarkerBase;
}
event.cardTop = cardTop;
}
return { eventsCopy, totalHeight: currentTop + 20 };
}
// Функция отрисовки
function renderTimeline() {
const { eventsCopy, totalHeight } = layoutEvents();
timelineEvents.style.minHeight = totalHeight + 'px';
let html = '';
eventsCopy.forEach((event) => {
const linkHtml = event.link && event.link !== '#'
? `<a href="${event.link}" target="_blank">${event.title}</a>` // Убрана скрепка
: event.title;
html += `
<div class="timeline-event" data-id="${event.id}">
<div class="event-marker" style="top: ${event.markerTop}px;" title="${event.date}"></div>
<div class="event-card ${event.side}" style="top: ${event.cardTop}px;">
<div class="event-header">
<div class="event-title">${linkHtml}</div>
<div class="event-date">${event.date}</div> <!-- Убран значок календарика -->
</div>
<div class="event-description">${event.description}</div>
</div>
</div>
`;
});
timelineEvents.innerHTML = html;
document.getElementById('totalEvents').textContent = events.length;
if (events.length > 0) {
const lastEvent = events[events.length - 1];
document.getElementById('lastEvent').textContent = lastEvent.title;
} else {
document.getElementById('lastEvent').textContent = '—';
}
}
// Инициализация
renderTimeline();
})();
</script>
</body>
</html>[/html]