Fix slide snap + presentation keyboard nav

- html/body height 100%, html overflow-y scroll — proper snap container
- box-sizing border-box on sections (padding wasn't being included)
- 2px black border-top between slides — visual divider
- frame display block, body margin 0
- Keyboard: ArrowDown/PageDown/Space → next, ArrowUp/PageUp → prev,
  Home/End → first/last

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Telecom 2026-05-21 21:38:42 +05:00
parent fc8bab570e
commit 5c1ab55af0

View File

@ -106,13 +106,18 @@
}
}
html, body {
height: 100%;
}
html {
scroll-behavior: smooth;
font-size: clamp(18px, 1.6vw, 28px); /* масштабируется под экран — для проектора 24–28px */
font-size: clamp(18px, 1.6vw, 28px);
scroll-snap-type: y mandatory;
overflow-y: scroll;
scroll-padding-top: 0;
}
/* PRESENTATION MODE: каждая секция = ровно 1 экран, фиксация при скролле */
/* PRESENTATION MODE: каждая секция = ровно 1 экран */
.hero,
section.section,
.dark-section {
@ -124,7 +129,7 @@ section.section,
justify-content: center;
padding-top: 4vh;
padding-bottom: 4vh;
overflow-y: auto; /* если контент длиннее — скролл внутри слайда */
box-sizing: border-box;
}
/* Усиливаем типографику для большого экрана */
@ -184,9 +189,18 @@ body {
font-family: 'Lora', Georgia, serif !important;
background: var(--page-bg);
padding: 0;
margin: 0;
overflow: visible;
}
.frame { gap: 0; min-height: 100dvh; }
.frame { gap: 0; min-height: 100dvh; display: block; }
/* Усиливаем визуальную границу между слайдами */
.hero, section.section, .dark-section {
border-top: 2px solid var(--text) !important;
position: relative;
}
.hero { border-top: none !important; }
/* Шрифты заголовков */
.hero-title, .section-title, .dark-title,
@ -3061,16 +3075,18 @@ const SCHEDULE = [
targets.forEach(el => io.observe(el));
})();
// Slide counter — показывает текущий слайд / всего
// Slide counter + keyboard nav (PageDown / Arrow / Space)
(function() {
const counter = document.getElementById('slide-counter');
if (!counter) return;
const slides = Array.from(document.querySelectorAll('.hero, section.section, .dark-section'));
const total = slides.length;
let current = 0;
const update = (idx) => {
counter.textContent = `— ${idx + 1} / ${total} —`;
current = idx;
if (counter) counter.textContent = `— ${idx + 1} / ${total} —`;
};
update(0);
const io = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting && e.intersectionRatio > 0.5) {
@ -3080,6 +3096,24 @@ const SCHEDULE = [
});
}, { threshold: [0.5, 0.6, 0.75] });
slides.forEach(s => io.observe(s));
const goTo = (idx) => {
idx = Math.max(0, Math.min(total - 1, idx));
slides[idx].scrollIntoView({ behavior: 'smooth', block: 'start' });
};
document.addEventListener('keydown', (e) => {
if (['INPUT', 'TEXTAREA'].includes(document.activeElement?.tagName)) return;
if (e.key === 'ArrowDown' || e.key === 'PageDown' || e.key === ' ') {
e.preventDefault(); goTo(current + 1);
} else if (e.key === 'ArrowUp' || e.key === 'PageUp') {
e.preventDefault(); goTo(current - 1);
} else if (e.key === 'Home') {
e.preventDefault(); goTo(0);
} else if (e.key === 'End') {
e.preventDefault(); goTo(total - 1);
}
});
})();
</script>
</body>