1477 lines
95 KiB
HTML
1477 lines
95 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>между. — CHAPTER / Литературный журнал о близости 18+</title>
|
||
<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=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,600&family=Inter:wght@300;400;500;600&family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<style>
|
||
:root {
|
||
--bg-paper: #F5F0E8;
|
||
--bg-surface: #FFFDFA;
|
||
--bg-subtle: #EAE2D6;
|
||
--text-ink: #24211D;
|
||
--text-meta: #686158;
|
||
--border-hairline: #D8CFC3;
|
||
--border-warm: #D6B39B;
|
||
--accent-wine: #793C49;
|
||
--accent-wine-hover: #612E39;
|
||
--accent-wine-soft: #F3E8EA;
|
||
--video-dark: #211A18;
|
||
--video-surface: #29241F;
|
||
--reading-size: 20px;
|
||
--reading-lh: 32px;
|
||
}
|
||
body.theme-noir {
|
||
--bg-paper: #10121A;
|
||
--bg-surface: #1C2030;
|
||
--bg-subtle: #252B3D;
|
||
--text-ink: #F6F7F2;
|
||
--text-meta: #B9C0D0;
|
||
--border-hairline: #2E364B;
|
||
--border-warm: #3E4760;
|
||
--accent-wine: #C9F26F;
|
||
--accent-wine-hover: #B5E055;
|
||
--accent-wine-soft: rgba(201, 242, 111, 0.12);
|
||
}
|
||
body {
|
||
background-color: var(--bg-paper);
|
||
color: var(--text-ink);
|
||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||
font-size: 16px;
|
||
line-height: 1.55;
|
||
transition: background-color 0.25s ease, color 0.25s ease;
|
||
margin: 0;
|
||
}
|
||
.font-serif-editorial {
|
||
font-family: 'Cormorant Garamond', Georgia, serif;
|
||
}
|
||
.reading-prose p {
|
||
font-family: 'Cormorant Garamond', Georgia, serif;
|
||
font-size: var(--reading-size);
|
||
line-height: var(--reading-lh);
|
||
color: var(--text-ink);
|
||
margin-bottom: 1.45em;
|
||
}
|
||
.hairline-border {
|
||
border-color: var(--border-hairline);
|
||
}
|
||
.surface-card {
|
||
background-color: var(--bg-surface);
|
||
border: 1px solid var(--border-hairline);
|
||
border-radius: 6px;
|
||
}
|
||
.subtle-box {
|
||
background-color: var(--bg-subtle);
|
||
border: 1px solid var(--border-hairline);
|
||
border-radius: 6px;
|
||
}
|
||
.btn-wine {
|
||
background-color: var(--accent-wine);
|
||
color: #FFFDFA;
|
||
border-radius: 6px;
|
||
font-weight: 500;
|
||
transition: all 0.18s ease;
|
||
}
|
||
body.theme-noir .btn-wine {
|
||
color: #10121A;
|
||
font-weight: 600;
|
||
}
|
||
.btn-wine:hover {
|
||
background-color: var(--accent-wine-hover);
|
||
}
|
||
.btn-outline-editorial {
|
||
background-color: var(--bg-surface);
|
||
color: var(--text-ink);
|
||
border: 1px solid var(--border-hairline);
|
||
border-radius: 6px;
|
||
transition: all 0.18s ease;
|
||
}
|
||
.btn-outline-editorial:hover {
|
||
border-color: var(--accent-wine);
|
||
}
|
||
.nav-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 7px 10px;
|
||
border-radius: 5px;
|
||
font-size: 14px;
|
||
color: var(--text-meta);
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
text-align: left;
|
||
width: 100%;
|
||
}
|
||
.nav-item:hover {
|
||
color: var(--text-ink);
|
||
background-color: rgba(121, 60, 73, 0.06);
|
||
}
|
||
.nav-item.active {
|
||
color: var(--text-ink);
|
||
font-weight: 600;
|
||
background-color: var(--accent-wine-soft);
|
||
}
|
||
.nav-item.active::before {
|
||
content: "•";
|
||
color: var(--accent-wine);
|
||
font-weight: bold;
|
||
margin-right: 2px;
|
||
}
|
||
.meta-text {
|
||
color: var(--text-meta);
|
||
}
|
||
.wine-text {
|
||
color: var(--accent-wine);
|
||
}
|
||
.wine-badge {
|
||
background-color: var(--accent-wine-soft);
|
||
color: var(--accent-wine);
|
||
border: 1px solid rgba(121, 60, 73, 0.22);
|
||
border-radius: 4px;
|
||
padding: 2px 8px;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
}
|
||
/* Atmospheric blurred cinema frame for locked video adaptation */
|
||
.cinema-poster-locked {
|
||
background:
|
||
radial-gradient(circle at 72% 38%, rgba(214, 179, 155, 0.42), transparent 45%),
|
||
radial-gradient(circle at 28% 70%, rgba(121, 60, 73, 0.55), transparent 55%),
|
||
linear-gradient(135deg, #201A18 0%, #382927 50%, #1B1615 100%);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.cinema-poster-locked::after {
|
||
content: "";
|
||
position: absolute;
|
||
inset: 0;
|
||
backdrop-filter: blur(14px);
|
||
background: rgba(32, 26, 24, 0.38);
|
||
}
|
||
.cinema-player-unlocked {
|
||
background:
|
||
radial-gradient(circle at 68% 32%, rgba(214, 179, 155, 0.28), transparent 45%),
|
||
radial-gradient(circle at 30% 65%, rgba(121, 60, 73, 0.35), transparent 55%),
|
||
linear-gradient(160deg, #211A18 0%, #2E2320 55%, #161210 100%);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body class="min-h-screen flex flex-col lg:flex-row">
|
||
|
||
<!-- MOBILE HEADER (390px breakpoint from Figma) -->
|
||
<div class="lg:hidden flex items-center justify-between px-5 py-3.5 border-b hairline-border bg-[var(--bg-surface)] sticky top-0 z-30">
|
||
<div class="flex items-baseline gap-2.5 cursor-pointer" onclick="switchScreen('home')">
|
||
<span class="font-serif-editorial text-2xl font-semibold tracking-tight">между.</span>
|
||
<span class="text-[11px] uppercase tracking-widest meta-text">CHAPTER / 18+</span>
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<button onclick="toggleSubscriptionState()" id="mobSubBadge" class="text-[11px] px-2.5 py-1 rounded border hairline-border meta-text">
|
||
Подписка: выкл
|
||
</button>
|
||
<button onclick="document.getElementById('sidebarNav').classList.toggle('hidden')" class="px-3 py-1.5 rounded border hairline-border text-xs font-medium">
|
||
Меню · 18+
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- LEFT SIDEBAR (Exact 232px width from Figma spec 12:317745) -->
|
||
<aside id="sidebarNav" class="hidden lg:flex flex-col justify-between w-full lg:w-[232px] lg:shrink-0 border-r hairline-border bg-[var(--bg-paper)] px-5 py-7 select-none lg:min-h-screen">
|
||
<div class="space-y-6">
|
||
<!-- Brand Header -->
|
||
<div class="cursor-pointer" onclick="switchScreen('home')">
|
||
<div class="font-serif-editorial text-[32px] leading-none font-semibold tracking-tight">между.</div>
|
||
<div class="text-[11px] uppercase tracking-[0.14em] meta-text mt-2 font-medium">CHAPTER / ЖУРНАЛ 18+</div>
|
||
</div>
|
||
|
||
<!-- Primary Literary Navigation -->
|
||
<nav class="space-y-1">
|
||
<button onclick="switchScreen('home')" id="nav-home" class="nav-item active">Главная</button>
|
||
<button onclick="switchScreen('catalog')" id="nav-catalog" class="nav-item">Истории</button>
|
||
<button onclick="switchScreen('videos')" id="nav-videos" class="nav-item">Видео по историям</button>
|
||
<button onclick="switchScreen('continue')" id="nav-continue" class="nav-item">Продолжить чтение</button>
|
||
<button onclick="switchScreen('favorites')" id="nav-favorites" class="nav-item">Избранное</button>
|
||
</nav>
|
||
|
||
<!-- Secondary AI Format Navigation (Figma section: ДРУГОЙ ФОРМАТ · AI) -->
|
||
<div class="pt-4 border-t hairline-border space-y-1">
|
||
<div class="px-2.5 pb-1.5 text-[10px] uppercase tracking-[0.14em] meta-text font-semibold">ДРУГОЙ ФОРМАТ · AI</div>
|
||
<button onclick="switchScreen('ai_heroes')" id="nav-ai_heroes" class="nav-item">AI герои</button>
|
||
<button onclick="switchScreen('ai_chat')" id="nav-ai_chat" class="nav-item">Диалоги</button>
|
||
<button onclick="switchScreen('my_ai')" id="nav-my_ai" class="nav-item">Мои AI</button>
|
||
<button onclick="switchScreen('create_ai')" id="nav-create_ai" class="nav-item">Создать героя</button>
|
||
<button onclick="switchScreen('personal')" id="nav-personal" class="nav-item">Личное</button>
|
||
</div>
|
||
|
||
<!-- Account & Settings Navigation -->
|
||
<div class="pt-4 border-t hairline-border space-y-1">
|
||
<button onclick="switchScreen('subscription')" id="nav-subscription" class="nav-item">Подписка</button>
|
||
<button onclick="switchScreen('login')" id="nav-login" class="nav-item">Анна · Аккаунт</button>
|
||
<button onclick="switchScreen('settings')" id="nav-settings" class="nav-item">Настройки</button>
|
||
<button onclick="switchScreen('states')" id="nav-states" class="nav-item">Помощь · Состояния</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bottom 18+ Editorial Note -->
|
||
<div class="pt-6 border-t hairline-border mt-8 space-y-3">
|
||
<div class="text-xs leading-relaxed meta-text">
|
||
<strong class="font-medium text-[var(--text-ink)] block mb-0.5">Только для взрослых 18+</strong>
|
||
Истории о чувствах и близости.
|
||
</div>
|
||
<div class="flex items-center justify-between text-[11px] meta-text pt-1">
|
||
<span>Тема Figma:</span>
|
||
<button onclick="toggleThemeNoir()" id="themeSwitchBtn" class="underline hover:text-[var(--text-ink)]">
|
||
CHAPTER (Бумага)
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- MAIN EDITORIAL AREA (1440px Grid -> Remaining width with 48px desktop padding) -->
|
||
<div class="flex-1 flex flex-col min-w-0">
|
||
|
||
<!-- Top Section Bar (Полоса раздела + Поиск по журналу ⌘K + Interactive Subscription Toggle) -->
|
||
<header class="border-b hairline-border px-6 lg:px-12 py-3.5 flex flex-wrap items-center justify-between gap-4 bg-[var(--bg-paper)]">
|
||
<div class="flex items-center gap-3">
|
||
<span id="topBreadcrumb" class="text-xs font-medium tracking-wide uppercase meta-text">Главная</span>
|
||
<span class="meta-text opacity-40">·</span>
|
||
<button onclick="switchScreen('reader')" class="text-xs wine-text hover:underline font-medium">
|
||
📖 Открыть рассказ «После полуночи» + Видео ↓
|
||
</button>
|
||
</div>
|
||
|
||
<div class="flex flex-wrap items-center gap-3">
|
||
<!-- Quick Figma State Switcher for Founder Review -->
|
||
<div class="flex items-center gap-1.5 text-xs surface-card px-2.5 py-1">
|
||
<span class="meta-text text-[11px]">Режим видео в рассказах:</span>
|
||
<button onclick="setVideoAccess(false)" id="btnLockedState" class="px-2 py-0.5 rounded text-[11px] font-medium bg-[var(--accent-wine)] text-white">
|
||
🔒 Без подписки
|
||
</button>
|
||
<button onclick="setVideoAccess(true)" id="btnUnlockedState" class="px-2 py-0.5 rounded text-[11px] font-medium meta-text hover:text-[var(--text-ink)]">
|
||
🔓 Подписка активна (Плеер)
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Search Trigger (Поиск по журналу ⌘K from Figma) -->
|
||
<div class="surface-card px-3 py-1.5 flex items-center gap-3 text-xs meta-text">
|
||
<span>Поиск по журналу</span>
|
||
<kbd class="text-[10px] px-1.5 py-0.5 rounded border hairline-border">⌘ K</kbd>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- CONTENT CONTAINER (48px padding on desktop per Figma spec) -->
|
||
<main class="px-6 lg:px-12 py-8 lg:py-12 max-w-[1140px] w-full space-y-14">
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 1: ГЛАВНАЯ (Figma Frame 12:312192 · Главная · десктоп 1440px) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-home" class="space-y-12">
|
||
<!-- Editorial Hero -->
|
||
<div class="border-b hairline-border pb-10 space-y-4">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text font-medium">
|
||
ЛИТЕРАТУРНЫЙ ЖУРНАЛ О БЛИЗОСТИ · 18+
|
||
</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-6xl lg:text-[64px] leading-[1.02] font-normal tracking-tight">
|
||
Между строк.<br />Ближе к чувствам.
|
||
</h1>
|
||
<p class="text-base sm:text-lg meta-text max-w-xl leading-relaxed pt-1">
|
||
Законченные истории для неспешного чтения.<br />
|
||
Сначала — слова. Потом, если захочется, — кино.
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Story of the Day (ИСТОРИЯ ДНЯ / 01 — После полуночи) -->
|
||
<div class="surface-card p-7 lg:p-10 grid grid-cols-1 lg:grid-cols-12 gap-8 items-center">
|
||
<div class="lg:col-span-7 space-y-4">
|
||
<div class="flex flex-wrap items-center gap-2.5">
|
||
<span class="text-xs uppercase tracking-[0.12em] wine-text font-semibold">ИСТОРИЯ ДНЯ / 01</span>
|
||
<span class="meta-text">·</span>
|
||
<span class="text-xs meta-text">Романтическая проза · 3 мин</span>
|
||
<span class="wine-badge">🎬 Есть видео · по подписке</span>
|
||
</div>
|
||
<h2 class="font-serif-editorial text-4xl sm:text-5xl leading-[1.05] font-normal cursor-pointer hover:opacity-80" onclick="openStoryReader(0)">
|
||
После полуночи
|
||
</h2>
|
||
<p class="text-base leading-relaxed">
|
||
Опоздав на последний трамвай, двое решают не торопить утро. Рассказ о смелости остаться рядом.
|
||
</p>
|
||
<div class="text-xs meta-text">
|
||
Персонажи: Вера, 31 · Матвей, 34 | Видео-экранизация в конце текста: 08:40
|
||
</div>
|
||
<div class="pt-2 flex flex-wrap items-center gap-3">
|
||
<button onclick="openStoryReader(0)" class="btn-wine px-6 py-3 text-sm inline-flex items-center gap-2">
|
||
<span>Читать историю</span>
|
||
<span>→</span>
|
||
</button>
|
||
<button onclick="openStoryReaderAndScrollVideo(0)" class="btn-outline-editorial px-4 py-3 text-xs font-medium">
|
||
К видео-экранизации (08:40) ↓
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="lg:col-span-5 subtle-box p-7 lg:p-8 flex flex-col justify-between min-h-[220px]">
|
||
<div class="text-[11px] uppercase tracking-widest meta-text">Цитата из рассказа</div>
|
||
<blockquote class="font-serif-editorial italic text-2xl sm:text-[26px] leading-snug my-4">
|
||
«Иногда достаточно опоздать, чтобы оказаться вовремя».
|
||
</blockquote>
|
||
<div class="text-xs meta-text flex items-center justify-between pt-3 border-t hairline-border">
|
||
<span>Полный текст бесплатный</span>
|
||
<span class="wine-text font-medium">Видео 08:40 после текста →</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Continue Reading Bookmark Widget (ВАША ЗАКЛАДКА · СЕГОДНЯ) -->
|
||
<div class="space-y-4">
|
||
<div class="flex items-center justify-between">
|
||
<h3 class="font-serif-editorial text-2xl font-medium">На вашей странице</h3>
|
||
<button onclick="switchScreen('continue')" class="text-xs wine-text hover:underline font-medium">Продолжить чтение →</button>
|
||
</div>
|
||
<div class="surface-card p-6 flex flex-col md:flex-row md:items-center justify-between gap-6">
|
||
<div class="space-y-1.5 max-w-2xl">
|
||
<div class="text-[11px] uppercase tracking-[0.12em] wine-text font-semibold">ВАША ЗАКЛАДКА · СЕГОДНЯ</div>
|
||
<div class="font-serif-editorial text-2xl font-medium">После полуночи</div>
|
||
<p class="text-sm meta-text">
|
||
Вы остановились у моста: <span class="italic text-[var(--text-ink)]">«На другой стороне реки им нужно было расстаться».</span>
|
||
</p>
|
||
</div>
|
||
<div class="flex flex-col sm:flex-row sm:items-center gap-4 shrink-0">
|
||
<div class="text-right">
|
||
<div class="text-xs font-medium">Прочитано 42%</div>
|
||
<div class="text-[11px] meta-text">Осталось 2 мин</div>
|
||
<div class="w-36 h-1.5 bg-[var(--bg-subtle)] rounded-full overflow-hidden mt-1.5">
|
||
<div class="h-full bg-[var(--accent-wine)]" style="width: 42%"></div>
|
||
</div>
|
||
</div>
|
||
<button onclick="openStoryReader(0)" class="btn-outline-editorial px-4 py-2.5 text-xs font-medium">
|
||
Продолжить с 42% →
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Editorial Selection Grid (Выбор редакции — 3 stories) -->
|
||
<div class="space-y-5">
|
||
<div class="flex items-center justify-between border-b hairline-border pb-3">
|
||
<h3 class="font-serif-editorial text-3xl font-normal">Выбор редакции</h3>
|
||
<button onclick="switchScreen('catalog')" class="text-xs wine-text hover:underline font-medium">Все истории (4) →</button>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||
<!-- Card 1: Кофе после дождя -->
|
||
<article class="surface-card p-6 flex flex-col justify-between space-y-5">
|
||
<div class="space-y-3">
|
||
<div class="text-[11px] uppercase tracking-[0.1em] meta-text">СОВРЕМЕННАЯ РОМАНТИКА · 6 мин</div>
|
||
<h4 class="font-serif-editorial text-2xl font-medium cursor-pointer hover:opacity-80" onclick="openStoryReader(1)">
|
||
Кофе после дождя
|
||
</h4>
|
||
<p class="text-sm meta-text leading-relaxed">
|
||
В маленьком кафе Лида и Денис учатся говорить о будущем, не загадывая его друг за друга.
|
||
</p>
|
||
<blockquote class="font-serif-editorial italic text-base pt-2 border-t hairline-border">
|
||
«Кофе принесли в разных чашках. Лида решила, что это хороший знак: здесь не требовали совпадать.»
|
||
</blockquote>
|
||
</div>
|
||
<div class="pt-3 border-t hairline-border flex items-center justify-between">
|
||
<span class="wine-badge">🎬 Есть видео · 11:20</span>
|
||
<button onclick="openStoryReader(1)" class="text-xs font-medium wine-text hover:underline">Читать →</button>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- Card 2: Вечер в незнакомом городе -->
|
||
<article class="surface-card p-6 flex flex-col justify-between space-y-5">
|
||
<div class="space-y-3">
|
||
<div class="text-[11px] uppercase tracking-[0.1em] meta-text">ПРОЗА О ВЫБОРЕ · 8 мин</div>
|
||
<h4 class="font-serif-editorial text-2xl font-medium cursor-pointer hover:opacity-80" onclick="openStoryReader(2)">
|
||
Вечер в незнакомом городе
|
||
</h4>
|
||
<p class="text-sm meta-text leading-relaxed">
|
||
Три старых друга встречаются на один вечер. У каждого — свой маршрут, но одна общая история.
|
||
</p>
|
||
<blockquote class="font-serif-editorial italic text-base pt-2 border-t hairline-border">
|
||
«Они встретились у гостиницы, которую никто из них не выбрал бы для себя. И потому всем было легко.»
|
||
</blockquote>
|
||
</div>
|
||
<div class="pt-3 border-t hairline-border flex items-center justify-between">
|
||
<span class="wine-badge">🎬 Есть видео · 14:10</span>
|
||
<button onclick="openStoryReader(2)" class="text-xs font-medium wine-text hover:underline">Читать →</button>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- Card 3: Письмо, которое всё изменило -->
|
||
<article class="surface-card p-6 flex flex-col justify-between space-y-5">
|
||
<div class="space-y-3">
|
||
<div class="text-[11px] uppercase tracking-[0.1em] meta-text">ЭПИСТОЛЯРНАЯ ПРОЗА · 4 мин</div>
|
||
<h4 class="font-serif-editorial text-2xl font-medium cursor-pointer hover:opacity-80" onclick="openStoryReader(3)">
|
||
Письмо, которое всё изменило
|
||
</h4>
|
||
<p class="text-sm meta-text leading-relaxed">
|
||
Соня возвращает непрочитанное письмо. Андрей предлагает начать не с объяснений, а с прогулки.
|
||
</p>
|
||
<blockquote class="font-serif-editorial italic text-base pt-2 border-t hairline-border">
|
||
«Конверт пролежал в ящике стола почти год. Теперь Соня держала его так, словно это был билет в город, где она ещё не бывала.»
|
||
</blockquote>
|
||
</div>
|
||
<div class="pt-3 border-t hairline-border flex items-center justify-between">
|
||
<span class="text-xs meta-text px-2 py-0.5 rounded border hairline-border">Пока только текст</span>
|
||
<button onclick="openStoryReader(3)" class="text-xs font-medium wine-text hover:underline">Читать →</button>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 2: КАТАЛОГ ИСТОРИЙ (Figma 12:312704 + Node 12:312729 Filter) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-catalog" class="hidden space-y-10">
|
||
<div class="border-b hairline-border pb-8 space-y-3">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text font-medium">
|
||
БИБЛИОТЕКА / ЗАКОНЧЕННАЯ ПРОЗА / 18+
|
||
</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-5xl lg:text-[56px] leading-[1.04] font-normal">
|
||
Истории, в которых<br />хочется остаться.
|
||
</h1>
|
||
<p class="text-base meta-text max-w-2xl leading-relaxed">
|
||
Романтика и эротическая литература — о внимании, выборе и близости. Литературные истории для взрослых, без грубых сцен. Полный текст каждой истории открыт.
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Filter Bar (Exact Node 12:312729 from the user's Figma URL!) -->
|
||
<div class="flex flex-wrap items-center justify-between gap-4 pb-2">
|
||
<div class="flex flex-wrap items-center gap-2.5">
|
||
<select id="filterGenre" onchange="filterCatalog()" class="surface-card px-3.5 py-2 text-xs font-medium cursor-pointer outline-none">
|
||
<option value="all">Жанр: все ⌄</option>
|
||
<option value="Романтическая проза">Жанр: романтическая проза</option>
|
||
<option value="Современная романтика">Жанр: современная романтика</option>
|
||
<option value="Проза о выборе">Жанр: проза о выборе</option>
|
||
<option value="Эпистолярная проза">Жанр: эпистолярная проза</option>
|
||
</select>
|
||
<select id="filterMood" onchange="filterCatalog()" class="surface-card px-3.5 py-2 text-xs font-medium cursor-pointer outline-none">
|
||
<option value="all">Настроение: любое ⌄</option>
|
||
<option value="night">Ночной город и близость</option>
|
||
<option value="warm">Тёплый разговор</option>
|
||
</select>
|
||
<select id="filterTime" onchange="filterCatalog()" class="surface-card px-3.5 py-2 text-xs font-medium cursor-pointer outline-none">
|
||
<option value="all">Время: любое ⌄</option>
|
||
<option value="short">До 5 минут</option>
|
||
<option value="long">6–10 минут</option>
|
||
</select>
|
||
<select id="filterVideo" onchange="filterCatalog()" class="surface-card px-3.5 py-2 text-xs font-medium cursor-pointer outline-none">
|
||
<option value="all">Видео: все ⌄</option>
|
||
<option value="yes">Есть видео · по подписке</option>
|
||
<option value="text">Пока только текст</option>
|
||
</select>
|
||
</div>
|
||
<div id="catalogCountLabel" class="text-xs meta-text">4 истории · Редакционный порядок</div>
|
||
</div>
|
||
|
||
<div id="catalogGrid" class="grid grid-cols-1 md:grid-cols-2 gap-6"></div>
|
||
|
||
<div class="subtle-box p-5 text-xs meta-text flex flex-wrap items-center justify-between gap-2">
|
||
<span>Не нужно подписываться, чтобы дочитать. Видео — отдельное продолжение знакомства с историей.</span>
|
||
<button onclick="switchScreen('videos')" class="wine-text font-medium hover:underline">Перейти к видеоадаптациям →</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 3: ЧТЕНИЕ ПОЛНОЙ ИСТОРИИ + ВИДЕО В КОНЦЕ (12:313167 & 12:313889) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-reader" class="hidden space-y-10">
|
||
<!-- Reader Top Header & Controls -->
|
||
<div class="border-b hairline-border pb-8 max-w-[680px] space-y-4">
|
||
<div id="readerMetaCategory" class="text-xs uppercase tracking-[0.14em] wine-text font-semibold">
|
||
РОМАНТИЧЕСКАЯ ПРОЗА / 3 мин / 18+
|
||
</div>
|
||
<h1 id="readerTitle" class="font-serif-editorial text-4xl sm:text-5xl lg:text-[56px] leading-[1.04] font-normal">
|
||
После полуночи
|
||
</h1>
|
||
<p id="readerLead" class="text-base sm:text-lg meta-text leading-relaxed">
|
||
Опоздав на последний трамвай, двое решают не торопить утро. Рассказ о смелости остаться рядом.
|
||
</p>
|
||
<div id="readerCharacters" class="text-xs meta-text pt-1">
|
||
Редакция «между.» · Вымышленные взрослые: Вера, 31 · Матвей, 34
|
||
</div>
|
||
|
||
<!-- Reading Comfort Toolbar (А− / А+ / Закладка / Прочитано 42%) -->
|
||
<div class="pt-4 flex flex-wrap items-center justify-between gap-4 border-t hairline-border">
|
||
<div class="flex items-center gap-2">
|
||
<button onclick="changeFontSize(-2)" class="btn-outline-editorial px-3 py-1.5 text-xs font-medium">А−</button>
|
||
<span id="fontSizeIndicator" class="text-xs meta-text px-1">20 px</span>
|
||
<button onclick="changeFontSize(2)" class="btn-outline-editorial px-3 py-1.5 text-xs font-medium">А+</button>
|
||
<button onclick="toggleBookmarkToast()" id="bookmarkBtn" class="btn-outline-editorial px-3.5 py-1.5 text-xs font-medium ml-2">
|
||
🔖 Закладка
|
||
</button>
|
||
</div>
|
||
<div class="text-xs meta-text">
|
||
<strong class="text-[var(--text-ink)]">Прочитано 42%</strong> · Осталось 2 мин
|
||
</div>
|
||
</div>
|
||
|
||
<div class="subtle-box px-4 py-3 text-xs meta-text flex flex-wrap items-center justify-between gap-2">
|
||
<span>Сохранённая позиция — у моста, 42%.</span>
|
||
<a href="#endOfStoryVideoBlock" class="wine-text font-medium hover:underline">Видео по этой истории ↓ · после окончания текста</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 680px Literary Reading Column (Cormorant Garamond 20/32px per Figma spec) -->
|
||
<article class="max-w-[680px] reading-prose">
|
||
<h3 id="readerChapterHeading" class="font-serif-editorial text-2xl font-medium mb-6">I. После полуночи</h3>
|
||
<div id="readerBodyParagraphs"></div>
|
||
|
||
<div class="pt-6 pb-8 border-b hairline-border flex items-center justify-between text-xs uppercase tracking-[0.16em] meta-text">
|
||
<span>КОНЕЦ</span>
|
||
<span>Весь рассказ доступен без подписки · Позиция 42%</span>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- =================================================================== -->
|
||
<!-- KEY PRODUCT FEATURE: VIDEO BLOCK AT THE END OF THE STORY -->
|
||
<!-- Supports both Locked (12:313167) and Unlocked (12:313889 / 12:314274) -->
|
||
<!-- =================================================================== -->
|
||
<div id="endOfStoryVideoBlock" class="max-w-[680px] pt-2 space-y-6">
|
||
<div class="flex flex-wrap items-center justify-between gap-2">
|
||
<div>
|
||
<div class="text-xs uppercase tracking-[0.14em] wine-text font-semibold">ПРОДОЛЖЕНИЕ НА ЭКРАНЕ · 18+</div>
|
||
<h3 class="font-serif-editorial text-3xl font-normal mt-0.5">Видео по этой истории</h3>
|
||
</div>
|
||
<div class="flex items-center gap-1.5 text-xs">
|
||
<button onclick="setVideoAccess(false)" id="readerLockTab" class="px-2.5 py-1 rounded border hairline-border text-xs">
|
||
Состояние: Закрыто
|
||
</button>
|
||
<button onclick="setVideoAccess(true)" id="readerUnlockTab" class="px-2.5 py-1 rounded border hairline-border text-xs">
|
||
Состояние: Открыто (Плеер)
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- STATE A: VIDEO LOCKED (Figma 12:313167 · Полная история · видео закрыто) -->
|
||
<div id="videoLockedCard" class="surface-card overflow-hidden">
|
||
<div class="cinema-poster-locked h-64 sm:h-72 flex flex-col items-center justify-center p-6 text-center relative">
|
||
<div class="relative z-10 max-w-md space-y-3 text-[#FFFDFA]">
|
||
<span class="inline-block px-3 py-1 rounded bg-black/45 border border-white/20 text-[11px] uppercase tracking-widest">
|
||
🔒 Доступно по подписке · <span id="lockedDuration">08:40</span>
|
||
</span>
|
||
<div id="lockedStoryTitle" class="font-serif-editorial text-3xl sm:text-4xl">После полуночи</div>
|
||
<p class="text-xs text-[#E9E1D6] leading-relaxed">
|
||
Записанная кинематографичная экранизация финала истории. Тёплый свет ночной пекарни, мост через реку и продолжение вечера.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="p-6 sm:p-7 space-y-4 bg-[var(--bg-surface)]">
|
||
<div class="flex flex-wrap items-center justify-between gap-4">
|
||
<div>
|
||
<div class="text-sm font-medium">Записанная экранизация · <span id="lockedDurationSub">08:40</span></div>
|
||
<div class="text-xs meta-text mt-0.5">
|
||
Полный текст бесплатный. Подписка открывает только видеоверсии. 690 ₽ / месяц · продлевается автоматически.
|
||
</div>
|
||
</div>
|
||
<div class="flex flex-wrap items-center gap-3">
|
||
<button onclick="setVideoAccess(true)" class="btn-wine px-5 py-2.5 text-xs sm:text-sm">
|
||
Оформить подписку (690 ₽ / мес)
|
||
</button>
|
||
<button onclick="switchScreen('login')" class="btn-outline-editorial px-4 py-2.5 text-xs font-medium">
|
||
Уже есть подписка? Войти
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- STATE B: VIDEO UNLOCKED + CINEMA PLAYER (Figma 12:313889 & 12:314274) -->
|
||
<div id="videoUnlockedCard" class="hidden rounded-lg overflow-hidden border hairline-border bg-[#211A18] text-[#FFFDFA] shadow-xl">
|
||
<div class="cinema-player-unlocked p-6 sm:p-8 space-y-6">
|
||
<div class="flex flex-wrap items-center justify-between gap-2 text-xs text-[#D6B39B]">
|
||
<span class="uppercase tracking-[0.14em] font-medium">ЗАПИСАННАЯ АДАПТАЦИЯ · НЕ AI АВАТАР</span>
|
||
<span class="px-2.5 py-0.5 rounded bg-emerald-500/20 text-emerald-300 border border-emerald-400/30 text-[11px]">
|
||
✓ Подписка активна
|
||
</span>
|
||
</div>
|
||
|
||
<!-- Simulated Atmospheric Cinema Screen -->
|
||
<div class="relative rounded-md overflow-hidden border border-white/15 bg-black/50 aspect-video flex flex-col justify-between p-6">
|
||
<div class="flex items-center justify-between text-xs text-white/75">
|
||
<span id="playerStoryTitle" class="font-serif-editorial text-2xl text-white">После полуночи · Экранизация</span>
|
||
<span id="playerDurationBadge" class="font-mono text-xs">02:16 / 08:40</span>
|
||
</div>
|
||
|
||
<!-- Center Play/Pause Button & Scene Subtitle -->
|
||
<div class="my-auto text-center space-y-3">
|
||
<button onclick="toggleVideoPlayback()" id="playPauseCircle" class="w-16 h-16 rounded-full bg-[#793C49]/90 hover:bg-[#793C49] text-white flex items-center justify-center mx-auto text-xl shadow-lg transition transform hover:scale-105">
|
||
▶
|
||
</button>
|
||
<p id="videoSubtitleLine" class="font-serif-editorial italic text-lg sm:text-xl text-[#F5F0E8] max-w-md mx-auto">
|
||
«Под светом настольной лампы нашлось место и двум чашкам, и половине тёплого хлеба...»
|
||
</p>
|
||
<div id="videoStateNote" class="text-[11px] text-white/60">
|
||
На паузе · Нажмите ▶ для запуска демонстрации сцены
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Player Scrubber & Controls -->
|
||
<div class="space-y-2.5">
|
||
<div class="w-full h-1.5 bg-white/20 rounded-full overflow-hidden cursor-pointer" onclick="scrubVideo(event)">
|
||
<div id="videoProgressBar" class="h-full bg-[#D6B39B] transition-all duration-300" style="width: 28%"></div>
|
||
</div>
|
||
<div class="flex items-center justify-between text-[11px] text-white/80">
|
||
<div class="flex items-center gap-4">
|
||
<button onclick="toggleVideoPlayback()" id="playPauseTextBtn" class="hover:text-white font-medium">▶ Воспроизвести</button>
|
||
<span>🔊 Звук: вкл</span>
|
||
<span>CC Субтитры: рус</span>
|
||
</div>
|
||
<div class="flex items-center gap-3">
|
||
<span>1080p HD</span>
|
||
<span>⛶ Полный экран</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Next Story Recommendation (Figma 12:314274: После просмотра) -->
|
||
<div class="pt-4 border-t border-white/10 flex flex-wrap items-center justify-between gap-4 text-xs">
|
||
<div>
|
||
<div class="text-[#D6B39B] uppercase tracking-wider text-[10px]">После просмотра</div>
|
||
<div class="text-white/90 mt-0.5">
|
||
Следующая история: <strong>«Кофе после дождя»</strong> · современная романтика · 6 мин. Видеоверсия — 11:20.
|
||
</div>
|
||
</div>
|
||
<button onclick="openStoryReader(1)" class="px-4 py-2 rounded bg-white/10 hover:bg-white/20 text-white font-medium transition">
|
||
Читать «Кофе после дождя» →
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pt-2">
|
||
<button onclick="switchScreen('catalog')" class="text-xs meta-text hover:text-[var(--text-ink)]">
|
||
← К каталогу историй
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 4: ВИДЕО ПО ИСТОРИЯМ (Figma Frame 12:314623 · Десктоп) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-videos" class="hidden space-y-10">
|
||
<div class="border-b hairline-border pb-8 space-y-3">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text font-medium">
|
||
ИЗ БИБЛИОТЕКИ — НА ЭКРАН
|
||
</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-5xl lg:text-[56px] leading-[1.04] font-normal">
|
||
Те же чувства.<br />Другой язык.
|
||
</h1>
|
||
<p class="text-base meta-text max-w-2xl leading-relaxed">
|
||
Записанные адаптации прочитанных историй. Текст открыт каждому; для видео нужна подписка.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="subtle-box p-5 flex flex-wrap items-center justify-between gap-4">
|
||
<div class="space-y-1">
|
||
<div class="text-sm font-medium">Видеоверсии доступны по подписке (690 ₽ / месяц)</div>
|
||
<div class="text-xs meta-text">
|
||
В состоянии без подписки постеры размыты одинаково. Вы можете мгновенно протестировать оба состояния ниже.
|
||
</div>
|
||
</div>
|
||
<button onclick="toggleSubscriptionState()" class="btn-wine px-4 py-2 text-xs">
|
||
Переключить доступ к видео
|
||
</button>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||
<!-- Video 1 -->
|
||
<div class="surface-card overflow-hidden flex flex-col justify-between">
|
||
<div>
|
||
<div class="cinema-poster-locked h-44 flex items-center justify-center p-4 text-center">
|
||
<span class="relative z-10 px-3 py-1 rounded bg-black/55 text-[#FFFDFA] text-xs font-medium">
|
||
🎬 После полуночи · 08:40
|
||
</span>
|
||
</div>
|
||
<div class="p-6 space-y-2.5">
|
||
<div class="text-[11px] uppercase tracking-wider wine-text font-semibold">Доступно по подписке · 08:40</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">После полуночи</h3>
|
||
<p class="text-xs meta-text leading-relaxed">
|
||
Опоздав на последний трамвай, двое решают не торопить утро. Рассказ о смелости остаться рядом.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="p-6 pt-0 flex items-center gap-2">
|
||
<button onclick="openStoryReaderAndScrollVideo(0)" class="btn-wine flex-1 py-2 text-xs">Смотреть / К видео</button>
|
||
<button onclick="openStoryReader(0)" class="btn-outline-editorial px-3 py-2 text-xs">Текст</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Video 2 -->
|
||
<div class="surface-card overflow-hidden flex flex-col justify-between">
|
||
<div>
|
||
<div class="cinema-poster-locked h-44 flex items-center justify-center p-4 text-center">
|
||
<span class="relative z-10 px-3 py-1 rounded bg-black/55 text-[#FFFDFA] text-xs font-medium">
|
||
🎬 Кофе после дождя · 11:20
|
||
</span>
|
||
</div>
|
||
<div class="p-6 space-y-2.5">
|
||
<div class="text-[11px] uppercase tracking-wider wine-text font-semibold">Доступно по подписке · 11:20</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">Кофе после дождя</h3>
|
||
<p class="text-xs meta-text leading-relaxed">
|
||
В маленьком кафе Лида и Денис учатся говорить о будущем, не загадывая его друг за друга.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="p-6 pt-0 flex items-center gap-2">
|
||
<button onclick="openStoryReaderAndScrollVideo(1)" class="btn-wine flex-1 py-2 text-xs">Смотреть / К видео</button>
|
||
<button onclick="openStoryReader(1)" class="btn-outline-editorial px-3 py-2 text-xs">Текст</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Video 3 -->
|
||
<div class="surface-card overflow-hidden flex flex-col justify-between">
|
||
<div>
|
||
<div class="cinema-poster-locked h-44 flex items-center justify-center p-4 text-center">
|
||
<span class="relative z-10 px-3 py-1 rounded bg-black/55 text-[#FFFDFA] text-xs font-medium">
|
||
🎬 Вечер в незнакомом городе · 14:10
|
||
</span>
|
||
</div>
|
||
<div class="p-6 space-y-2.5">
|
||
<div class="text-[11px] uppercase tracking-wider wine-text font-semibold">Доступно по подписке · 14:10</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">Вечер в незнакомом городе</h3>
|
||
<p class="text-xs meta-text leading-relaxed">
|
||
Три старых друга встречаются на один вечер. У каждого — свой маршрут, но одна общая история.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="p-6 pt-0 flex items-center gap-2">
|
||
<button onclick="openStoryReaderAndScrollVideo(2)" class="btn-wine flex-1 py-2 text-xs">Смотреть / К видео</button>
|
||
<button onclick="openStoryReader(2)" class="btn-outline-editorial px-3 py-2 text-xs">Текст</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="text-xs meta-text">
|
||
У истории «Письмо, которое всё изменило» пока нет видео. Она остаётся в каталоге текстов.
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 5: ПРОДОЛЖИТЬ ЧТЕНИЕ (Figma Frame 12:315008) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-continue" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-8 space-y-3">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text font-medium">ВАША ПОЗИЦИЯ В ТЕКСТЕ</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-5xl leading-[1.04] font-normal">
|
||
Мы оставили<br />страницу открытой.
|
||
</h1>
|
||
<p class="text-sm meta-text max-w-xl">
|
||
Только начатые истории. Закладки избранного и сохранённые AI-материалы находятся в своих разделах.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="space-y-4">
|
||
<div class="surface-card p-6 flex flex-col sm:flex-row sm:items-center justify-between gap-6">
|
||
<div class="space-y-1.5">
|
||
<div class="text-xs meta-text">Романтическая проза · 3 мин · Сегодня, 21:14 · абзац у моста</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">После полуночи</h3>
|
||
<p class="font-serif-editorial italic text-lg meta-text">«На другой стороне реки им нужно было расстаться.»</p>
|
||
</div>
|
||
<div class="flex items-center gap-4 shrink-0">
|
||
<div class="text-right">
|
||
<div class="text-xs font-medium">Прочитано 42%</div>
|
||
<div class="text-[11px] meta-text">Осталось 2 мин</div>
|
||
</div>
|
||
<button onclick="openStoryReader(0)" class="btn-wine px-4 py-2.5 text-xs">Продолжить с 42%</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="surface-card p-6 flex flex-col sm:flex-row sm:items-center justify-between gap-6">
|
||
<div class="space-y-1.5">
|
||
<div class="text-xs meta-text">Современная романтика · 6 мин · Вчера, 19:06 · начало рассказа</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">Кофе после дождя</h3>
|
||
<p class="font-serif-editorial italic text-lg meta-text">«Кофе принесли в разных чашках.»</p>
|
||
</div>
|
||
<div class="flex items-center gap-4 shrink-0">
|
||
<div class="text-right">
|
||
<div class="text-xs font-medium">Прочитано 18%</div>
|
||
<div class="text-[11px] meta-text">Осталось 5 мин</div>
|
||
</div>
|
||
<button onclick="openStoryReader(1)" class="btn-outline-editorial px-4 py-2.5 text-xs font-medium">Продолжить с 18%</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="text-xs meta-text">Прогресс относится к чтению текста, а не к просмотру видео.</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 6: ИЗБРАННОЕ (Figma Frame 12:315383) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-favorites" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-8 space-y-3">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text font-medium">СОХРАНЁННОЕ ДЛЯ ВДОХНОВЕНИЯ</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-5xl leading-[1.04] font-normal">
|
||
К этому<br />хочется вернуться.
|
||
</h1>
|
||
<p class="text-sm meta-text max-w-xl">
|
||
Истории, видео и AI герои — три отдельные коллекции. Здесь нет прогресса чтения или личных версий AI.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||
<div class="surface-card p-6 space-y-3">
|
||
<div class="text-[11px] uppercase tracking-wider meta-text">РОМАНТИЧЕСКАЯ ПРОЗА · 3 мин</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">После полуночи</h3>
|
||
<p class="text-xs meta-text">Опоздав на последний трамвай, двое решают не торопить утро.</p>
|
||
<div class="pt-3 border-t hairline-border flex items-center justify-between">
|
||
<span class="wine-badge">Есть видео · по подписке</span>
|
||
<button onclick="openStoryReader(0)" class="text-xs wine-text font-medium">Читать историю →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="surface-card p-6 space-y-3">
|
||
<div class="text-[11px] uppercase tracking-wider meta-text">ЭПИСТОЛЯРНАЯ ПРОЗА · 4 мин</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">Письмо, которое всё изменило</h3>
|
||
<p class="text-xs meta-text">Соня возвращает непрочитанное письмо. Андрей предлагает начать с прогулки.</p>
|
||
<div class="pt-3 border-t hairline-border flex items-center justify-between">
|
||
<span class="text-xs meta-text">Пока только текст</span>
|
||
<button onclick="openStoryReader(3)" class="text-xs wine-text font-medium">Читать историю →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="subtle-box p-6 space-y-2.5 text-xs">
|
||
<div class="font-semibold text-sm">В коллекции</div>
|
||
<p class="meta-text">Истории · 2</p>
|
||
<p class="meta-text">Видео · 1 («После полуночи», 08:40)</p>
|
||
<p class="meta-text">AI герои · 1 (Инга, 32)</p>
|
||
<p class="meta-text pt-2 border-t hairline-border">
|
||
Личные конфигурации — в «Мои AI», материалы из своих разговоров — в «Личное».
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 7: AI ГЕРОИ (Figma Frame 12:317609 · ДРУГОЙ ФОРМАТ · AI) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-ai_heroes" class="hidden space-y-10">
|
||
<div class="border-b hairline-border pb-8 space-y-3">
|
||
<div class="text-xs uppercase tracking-[0.14em] wine-text font-semibold">ДРУГОЙ ФОРМАТ · AI / ВЗРОСЛЫЕ ВЫМЫШЛЕННЫЕ ПЕРСОНАЖИ 18+</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-5xl leading-[1.04] font-normal">
|
||
Разговор, у которого<br />есть характер.
|
||
</h1>
|
||
<p class="text-sm meta-text max-w-2xl">
|
||
Камерные диалоги по мотивам атмосферы журнала. Выбирайте готовый образ или настройте темп и дистанцию под себя.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||
<div class="surface-card p-6 flex flex-col justify-between space-y-5">
|
||
<div class="space-y-3">
|
||
<div class="flex items-center justify-between">
|
||
<span class="wine-badge">AI · 18+</span>
|
||
<span class="text-xs meta-text">Спокойный · Внимательный</span>
|
||
</div>
|
||
<h3 class="font-serif-editorial text-3xl font-medium">Лев, 36</h3>
|
||
<p class="text-xs font-medium wine-text">Архитектор · Вечерний город</p>
|
||
<p class="text-sm meta-text leading-relaxed">
|
||
Внимательный к деталям, с мягкой иронией. Любит старые мосты, поздние трамваи и разговоры без спешки.
|
||
</p>
|
||
</div>
|
||
<div class="pt-3 border-t hairline-border flex items-center gap-2">
|
||
<button onclick="switchScreen('ai_chat')" class="btn-wine flex-1 py-2.5 text-xs">Открыть диалог →</button>
|
||
<button onclick="switchScreen('my_ai')" class="btn-outline-editorial px-3 py-2.5 text-xs">Моя версия</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="surface-card p-6 flex flex-col justify-between space-y-5">
|
||
<div class="space-y-3">
|
||
<div class="flex items-center justify-between">
|
||
<span class="wine-badge">AI · 18+</span>
|
||
<span class="text-xs meta-text">Тёплый · Литературный</span>
|
||
</div>
|
||
<h3 class="font-serif-editorial text-3xl font-medium">Инга, 32</h3>
|
||
<p class="text-xs font-medium wine-text">Переводчица · Маленькие кафе</p>
|
||
<p class="text-sm meta-text leading-relaxed">
|
||
Любит прогулки после дождя и разговоры о редких словах. Умеет слушать паузы между фразами.
|
||
</p>
|
||
</div>
|
||
<div class="pt-3 border-t hairline-border flex items-center gap-2">
|
||
<button onclick="switchScreen('ai_chat')" class="btn-wine flex-1 py-2.5 text-xs">Открыть диалог →</button>
|
||
<button onclick="switchScreen('my_ai')" class="btn-outline-editorial px-3 py-2.5 text-xs">Моя версия</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="surface-card p-6 flex flex-col justify-between space-y-5">
|
||
<div class="space-y-3">
|
||
<div class="flex items-center justify-between">
|
||
<span class="wine-badge">AI · Конструктор</span>
|
||
<span class="text-xs meta-text">5 шагов</span>
|
||
</div>
|
||
<h3 class="font-serif-editorial text-3xl font-medium">Свой образ</h3>
|
||
<p class="text-xs font-medium wine-text">Персональная настройка</p>
|
||
<p class="text-sm meta-text leading-relaxed">
|
||
Задайте образ, внешность, характер, голос и границы общения в спокойном 5-шаговом конструкторе.
|
||
</p>
|
||
</div>
|
||
<div class="pt-3 border-t hairline-border">
|
||
<button onclick="switchScreen('create_ai')" class="btn-outline-editorial w-full py-2.5 text-xs font-medium">
|
||
Создать героя →
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 8: ДИАЛОГИ + AI ВИДЕОДИАЛОГ (Figma Frame 12:317552) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-ai_chat" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-6 flex flex-wrap items-center justify-between gap-4">
|
||
<div>
|
||
<div class="text-xs uppercase tracking-[0.14em] wine-text font-semibold">ДИАЛОГИ / ЛЕВ, 36 · AI · ЛИЧНАЯ ВЕРСИЯ</div>
|
||
<h1 class="font-serif-editorial text-3xl sm:text-4xl font-normal mt-1">Лев · Кофе после дождя</h1>
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<button onclick="toggleAiVideoMode(false)" id="chatModeTextBtn" class="btn-wine px-3.5 py-1.5 text-xs">Текст и голос</button>
|
||
<button onclick="toggleAiVideoMode(true)" id="chatModeVideoBtn" class="btn-outline-editorial px-3.5 py-1.5 text-xs">AI видеодиалог (Аватар)</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- AI Video Avatar Call Box (Hidden by default, toggled via button) -->
|
||
<div id="aiVideoCallBox" class="hidden rounded-lg p-6 bg-[#211A18] text-[#FFFDFA] space-y-4">
|
||
<div class="flex items-center justify-between text-xs text-[#D6B39B]">
|
||
<span>AI ВИДЕОДИАЛОГ · ВЫМЫШЛЕННЫЙ AI АВАТАР · 18+</span>
|
||
<span>Камера пользователя: Выкл. (необязательна)</span>
|
||
</div>
|
||
<div class="aspect-video max-h-[340px] w-full rounded bg-black/50 border border-white/15 flex flex-col items-center justify-center p-6 text-center space-y-3">
|
||
<div class="w-20 h-20 rounded-full bg-[#793C49]/40 border border-[#D6B39B] flex items-center justify-center font-serif-editorial text-3xl">
|
||
Л
|
||
</div>
|
||
<div class="font-serif-editorial text-2xl">Лев, 36 · AI аватар готов к разговору</div>
|
||
<p class="text-xs text-white/70 max-w-md">
|
||
«Кажется, дождь решил задержать нас здесь ещё на полчаса. Я не против. А ты?»
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Chat Messages Thread -->
|
||
<div class="surface-card p-6 space-y-5 max-w-[760px]">
|
||
<div class="text-center text-xs meta-text pb-2 border-b hairline-border">
|
||
Сегодня · Сцена: «За окном дождь. В кафе почти никого.»
|
||
</div>
|
||
|
||
<div id="chatMessagesList" class="space-y-4">
|
||
<div class="subtle-box p-4 max-w-lg space-y-1">
|
||
<div class="text-[11px] meta-text">19:41 · Лев · AI</div>
|
||
<p class="text-sm">Кажется, дождь решил задержать нас здесь. Я не против. А ты?</p>
|
||
</div>
|
||
|
||
<div class="p-4 rounded-md bg-[var(--accent-wine-soft)] ml-auto max-w-lg space-y-1">
|
||
<div class="text-[11px] wine-text">19:41 · Вы · Доставлено ✓✓</div>
|
||
<p class="text-sm">Если кофе хороший — я тоже. Часто сюда заходишь?</p>
|
||
</div>
|
||
|
||
<div class="subtle-box p-4 max-w-lg space-y-1">
|
||
<div class="text-[11px] meta-text">19:42 · Лев · AI</div>
|
||
<p class="text-sm">Когда хочется замедлиться. Здесь никто не торопит, а бариста запоминает любимый кофе. Что заказать тебе?</p>
|
||
</div>
|
||
</div>
|
||
|
||
<form onsubmit="sendAiChatMessage(event)" class="pt-4 border-t hairline-border flex gap-2">
|
||
<input id="aiChatInput" type="text" placeholder="Написать Льву…" class="flex-1 px-4 py-2.5 rounded border hairline-border bg-[var(--bg-paper)] text-sm outline-none" />
|
||
<button type="submit" class="btn-wine px-5 py-2.5 text-xs">Отправить</button>
|
||
</form>
|
||
<div class="text-[11px] meta-text">
|
||
Лев — AI. Ответы вымышлены. Вы всегда можете сохранить понравившуюся фразу в «Личное».
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 9: МОИ AI & СОЗДАТЬ ГЕРОЯ & ЛИЧНОЕ (12:317510 / 460 / 425) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-my_ai" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-6">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text">ЛИЧНЫЕ КОНФИГУРАЦИИ · AI</div>
|
||
<h1 class="font-serif-editorial text-4xl font-normal mt-1">Мои AI</h1>
|
||
<p class="text-sm meta-text mt-1">Сохранённые версии героев с вашим темпом беседы и границами.</p>
|
||
</div>
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||
<div class="surface-card p-6 space-y-3">
|
||
<div class="wine-badge inline-block">Личная версия</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">Лев · моя версия</h3>
|
||
<p class="text-xs meta-text">Тон: спокойный, внимательный · Сценарий: вечерний город после дождя.</p>
|
||
<button onclick="switchScreen('ai_chat')" class="btn-wine px-4 py-2 text-xs">Продолжить диалог →</button>
|
||
</div>
|
||
<div class="surface-card p-6 space-y-3">
|
||
<div class="wine-badge inline-block">Конструктор</div>
|
||
<h3 class="font-serif-editorial text-2xl font-medium">Создать нового героя</h3>
|
||
<p class="text-xs meta-text">Настройте имя, возраст (18+), тембр голоса и характер с нуля.</p>
|
||
<button onclick="switchScreen('create_ai')" class="btn-outline-editorial px-4 py-2 text-xs">Открыть конструктор →</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="screen-create_ai" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-6">
|
||
<div class="text-xs uppercase tracking-[0.14em] wine-text font-semibold">КОНСТРУКТОР ОБРАЗА · 5 ШАГОВ</div>
|
||
<h1 class="font-serif-editorial text-4xl font-normal mt-1">Создать героя</h1>
|
||
<p class="text-sm meta-text mt-1">Все персонажи — вымышленные взрослые (18+).</p>
|
||
</div>
|
||
<div class="flex flex-wrap gap-2 text-xs">
|
||
<span class="px-3 py-1.5 rounded bg-[var(--accent-wine)] text-white font-medium">1 · Образ</span>
|
||
<span class="px-3 py-1.5 rounded surface-card">2 · Внешность</span>
|
||
<span class="px-3 py-1.5 rounded surface-card">3 · Характер</span>
|
||
<span class="px-3 py-1.5 rounded surface-card">4 · Голос и общение</span>
|
||
<span class="px-3 py-1.5 rounded surface-card">5 · Проверка</span>
|
||
</div>
|
||
<div class="surface-card p-6 max-w-xl space-y-4">
|
||
<div>
|
||
<label class="block text-xs meta-text mb-1">Имя героя</label>
|
||
<input type="text" value="Алекс" class="w-full px-3.5 py-2 rounded border hairline-border bg-[var(--bg-paper)] text-sm" />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs meta-text mb-1">Возраст (только 18+)</label>
|
||
<input type="text" value="32 года · Взрослый вымышленный герой" class="w-full px-3.5 py-2 rounded border hairline-border bg-[var(--bg-paper)] text-sm" />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs meta-text mb-1">Атмосфера и характер</label>
|
||
<textarea rows="3" class="w-full px-3.5 py-2 rounded border hairline-border bg-[var(--bg-paper)] text-sm">Внимательный собеседник с мягким юмором. Любит ночные прогулки и кинематограф.</textarea>
|
||
</div>
|
||
<button onclick="switchScreen('ai_chat')" class="btn-wine px-5 py-2.5 text-xs">Сохранить и начать разговор →</button>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="screen-personal" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-6">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text">ЛИЧНЫЙ АРХИВ</div>
|
||
<h1 class="font-serif-editorial text-4xl font-normal mt-1">Маленькие вещи, которые остаются.</h1>
|
||
<p class="text-sm meta-text mt-1">Сохранённые фрагменты из ваших диалогов и любимые строки из рассказов.</p>
|
||
</div>
|
||
<div class="surface-card p-6 space-y-3 max-w-2xl">
|
||
<div class="text-xs meta-text">Из рассказа «После полуночи»</div>
|
||
<blockquote class="font-serif-editorial italic text-2xl">
|
||
«С этими тёплыми свёртками они стали похожи на людей, возвращавшихся из одного дома.»
|
||
</blockquote>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 10: ПОДПИСКА · УСЛОВИЯ (Figma Frame 12:313554 · 690 ₽ / мес) -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-subscription" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-8 space-y-3">
|
||
<div class="text-xs uppercase tracking-[0.14em] wine-text font-semibold">ВИДЕОВЕРСИИ / ОТДЕЛЬНО ОТ ЧТЕНИЯ</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-5xl leading-[1.04] font-normal">
|
||
Ещё один способ<br />почувствовать историю.
|
||
</h1>
|
||
<p class="text-base meta-text max-w-2xl">
|
||
Читайте все истории бесплатно. Подписка открывает только записанные видеоадаптации — не AI-диалоги и не доступ к текстам.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="surface-card p-8 max-w-xl space-y-6">
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-xs uppercase tracking-wider wine-text font-semibold">ОДИН ПЛАН · БИБЛИОТЕКА ВИДЕО</span>
|
||
<span class="wine-badge">18+</span>
|
||
</div>
|
||
<div>
|
||
<div class="font-serif-editorial text-5xl font-semibold">690 ₽ / месяц</div>
|
||
<div class="text-xs meta-text mt-1">Продлевается автоматически · Отмена в любой момент в Настройках</div>
|
||
</div>
|
||
<ul class="space-y-2.5 text-sm">
|
||
<li>✓ Все доступные записанные видеоадаптации («После полуночи», «Кофе после дождя» и др.)</li>
|
||
<li>✓ Новые видеоверсии по мере выхода</li>
|
||
<li>✓ Полные тексты — всегда бесплатно и без подписки</li>
|
||
</ul>
|
||
<div class="pt-2 flex flex-wrap items-center gap-3">
|
||
<button onclick="setVideoAccess(true);openStoryReaderAndScrollVideo(0);" class="btn-wine px-6 py-3 text-sm">
|
||
Оформить подписку и открыть видео →
|
||
</button>
|
||
<button onclick="openStoryReader(0)" class="btn-outline-editorial px-4 py-3 text-xs">
|
||
← Вернуться к истории без оформления
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===================================================================== -->
|
||
<!-- SCREEN 11: ВХОД (12:315832) & НАСТРОЙКИ (12:316253) & СОСТОЯНИЯ -->
|
||
<!-- ===================================================================== -->
|
||
<section id="screen-login" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-6">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text">ВАШ АККАУНТ / 18+</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-5xl font-normal mt-1">Вернуться к своей странице.</h1>
|
||
<p class="text-sm meta-text mt-1">Войдите, чтобы проверить подписку и сохранить вашу библиотеку.</p>
|
||
</div>
|
||
<div class="surface-card p-7 max-w-md space-y-4">
|
||
<div>
|
||
<label class="block text-xs meta-text mb-1">Электронная почта</label>
|
||
<input type="email" value="anna@example.ru" class="w-full px-3.5 py-2 rounded border hairline-border bg-[var(--bg-paper)] text-sm" />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs meta-text mb-1">Пароль</label>
|
||
<input type="password" value="••••••••••••" class="w-full px-3.5 py-2 rounded border hairline-border bg-[var(--bg-paper)] text-sm" />
|
||
</div>
|
||
<label class="flex items-start gap-2 text-xs meta-text">
|
||
<input type="checkbox" checked class="mt-1" />
|
||
<span>Мне исполнилось 18 лет. Я согласна с условиями использования и политикой конфиденциальности.</span>
|
||
</label>
|
||
<div class="pt-2 flex gap-2">
|
||
<button onclick="setVideoAccess(true);openStoryReaderAndScrollVideo(0)" class="btn-wine flex-1 py-2.5 text-xs">Войти и вернуться к истории</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="screen-settings" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-6">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text">АККАУНТ И ВАШ КОМФОРТ</div>
|
||
<h1 class="font-serif-editorial text-4xl sm:text-5xl font-normal mt-1">Настроить свой ритм.</h1>
|
||
</div>
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-3xl">
|
||
<div class="surface-card p-6 space-y-4">
|
||
<h3 class="font-serif-editorial text-2xl font-medium">Чтение</h3>
|
||
<p class="text-xs meta-text">
|
||
Шрифт: Cormorant Garamond. Размер текста на компьютере — 20 px, на телефоне — 18 px. Межстрочный интервал — 32 / 29 px.
|
||
</p>
|
||
<div class="flex items-center gap-3">
|
||
<button onclick="changeFontSize(-2)" class="btn-outline-editorial px-3 py-1.5 text-xs">А−</button>
|
||
<span class="text-xs font-medium">20 px</span>
|
||
<button onclick="changeFontSize(2)" class="btn-outline-editorial px-3 py-1.5 text-xs">А+</button>
|
||
</div>
|
||
</div>
|
||
<div class="surface-card p-6 space-y-4">
|
||
<h3 class="font-serif-editorial text-2xl font-medium">Приватность и доступность</h3>
|
||
<label class="flex items-center gap-2 text-xs"><input type="checkbox" checked /> Сохранять позицию чтения (42%)</label>
|
||
<label class="flex items-center gap-2 text-xs"><input type="checkbox" checked /> Субтитры для видеоверсий</label>
|
||
<label class="flex items-center gap-2 text-xs"><input type="checkbox" onchange="toggleThemeNoir()" /> Вечерняя тема NOIR (#10121A)</label>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="screen-states" class="hidden space-y-8">
|
||
<div class="border-b hairline-border pb-6">
|
||
<div class="text-xs uppercase tracking-[0.14em] meta-text">ДОСКА СОСТОЯНИЙ И СПЕЦИФИКАЦИЯ FIGMA (12:317745 & 12:316744)</div>
|
||
<h1 class="font-serif-editorial text-4xl font-normal mt-1">Разные причины. Ясный следующий шаг.</h1>
|
||
</div>
|
||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 text-xs">
|
||
<div class="surface-card p-5 space-y-1.5">
|
||
<div class="wine-text font-semibold uppercase">01 / Палитра CHAPTER</div>
|
||
<p class="meta-text">Бумага <code>#F5F0E8</code> · Поверхность <code>#FFFDFA</code> · Текст <code>#24211D</code> · Мета <code>#686158</code> · Вино <code>#793C49</code></p>
|
||
</div>
|
||
<div class="surface-card p-5 space-y-1.5">
|
||
<div class="wine-text font-semibold uppercase">02 / Оформление · Успех</div>
|
||
<p class="meta-text">Подписка активна. Возврат к «После полуночи», в тот же блок видео. Позиция чтения 42% сохранена.</p>
|
||
</div>
|
||
<div class="surface-card p-5 space-y-1.5">
|
||
<div class="wine-text font-semibold uppercase">03 / Подписка истекла</div>
|
||
<p class="meta-text">Видео «После полуночи» закрыто. Рассказ остаётся бесплатным.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
</div>
|
||
|
||
<!-- Toast Notification -->
|
||
<div id="editorialToast" class="hidden fixed bottom-6 right-6 surface-card px-5 py-3 shadow-xl text-xs font-medium z-50">
|
||
🔖 Позиция чтения (42% · у моста) сохранена на вашей странице
|
||
</div>
|
||
|
||
<script>
|
||
const STORIES = [
|
||
{
|
||
id: 0,
|
||
genre: "Романтическая проза",
|
||
meta: "РОМАНТИЧЕСКАЯ ПРОЗА / 3 мин / 18+",
|
||
duration: "3 мин",
|
||
timeCat: "short",
|
||
mood: "night",
|
||
hasVideo: true,
|
||
videoDuration: "08:40",
|
||
title: "После полуночи",
|
||
characters: "Редакция «между.» · Вымышленные взрослые: Вера, 31 · Матвей, 34",
|
||
lead: "Опоздав на последний трамвай, двое решают не торопить утро. Рассказ о смелости остаться рядом.",
|
||
quote: "«Вера услышала, как за поворотом стих последний трамвай. Город словно перевернул страницу.»",
|
||
chapter: "I. После полуночи",
|
||
paragraphs: [
|
||
"Вера услышала, как за поворотом стих последний трамвай. Город словно перевернул страницу. На остановке остались мокрая афиша, жёлтый свет фонаря и человек, который тоже не успел. Он посмотрел на часы, потом на пустые рельсы и почему-то улыбнулся.",
|
||
"— Кажется, нас освободили от расписания, — сказал он. Вера узнала Матвея не сразу. В книжном он стоял за колонной и слушал, как она читает чужие стихи. Потом помог собрать стулья, но имени так и не спросил. Теперь их знакомство продолжилось без всякого повода.",
|
||
"Дождь закончился, оставив на мостовой маленькие озёра. Вера сказала, что живёт за рекой. Матвею было в другую сторону. Они сверились с картой и спрятали телефоны: до моста путь у них всё-таки был общий. Вера подтянула воротник пальто, и они пошли.",
|
||
"Сначала говорили о вечере. О поэте, который потерял очки, хотя держал их в руке. О женщине в первом ряду, записывавшей не стихи, а, вероятно, список покупок. Потом разговор стал тише. Матвей признался, что давно собирается сменить работу. Вера — что второй месяц не может распаковать последнюю коробку после переезда.",
|
||
"— Там что-нибудь важное? — спросил он. — Только вещи, которым пока нет места. Она удивилась собственному ответу. Обычно о переезде хотелось говорить как о решённой задаче. Матвей не предложил ни полок, ни полезного номера. Он просто кивнул, словно хорошо знал такие коробки.",
|
||
"У моста ещё работала пекарня. Они купили один большой хлеб, потому что маленькие уже закончились. Продавщица разрезала его пополам и завернула в два бумажных пакета. С этими тёплыми свёртками они стали похожи на людей, возвращавшихся из одного дома.",
|
||
"Вера заметила это сходство и рассмеялась. Матвей спросил почему. Она рассказала. Теперь засмеялся и он — не над ней, а рядом с ней. Эта разница вдруг показалась важнее всех слов, сказанных за вечер. Внизу под мостом медленно плыл отражённый свет окон.",
|
||
"На другой стороне реки им нужно было расстаться. Они остановились у перил. Вера могла назвать улицу, пожелать спокойной ночи и унести этот вечер как красивую случайность. Такие случайности ничего не требовали и потому долго казались ей безопасными.",
|
||
"— Я завтра буду разбирать коробку, — сказала она. — А после? В вопросе не было ни уверенности, ни обещания. Он оставлял ей место для любого ответа. Вера посмотрела на бумажный пакет, сквозь который ещё чувствовалось тепло, и поняла, что впервые за долгое время не хочет заранее придумывать конец.",
|
||
"— После можно выпить чаю. У меня пока только две чашки. — Значит, я не приведу весь книжный клуб. Они обменялись номерами. Матвей не стал сразу звонить для проверки, и это тоже ей понравилось. Вера сама написала адрес, добавив: «После семи».",
|
||
"Домой она шла медленно. У двери поставила пакет на подоконник и долго искала ключи, хотя они были в наружном кармане. В квартире пахло краской и холодным деревом. Последняя коробка стояла у стены. Вера открыла её, достала настольную лампу и поставила на кухне.",
|
||
"Под светом нашлось место и чашкам, и половине хлеба. Телефон коротко загорелся: «До завтра, Вера». Она ответила: «До завтра». За окном уже начинался новый день, но впервые ей не хотелось его торопить. Она выключила верхний свет. Лампу оставила гореть."
|
||
]
|
||
},
|
||
{
|
||
id: 1,
|
||
genre: "Современная романтика",
|
||
meta: "СОВРЕМЕННАЯ РОМАНТИКА / 6 мин / 18+",
|
||
duration: "6 мин",
|
||
timeCat: "long",
|
||
mood: "warm",
|
||
hasVideo: true,
|
||
videoDuration: "11:20",
|
||
title: "Кофе после дождя",
|
||
characters: "Редакция «между.» · Вымышленные взрослые: Лида, 29 · Денис, 33",
|
||
lead: "В маленьком кафе Лида и Денис учатся говорить о будущем, не загадывая его друг за друга.",
|
||
quote: "«Кофе принесли в разных чашках. Лида решила, что это хороший знак: здесь не требовали совпадать.»",
|
||
chapter: "I. Кофе после дождя",
|
||
paragraphs: [
|
||
"Кофе принесли в разных чашках — одну широкую, с тонким золотым ободком, другую высокую, из тяжёлого тёплого фаянса. Лида решила, что это хороший знак: здесь не требовали совпадать.",
|
||
"За витриной шумел октябрьский ливень. Денис снял промокший шарф и положил его на спинку соседнего стула. Они знали друг друга три недели, но до сегодняшнего дня всегда встречались на ходу — между выставками, звонками и чужими компаниями.",
|
||
"— Знаешь, чего я боюсь в таких вечерах? — спросила Лида, согревая ладони о чашку. — Что кто-нибудь обязательно начнёт спрашивать про планы на пять лет вперёд.",
|
||
"— Тогда давай договоримся, — улыбнулся Денис. — Наше будущее сегодня заканчивается ровно в полночь. А дальше посмотрим, захочется ли его продлить.",
|
||
"Это сняло неловкость быстрее любого комплимента. Когда через час официант зажёг на столиках маленькие свечи, разговор уже шёл о том, какие окна в городе кажутся самыми уютными и почему в дождь так легко признаваться в желаниях."
|
||
]
|
||
},
|
||
{
|
||
id: 2,
|
||
genre: "Проза о выборе",
|
||
meta: "ПРОЗА О ВЫБОРЕ / 8 мин / 18+",
|
||
duration: "8 мин",
|
||
timeCat: "long",
|
||
mood: "night",
|
||
hasVideo: true,
|
||
videoDuration: "14:10",
|
||
title: "Вечер в незнакомом городе",
|
||
characters: "Редакция «между.» · Вымышленные взрослые: Ася, 32 · Илья, 35 · Роман, 36",
|
||
lead: "Три старых друга встречаются на один вечер. У каждого — свой маршрут, но одна общая история.",
|
||
quote: "«Они встретились у гостиницы, которую никто из них не выбрал бы для себя. И потому всем было легко.»",
|
||
chapter: "I. Вечер в незнакомом городе",
|
||
paragraphs: [
|
||
"Они встретились у гостиницы, которую никто из них не выбрал бы для себя. И потому всем было легко. Чужой вокзал, влажный воздух северного города и три часа до ночного поезда создавали редкое чувство невесомости.",
|
||
"Ася смотрела, как Илья и Роман спорят о карте старого центра, и ловила себя на мысли, что за пять лет разлуки исчезла вся прежняя осторожность. Осталось только острое, почти осязаемое притяжение людей, которые слишком хорошо помнят друг друга."
|
||
]
|
||
},
|
||
{
|
||
id: 3,
|
||
genre: "Эпистолярная проза",
|
||
meta: "ЭПИСТОЛЯРНАЯ ПРОЗА / 4 мин / 18+",
|
||
duration: "4 мин",
|
||
timeCat: "short",
|
||
mood: "warm",
|
||
hasVideo: false,
|
||
videoDuration: "",
|
||
title: "Письмо, которое всё изменило",
|
||
characters: "Редакция «между.» · Вымышленные взрослые: Соня, 30 · Андрей, 34",
|
||
lead: "Соня возвращает непрочитанное письмо. Андрей предлагает начать не с объяснений, а с прогулки.",
|
||
quote: "«Конверт пролежал в ящике стола почти год. Теперь Соня держала его так, словно это был билет в город, где она ещё не бывала.»",
|
||
chapter: "I. Письмо",
|
||
paragraphs: [
|
||
"Конверт пролежал в ящике стола почти год. Теперь Соня держала его так, словно это был билет в город, где она ещё не бывала. Бумага сохранила лёгкий запах табака и кедра.",
|
||
"Когда Андрей открыл дверь, он посмотрел на запечатанный конверт в её руке и не стал спрашивать, почему она не вскрыла его прошлой зимой. Он просто взял пальто с вешалки: «Пойдём к набережной. Прочитаешь вслух, если захочешь»."
|
||
]
|
||
}
|
||
];
|
||
|
||
let isSubscribed = false;
|
||
let isVideoPlaying = false;
|
||
let currentFontSize = 20;
|
||
|
||
const SCREEN_TITLES = {
|
||
home: "Главная",
|
||
catalog: "Истории",
|
||
reader: "Истории / Чтение",
|
||
videos: "Видео по историям",
|
||
continue: "Продолжить чтение",
|
||
favorites: "Избранное",
|
||
ai_heroes: "Другой формат · AI герои",
|
||
ai_chat: "Диалоги / Лев · моя версия",
|
||
my_ai: "Мои AI",
|
||
create_ai: "Создать героя",
|
||
personal: "Личное",
|
||
subscription: "Подписка",
|
||
login: "Вход · 18+",
|
||
settings: "Настройки",
|
||
states: "Состояния интерфейса"
|
||
};
|
||
|
||
function switchScreen(screenId) {
|
||
Object.keys(SCREEN_TITLES).forEach(k => {
|
||
const sec = document.getElementById('screen-' + k);
|
||
if (sec) sec.classList.add('hidden');
|
||
const nav = document.getElementById('nav-' + k);
|
||
if (nav) nav.classList.remove('active');
|
||
});
|
||
const target = document.getElementById('screen-' + screenId);
|
||
if (target) target.classList.remove('hidden');
|
||
const activeNav = document.getElementById('nav-' + (screenId === 'reader' ? 'catalog' : screenId));
|
||
if (activeNav) activeNav.classList.add('active');
|
||
document.getElementById('topBreadcrumb').innerText = SCREEN_TITLES[screenId] || "Главная";
|
||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||
}
|
||
|
||
function renderCatalog(list) {
|
||
const grid = document.getElementById('catalogGrid');
|
||
document.getElementById('catalogCountLabel').innerText = `${list.length} истории · Редакционный порядок`;
|
||
grid.innerHTML = list.map(s => `
|
||
<article class="surface-card p-7 flex flex-col justify-between space-y-5">
|
||
<div class="space-y-3">
|
||
<div class="text-[11px] uppercase tracking-[0.12em] meta-text">${s.genre.toUpperCase()} · ${s.duration}</div>
|
||
<h3 class="font-serif-editorial text-3xl font-normal cursor-pointer hover:opacity-80" onclick="openStoryReader(${s.id})">${s.title}</h3>
|
||
<p class="text-sm meta-text leading-relaxed">${s.lead}</p>
|
||
<blockquote class="font-serif-editorial italic text-lg pt-3 border-t hairline-border">${s.quote}</blockquote>
|
||
</div>
|
||
<div class="pt-4 border-t hairline-border flex items-center justify-between">
|
||
${s.hasVideo
|
||
? `<span class="wine-badge">🎬 Есть видео · по подписке (${s.videoDuration})</span>`
|
||
: `<span class="text-xs meta-text px-2.5 py-0.5 rounded border hairline-border">Пока только текст</span>`
|
||
}
|
||
<button onclick="openStoryReader(${s.id})" class="text-xs font-medium wine-text hover:underline">Читать историю →</button>
|
||
</div>
|
||
</article>
|
||
`).join('');
|
||
}
|
||
|
||
function filterCatalog() {
|
||
const g = document.getElementById('filterGenre').value;
|
||
const m = document.getElementById('filterMood').value;
|
||
const t = document.getElementById('filterTime').value;
|
||
const v = document.getElementById('filterVideo').value;
|
||
const filtered = STORIES.filter(s => {
|
||
if (g !== 'all' && s.genre !== g) return false;
|
||
if (m !== 'all' && s.mood !== m) return false;
|
||
if (t !== 'all' && s.timeCat !== t) return false;
|
||
if (v === 'yes' && !s.hasVideo) return false;
|
||
if (v === 'text' && s.hasVideo) return false;
|
||
return true;
|
||
});
|
||
renderCatalog(filtered);
|
||
}
|
||
|
||
function openStoryReader(storyIdx) {
|
||
const s = STORIES[storyIdx] || STORIES[0];
|
||
document.getElementById('readerMetaCategory').innerText = s.meta;
|
||
document.getElementById('readerTitle').innerText = s.title;
|
||
document.getElementById('readerLead').innerText = s.lead;
|
||
document.getElementById('readerCharacters').innerText = s.characters;
|
||
document.getElementById('readerChapterHeading').innerText = s.chapter;
|
||
document.getElementById('readerBodyParagraphs').innerHTML = s.paragraphs.map(p => `<p>${p}</p>`).join('');
|
||
document.getElementById('lockedStoryTitle').innerText = s.title;
|
||
document.getElementById('playerStoryTitle').innerText = s.title + " · Экранизация";
|
||
document.getElementById('lockedDuration').innerText = s.videoDuration || "08:40";
|
||
document.getElementById('lockedDurationSub').innerText = s.videoDuration || "08:40";
|
||
document.getElementById('playerDurationBadge').innerText = "02:16 / " + (s.videoDuration || "08:40");
|
||
switchScreen('reader');
|
||
}
|
||
|
||
function openStoryReaderAndScrollVideo(storyIdx) {
|
||
openStoryReader(storyIdx);
|
||
setTimeout(() => {
|
||
const el = document.getElementById('endOfStoryVideoBlock');
|
||
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
}, 150);
|
||
}
|
||
|
||
function setVideoAccess(unlocked) {
|
||
isSubscribed = unlocked;
|
||
const lockedCard = document.getElementById('videoLockedCard');
|
||
const unlockedCard = document.getElementById('videoUnlockedCard');
|
||
const bLock = document.getElementById('btnLockedState');
|
||
const bUnlock = document.getElementById('btnUnlockedState');
|
||
const mobSub = document.getElementById('mobSubBadge');
|
||
|
||
if (unlocked) {
|
||
lockedCard.classList.add('hidden');
|
||
unlockedCard.classList.remove('hidden');
|
||
bUnlock.className = "px-2 py-0.5 rounded text-[11px] font-medium bg-[var(--accent-wine)] text-white";
|
||
bLock.className = "px-2 py-0.5 rounded text-[11px] font-medium meta-text hover:text-[var(--text-ink)]";
|
||
if (mobSub) mobSub.innerText = "Подписка: активна";
|
||
} else {
|
||
lockedCard.classList.remove('hidden');
|
||
unlockedCard.classList.add('hidden');
|
||
bLock.className = "px-2 py-0.5 rounded text-[11px] font-medium bg-[var(--accent-wine)] text-white";
|
||
bUnlock.className = "px-2 py-0.5 rounded text-[11px] font-medium meta-text hover:text-[var(--text-ink)]";
|
||
if (mobSub) mobSub.innerText = "Подписка: выкл";
|
||
}
|
||
}
|
||
|
||
function toggleSubscriptionState() {
|
||
setVideoAccess(!isSubscribed);
|
||
}
|
||
|
||
function toggleVideoPlayback() {
|
||
isVideoPlaying = !isVideoPlaying;
|
||
document.getElementById('playPauseCircle').innerText = isVideoPlaying ? "⏸" : "▶";
|
||
document.getElementById('playPauseTextBtn').innerText = isVideoPlaying ? "⏸ Пауза" : "▶ Воспроизвести";
|
||
document.getElementById('videoStateNote').innerText = isVideoPlaying
|
||
? "Идёт воспроизведение экранизации · Звук включён"
|
||
: "На паузе · Позиция чтения 42% сохранена";
|
||
document.getElementById('videoProgressBar').style.width = isVideoPlaying ? "64%" : "28%";
|
||
}
|
||
|
||
function scrubVideo(e) {
|
||
const rect = e.currentTarget.getBoundingClientRect();
|
||
const pct = Math.max(5, Math.min(98, Math.round(((e.clientX - rect.left) / rect.width) * 100)));
|
||
document.getElementById('videoProgressBar').style.width = pct + "%";
|
||
}
|
||
|
||
function changeFontSize(delta) {
|
||
currentFontSize = Math.max(16, Math.min(26, currentFontSize + delta));
|
||
document.documentElement.style.setProperty('--reading-size', currentFontSize + 'px');
|
||
document.documentElement.style.setProperty('--reading-lh', Math.round(currentFontSize * 1.6) + 'px');
|
||
const ind = document.getElementById('fontSizeIndicator');
|
||
if (ind) ind.innerText = currentFontSize + ' px';
|
||
}
|
||
|
||
function toggleBookmarkToast() {
|
||
const t = document.getElementById('editorialToast');
|
||
t.classList.remove('hidden');
|
||
setTimeout(() => t.classList.add('hidden'), 3000);
|
||
}
|
||
|
||
function toggleAiVideoMode(showVideo) {
|
||
const box = document.getElementById('aiVideoCallBox');
|
||
const bText = document.getElementById('chatModeTextBtn');
|
||
const bVid = document.getElementById('chatModeVideoBtn');
|
||
if (showVideo) {
|
||
box.classList.remove('hidden');
|
||
bVid.className = "btn-wine px-3.5 py-1.5 text-xs";
|
||
bText.className = "btn-outline-editorial px-3.5 py-1.5 text-xs";
|
||
} else {
|
||
box.classList.add('hidden');
|
||
bText.className = "btn-wine px-3.5 py-1.5 text-xs";
|
||
bVid.className = "btn-outline-editorial px-3.5 py-1.5 text-xs";
|
||
}
|
||
}
|
||
|
||
function sendAiChatMessage(e) {
|
||
e.preventDefault();
|
||
const inp = document.getElementById('aiChatInput');
|
||
const val = inp.value.trim();
|
||
if (!val) return;
|
||
const list = document.getElementById('chatMessagesList');
|
||
list.innerHTML += `
|
||
<div class="p-4 rounded-md bg-[var(--accent-wine-soft)] ml-auto max-w-lg space-y-1">
|
||
<div class="text-[11px] wine-text">Сейчас · Вы · Доставлено ✓✓</div>
|
||
<p class="text-sm">${val}</p>
|
||
</div>
|
||
<div class="subtle-box p-4 max-w-lg space-y-1">
|
||
<div class="text-[11px] meta-text">Сейчас · Лев · AI</div>
|
||
<p class="text-sm">Мне нравится, как ты это замечаешь. Давай возьмём ещё по чашке кофе и никуда не будем спешить.</p>
|
||
</div>
|
||
`;
|
||
inp.value = '';
|
||
}
|
||
|
||
function toggleThemeNoir() {
|
||
document.body.classList.toggle('theme-noir');
|
||
const isNoir = document.body.classList.contains('theme-noir');
|
||
document.getElementById('themeSwitchBtn').innerText = isNoir ? "NOIR (#10121A)" : "CHAPTER (Бумага)";
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
renderCatalog(STORIES);
|
||
openStoryReader(0);
|
||
switchScreen('home');
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |