fix: hero CTAs invisible until scroll, seek animation skip, layout overhaul

- Remove data-reveal from hero h1/subtitle/mascot/cta-group/version-badge
  (critical above-fold content must never start hidden)
- Change IntersectionObserver rootMargin -150px to -30px, threshold 0.1 to 0.05
  (CTAs at ~530px were past the observer zone on laptops)
- Hero layout: align-items flex-start + padding-top 7.5rem for content at top
- Cards 62cqw to 70cqw, -3% offsets for dramatic overlap cascade
- Film animation: replace stick-figure walker with cinematic night scene
  (7 twinkling stars, glowing moon with drift, parallax mountains, firefly)
- Seek now restarts all film child animations via .demo-reset class toggle
  (was incorrectly resetting parent only — no visible jump)
- Add .demo-seek-sweep overlay + brightness flash during seek
- Video select: placeholder option ('Choose a video tab...') until story picks
- RATE 8 to 1 for realtime playback
- Version badge moved below download buttons
- All 15 locale files: add DEMO_SELECT_PLACEHOLDER key
This commit is contained in:
KoalaDev
2026-07-03 10:42:09 +02:00
parent e5a4032710
commit 573847486b
18 changed files with 219 additions and 95 deletions
+28 -3
View File
@@ -29,8 +29,8 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
}, {
rootMargin: '0px 0px -150px 0px',
threshold: 0.1
rootMargin: '0px 0px -30px 0px',
threshold: 0.05
});
revealElements.forEach(el => revealObserver.observe(el));
@@ -433,7 +433,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (!launcher || !chip || !cursor || !playBtn || !pauseBtn) return;
const EP_LEN = 2537; // fake 42:17 episode
const RATE = 8; // timelapse factor so the demo feels alive
const RATE = 1; // realtime: 1 wall-clock second = 1 video second
const START_T = 754; // 12:34
const tabs = {};
@@ -548,14 +548,35 @@ document.addEventListener('DOMContentLoaded', () => {
tabs[sourceKey].t = fraction * EP_LEN;
renderTab(tabs[sourceKey]);
showEvent('» ' + NAMES[sourceKey]);
// visible "cut" so the jump reads as a real seek, not a silent update
flashSeek(tabs[sourceKey].root);
setTimeout(() => {
tabs[peerKey].t = tabs[sourceKey].t;
renderTab(tabs[peerKey]);
flashSeek(tabs[peerKey].root);
pulse();
broadcasting = false;
}, 90);
};
// Restart the film animations mid-stride + trigger the sweep overlay
let seekFlashTimers = [];
const flashSeek = (root) => {
if (!root) return;
root.classList.remove('demo-seeking');
// Restart every animated layer from frame zero so the jump is visible
const film = root.querySelector('.demo-film');
if (film) {
film.classList.add('demo-reset');
void film.offsetWidth; // force reflow so the browser commits the reset
film.classList.remove('demo-reset');
}
void root.offsetWidth;
root.classList.add('demo-seeking');
const t = setTimeout(() => root.classList.remove('demo-seeking'), 360);
seekFlashTimers.push(t);
};
const setPopupOpen = (open) => {
scene.classList.toggle('popup-open', open);
launcher.setAttribute('aria-expanded', open ? 'true' : 'false');
@@ -651,6 +672,10 @@ document.addEventListener('DOMContentLoaded', () => {
const flashSelect = () => {
if (!videoSelect) return;
// Actually pick the Stranger Things tab so the placeholder reads as chosen
if (videoSelect.options.length > 1) {
videoSelect.selectedIndex = 1;
}
videoSelect.classList.remove('demo-attn');
void videoSelect.offsetWidth;
videoSelect.classList.add('demo-attn');
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Raum erstellen",
"DEMO_JOINED": "Raum beigetreten",
"DEMO_TAB_SELECTED": "Tab ausgewählt",
"DEMO_SELECT_PLACEHOLDER": "Video-Tab wählen…",
"ADD_TO_CHROME": "Zu Chrome hinzufügen",
"ADD_TO_FIREFOX": "Zu Firefox hinzufügen",
"COMPAT_HEADING": "Funktioniert auf deinen Lieblingsplattformen",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Create Room",
"DEMO_JOINED": "Room joined",
"DEMO_TAB_SELECTED": "Tab selected",
"DEMO_SELECT_PLACEHOLDER": "Choose a video tab…",
"ADD_TO_CHROME": "Add to Chrome",
"ADD_TO_FIREFOX": "Add to Firefox",
"COMPAT_HEADING": "Works on your favorite platforms",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Crear sala",
"DEMO_JOINED": "Conectado a la sala",
"DEMO_TAB_SELECTED": "Pestaña seleccionada",
"DEMO_SELECT_PLACEHOLDER": "Elige una pestaña de video…",
"ADD_TO_CHROME": "Añadir a Chrome",
"ADD_TO_FIREFOX": "Añadir a Firefox",
"COMPAT_HEADING": "Funciona en tus plataformas favoritas",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Créer un salon",
"DEMO_JOINED": "Salon rejoint",
"DEMO_TAB_SELECTED": "Onglet sélectionné",
"DEMO_SELECT_PLACEHOLDER": "Choisir un onglet vidéo…",
"ADD_TO_CHROME": "Ajouter à Chrome",
"ADD_TO_FIREFOX": "Ajouter à Firefox",
"COMPAT_HEADING": "Fonctionne sur vos plateformes préférées",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Crea stanza",
"DEMO_JOINED": "Entrato nella stanza",
"DEMO_TAB_SELECTED": "Scheda selezionata",
"DEMO_SELECT_PLACEHOLDER": "Scegli una scheda video…",
"ADD_TO_CHROME": "Aggiungi a Chrome",
"ADD_TO_FIREFOX": "Aggiungi a Firefox",
"COMPAT_HEADING": "Compatibile con le tue piattaforme preferite",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "ルームを作成",
"DEMO_JOINED": "ルームに参加",
"DEMO_TAB_SELECTED": "タブを選択済み",
"DEMO_SELECT_PLACEHOLDER": "動画タブを選ぶ…",
"ADD_TO_CHROME": "Chromeに追加",
"ADD_TO_FIREFOX": "Firefoxに追加",
"COMPAT_HEADING": "お気に入りのプラットフォームで動作",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "방 만들기",
"DEMO_JOINED": "방 참여됨",
"DEMO_TAB_SELECTED": "탭 선택됨",
"DEMO_SELECT_PLACEHOLDER": "동영상 탭 선택…",
"ADD_TO_CHROME": "Chrome에 추가",
"ADD_TO_FIREFOX": "Firefox에 추가",
"COMPAT_HEADING": "가장 좋아하는 플랫폼에서 작동합니다",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Kamer aanmaken",
"DEMO_JOINED": "In de kamer",
"DEMO_TAB_SELECTED": "Tabblad geselecteerd",
"DEMO_SELECT_PLACEHOLDER": "Kies een videotabblad…",
"ADD_TO_CHROME": "Toevoegen aan Chrome",
"ADD_TO_FIREFOX": "Toevoegen aan Firefox",
"COMPAT_HEADING": "Werkt op uw favoriete platforms",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Utwórz pokój",
"DEMO_JOINED": "Dołączono do pokoju",
"DEMO_TAB_SELECTED": "Karta wybrana",
"DEMO_SELECT_PLACEHOLDER": "Wybierz kartę wideo…",
"ADD_TO_CHROME": "Dodaj do Chrome",
"ADD_TO_FIREFOX": "Dodaj do Firefox",
"COMPAT_HEADING": "Działa na Twoich ulubionych platformach",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Criar sala",
"DEMO_JOINED": "Entrou na sala",
"DEMO_TAB_SELECTED": "Aba selecionada",
"DEMO_SELECT_PLACEHOLDER": "Escolha uma aba de vídeo…",
"ADD_TO_CHROME": "Adicionar ao Chrome",
"ADD_TO_FIREFOX": "Adicionar ao Firefox",
"COMPAT_HEADING": "Funciona nas suas plataformas favoritas",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Criar sala",
"DEMO_JOINED": "Entrou na sala",
"DEMO_TAB_SELECTED": "Separador selecionado",
"DEMO_SELECT_PLACEHOLDER": "Escolha um separador de vídeo…",
"ADD_TO_CHROME": "Adicionar ao Chrome",
"ADD_TO_FIREFOX": "Adicionar ao Firefox",
"COMPAT_HEADING": "Funciona nas suas plataformas favoritas",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Создать комнату",
"DEMO_JOINED": "В комнате",
"DEMO_TAB_SELECTED": "Вкладка выбрана",
"DEMO_SELECT_PLACEHOLDER": "Выберите вкладку с видео…",
"ADD_TO_CHROME": "Установить в Chrome",
"ADD_TO_FIREFOX": "Установить в Firefox",
"COMPAT_HEADING": "Работает на ваших любимых платформах",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Oda oluştur",
"DEMO_JOINED": "Odaya katıldı",
"DEMO_TAB_SELECTED": "Sekme seçildi",
"DEMO_SELECT_PLACEHOLDER": "Bir video sekmesi seçin…",
"ADD_TO_CHROME": "Chrome'a Ekle",
"ADD_TO_FIREFOX": "Firefox'a Ekle",
"COMPAT_HEADING": "En sevdiğiniz platformlarda çalışır",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "Створити кімнату",
"DEMO_JOINED": "У кімнаті",
"DEMO_TAB_SELECTED": "Вкладку вибрано",
"DEMO_SELECT_PLACEHOLDER": "Оберіть вкладку з відео…",
"ADD_TO_CHROME": "Додати до Chrome",
"ADD_TO_FIREFOX": "Додати до Firefox",
"COMPAT_HEADING": "Працює на ваших улюблених платформах",
+1
View File
@@ -23,6 +23,7 @@
"DEMO_CREATE_ROOM": "创建房间",
"DEMO_JOINED": "已加入房间",
"DEMO_TAB_SELECTED": "已选择标签页",
"DEMO_SELECT_PLACEHOLDER": "选择视频标签页…",
"ADD_TO_CHROME": "添加到Chrome",
"ADD_TO_FIREFOX": "添加到Firefox",
"COMPAT_HEADING": "适用于您最喜欢的平台",
+135 -58
View File
@@ -218,16 +218,16 @@ nav {
.hero {
min-height: 100vh;
display: flex;
align-items: center;
padding-top: 8rem;
padding-bottom: 4rem;
align-items: flex-start;
padding-top: 7.5rem;
padding-bottom: 3rem;
}
.hero-grid {
display: grid;
grid-template-columns: 1.2fr 1fr;
align-items: center;
gap: 4rem;
align-items: start;
gap: 3rem;
text-align: left;
width: 100%;
}
@@ -236,7 +236,7 @@ nav {
font-size: 4.5rem;
font-weight: 800;
line-height: 1.1;
margin-bottom: 1.5rem;
margin-bottom: 1.4rem;
padding-bottom: 0.1em;
background: linear-gradient(to bottom, #fff 40%, #6366f1);
-webkit-background-clip: text;
@@ -251,7 +251,7 @@ nav {
.hero-text p, .hero-subtitle {
font-size: 1.25rem;
color: var(--text-muted);
margin-bottom: 2.5rem;
margin-bottom: 1.9rem;
max-width: 600px;
font-weight: 400;
line-height: 1.6;
@@ -343,6 +343,11 @@ nav {
transition: transform 0.2s, box-shadow 0.2s, background 0.2s;
}
.version-badge-below {
margin-bottom: 0;
margin-top: 1.5rem;
}
.version-badge:hover {
background: rgba(99, 102, 241, 0.2);
box-shadow: 0 0 16px rgba(99, 102, 241, 0.3);
@@ -2977,13 +2982,13 @@ header[id] {
.hero-demo-scene {
position: relative;
width: 100%;
height: 370px;
height: calc(63cqw + 84px);
height: 390px;
height: calc(66cqw + 78px);
transition: height 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.hero-demo-scene.popup-open {
height: 590px;
height: 600px;
}
/* While initializing, suppress all transitions so the popup can start closed
@@ -3048,8 +3053,8 @@ header[id] {
/* Video tab cards: a clean window cascade — the right one is in front */
.demo-tab-card {
position: absolute;
width: 274px;
width: 62cqw;
width: 310px;
width: 70cqw;
background: #131c31;
border: 1px solid rgba(255, 255, 255, 0.09);
border-radius: 14px;
@@ -3068,8 +3073,8 @@ header[id] {
/* Card A = the foreground window at the top right ("your" browser,
hosts the extension icon in its toolbar) */
.demo-tab-a {
top: 30px;
right: 0;
top: 22px;
right: -3%;
transform: rotate(1.2deg);
transform-origin: top right;
z-index: 3;
@@ -3077,21 +3082,21 @@ header[id] {
/* Card B = the friend's window, lower left, tucked behind */
.demo-tab-b {
top: 168px;
top: calc(28cqw + 44px);
left: 0;
transform: rotate(-1.5deg);
top: 142px;
top: calc(20cqw + 40px);
left: -3%;
transform: rotate(-1.6deg);
transform-origin: top left;
z-index: 2;
}
/* When the popup slides in from the right edge, the tabs step aside */
.hero-demo-scene.popup-open .demo-tab-a {
transform: rotate(1deg) translate(-55%, 2%) scale(0.9);
transform: rotate(1deg) translate(-48%, 2%) scale(0.88);
}
.hero-demo-scene.popup-open .demo-tab-b {
transform: rotate(-1.5deg) scale(0.95);
transform: rotate(-1.6deg) scale(0.94);
}
.demo-tab-titlebar {
@@ -3533,62 +3538,134 @@ header[id] {
height: 100%;
}
.film-limb {
stroke: #e2e8f0;
stroke-width: 2;
stroke-linecap: round;
/* Cinematic "movie" scene: a moonlit landscape with parallax mountains,
twinkling stars, a glowing moon, and a drifting firefly. Every layer
freezes when playback pauses — on both tabs at once. */
.demo-film {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.film-walker {
transform: translate(-15px, 74px);
animation: filmWalk 10s linear infinite;
}
@keyframes filmWalk {
to { transform: translate(175px, 74px); }
}
.film-bob {
animation: filmBob 0.5s ease-in-out infinite alternate;
}
@keyframes filmBob {
to { transform: translateY(-1.8px); }
}
.film-swing-1,
.film-swing-2 {
/* Stars: staggered twinkle so the sky feels alive */
.film-star {
transform-box: fill-box;
transform-origin: top center;
transform-origin: center;
animation: filmTwinkle 2.8s ease-in-out infinite;
}
.film-star:nth-child(2) { animation-duration: 3.4s; animation-delay: 0.5s; }
.film-star:nth-child(3) { animation-duration: 2.4s; animation-delay: 1.1s; }
.film-star:nth-child(4) { animation-duration: 3.6s; animation-delay: 0.3s; }
.film-star:nth-child(5) { animation-duration: 2.6s; animation-delay: 1.6s; }
.film-star:nth-child(6) { animation-duration: 3.2s; animation-delay: 0.8s; }
.film-star:nth-child(7) { animation-duration: 2.2s; animation-delay: 1.3s; }
@keyframes filmTwinkle {
0%, 100% { opacity: 0.25; transform: scale(0.85); }
50% { opacity: 1; transform: scale(1.15); }
}
.film-swing-1 { animation: filmSwing 0.5s ease-in-out infinite alternate; }
.film-swing-2 { animation: filmSwing 0.5s ease-in-out infinite alternate-reverse; }
@keyframes filmSwing {
from { transform: rotate(30deg); }
to { transform: rotate(-30deg); }
/* Moon: gentle glow pulse + slow arc drift */
.film-moon {
transform-box: fill-box;
transform-origin: center;
animation: filmMoon 6s ease-in-out infinite alternate;
}
.film-ball-x {
animation: filmBallX 6.5s linear infinite;
@keyframes filmMoon {
from { transform: translate(0, 0); filter: drop-shadow(0 0 4px rgba(241,245,249,0.5)); }
to { transform: translate(-6px, 3px); filter: drop-shadow(0 0 10px rgba(241,245,249,0.95)); }
}
@keyframes filmBallX {
to { transform: translateX(175px); }
/* Mountain layers: subtle parallax sway (oscillates so it never runs off-edge) */
.film-mtn-back {
transform-box: fill-box;
animation: filmMtnBack 24s ease-in-out infinite alternate;
}
.film-ball {
animation: filmBallY 0.55s cubic-bezier(0.4, 0, 0.6, 1) infinite alternate;
@keyframes filmMtnBack {
from { transform: translateX(-3px); }
to { transform: translateX(3px); }
}
@keyframes filmBallY {
to { transform: translateY(-16px); }
.film-mtn-front {
transform-box: fill-box;
animation: filmMtnFront 16s ease-in-out infinite alternate;
}
@keyframes filmMtnFront {
from { transform: translateX(-5px); }
to { transform: translateX(5px); }
}
/* Firefly: warm dot floating across the foreground */
.film-firefly {
animation: filmFireflyX 11s linear infinite;
}
@keyframes filmFireflyX {
from { transform: translate(15px, 0); }
to { transform: translate(145px, 0); }
}
.film-firefly-light {
transform-box: fill-box;
transform-origin: center;
animation: filmFireflyBob 2.6s ease-in-out infinite alternate;
filter: drop-shadow(0 0 5px rgba(253, 224, 71, 0.95));
}
@keyframes filmFireflyBob {
from { transform: translateY(-4px) scale(0.9); opacity: 0.7; }
to { transform: translateY(4px) scale(1.15); opacity: 1; }
}
.demo-film * { animation-play-state: paused; }
.demo-tab-card.playing .demo-film * { animation-play-state: running; }
/* Seek-reset: scrubbing restarts every film layer from frame zero so the
jump reads as a real cut, not a silent time update. */
.demo-film.demo-reset * {
animation: none !important;
}
/* Seek-break: scrubbing the timeline visibly glitches both videos so the
jump reads as a real cut instead of an invisible time update. A scanline
sweep + brightness pop, and the film animations restart mid-stride. */
.demo-video-art { transition: filter 0.12s ease-out; }
.demo-tab-card.demo-seeking .demo-video-art {
animation-play-state: paused;
filter: brightness(1.9) saturate(1.4) blur(0.6px);
}
.demo-tab-card .demo-seek-sweep {
position: absolute;
inset: 0;
z-index: 4;
pointer-events: none;
opacity: 0;
background: linear-gradient(90deg,
transparent 0%,
rgba(129, 140, 248, 0.35) 20%,
rgba(255, 255, 255, 0.55) 50%,
rgba(129, 140, 248, 0.35) 80%,
transparent 100%);
mix-blend-mode: screen;
transform: translateX(-100%);
}
.demo-tab-card.demo-seeking .demo-seek-sweep {
animation: demoSeekSweep 0.34s ease-out;
}
@keyframes demoSeekSweep {
0% { opacity: 0; transform: translateX(-100%); }
20% { opacity: 1; }
100% { opacity: 0; transform: translateX(100%); }
}
/* The sync chip only appears once the room is connected (story progression) */
.demo-sync-chip {
opacity: 0;
+41 -34
View File
@@ -276,16 +276,12 @@
<header class="hero" id="main-content">
<div class="container hero-grid">
<div class="hero-text">
<a href="https://github.com/Shik3i/KoalaSync/blob/main/docs/CHANGELOG.md" target="_blank" rel="noopener" class="version-badge" data-reveal style="text-decoration: none; display: inline-block; transition: transform 0.2s, box-shadow 0.2s;" title="View Changelog">
<span class="version-text-en" lang="en">v2.2.1 OUT NOW</span>
<span class="version-text-de" lang="de">v2.2.1 JETZT VERFÜGBAR</span>
</a>
<h1 data-reveal>{{HERO_TITLE}}</h1>
<p class="hero-subtitle" data-reveal>{{HERO_SUBTITLE}}</p>
<div class="hero-mascot-container" data-reveal>
<h1>{{HERO_TITLE}}</h1>
<p class="hero-subtitle">{{HERO_SUBTITLE}}</p>
<div class="hero-mascot-container">
<img src="{{ASSET_PATH}}assets/LookDownKoala-1x.webp" srcset="{{ASSET_PATH}}assets/LookDownKoala-1x.webp 90w, {{ASSET_PATH}}assets/LookDownKoala.webp 205w" sizes="90px" alt="{{HERO_MASCOT_ALT}}" class="hero-lookdown-mascot" width="90" height="132" loading="eager" fetchpriority="high" decoding="async">
</div>
<div class="cta-group" data-reveal>
<div class="cta-group">
<a href="https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc" class="btn btn-primary">
<img src="{{ASSET_PATH}}assets/chrome.svg" alt="Chrome" width="20" height="20">
<span>{{ADD_TO_CHROME}}</span>
@@ -299,6 +295,10 @@
GitHub Releases
</a>
</div>
<a href="https://github.com/Shik3i/KoalaSync/blob/main/docs/CHANGELOG.md" target="_blank" rel="noopener" class="version-badge version-badge-below" style="text-decoration: none; display: inline-block; transition: transform 0.2s, box-shadow 0.2s;" title="View Changelog">
<span class="version-text-en" lang="en">v2.2.1 OUT NOW</span>
<span class="version-text-de" lang="de">v2.2.1 JETZT VERFÜGBAR</span>
</a>
</div>
<!-- Interactive Live Demo: two synced video tabs + the extension popup -->
@@ -321,19 +321,22 @@
</div>
<div class="demo-video">
<div class="demo-video-art" aria-hidden="true"></div>
<svg class="demo-film" viewBox="0 0 160 90" preserveAspectRatio="xMidYMax slice" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="34" cy="98" rx="60" ry="20" fill="rgba(30,27,75,0.6)"/>
<ellipse cx="128" cy="102" rx="75" ry="24" fill="rgba(49,46,129,0.4)"/>
<g class="film-ball-x"><circle class="film-ball" cx="0" cy="74" r="3.2" fill="#a5b4fc"/></g>
<g class="film-walker">
<g class="film-bob">
<circle cx="0" cy="-23" r="4.2" fill="#e2e8f0"/>
<line x1="0" y1="-19" x2="0" y2="-8" class="film-limb"/>
<line x1="0" y1="-16.5" x2="0" y2="-8.5" class="film-limb film-swing-1"/>
<line x1="0" y1="-16.5" x2="0" y2="-8.5" class="film-limb film-swing-2"/>
<line x1="0" y1="-8" x2="0" y2="3" class="film-limb film-swing-1"/>
<line x1="0" y1="-8" x2="0" y2="3" class="film-limb film-swing-2"/>
</g>
<div class="demo-seek-sweep" aria-hidden="true"></div>
<svg class="demo-film" viewBox="0 0 160 90" preserveAspectRatio="xMidYMid slice" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<g class="film-stars" fill="#e2e8f0">
<circle class="film-star" cx="18" cy="14" r="0.8"/>
<circle class="film-star" cx="42" cy="24" r="0.6"/>
<circle class="film-star" cx="64" cy="10" r="0.9"/>
<circle class="film-star" cx="90" cy="28" r="0.6"/>
<circle class="film-star" cx="108" cy="16" r="0.5"/>
<circle class="film-star" cx="134" cy="22" r="0.8"/>
<circle class="film-star" cx="150" cy="12" r="0.5"/>
</g>
<circle class="film-moon" cx="122" cy="26" r="7.5" fill="#f1f5f9" opacity="0.92"/>
<path class="film-mtn-back" d="M-12,66 L16,46 L40,60 L66,42 L94,58 L122,44 L150,60 L172,50 L172,92 L-12,92 Z" fill="rgba(30,27,75,0.7)"/>
<path class="film-mtn-front" d="M-12,80 L14,66 L36,78 L60,62 L86,76 L112,64 L140,78 L172,68 L172,92 L-12,92 Z" fill="rgba(49,46,129,0.6)"/>
<g class="film-firefly">
<circle class="film-firefly-light" cx="0" cy="72" r="1.4" fill="#fde047"/>
</g>
</svg>
<div class="demo-play-overlay" aria-hidden="true">
@@ -357,19 +360,22 @@
</div>
<div class="demo-video">
<div class="demo-video-art" aria-hidden="true"></div>
<svg class="demo-film" viewBox="0 0 160 90" preserveAspectRatio="xMidYMax slice" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="34" cy="98" rx="60" ry="20" fill="rgba(30,27,75,0.6)"/>
<ellipse cx="128" cy="102" rx="75" ry="24" fill="rgba(49,46,129,0.4)"/>
<g class="film-ball-x"><circle class="film-ball" cx="0" cy="74" r="3.2" fill="#a5b4fc"/></g>
<g class="film-walker">
<g class="film-bob">
<circle cx="0" cy="-23" r="4.2" fill="#e2e8f0"/>
<line x1="0" y1="-19" x2="0" y2="-8" class="film-limb"/>
<line x1="0" y1="-16.5" x2="0" y2="-8.5" class="film-limb film-swing-1"/>
<line x1="0" y1="-16.5" x2="0" y2="-8.5" class="film-limb film-swing-2"/>
<line x1="0" y1="-8" x2="0" y2="3" class="film-limb film-swing-1"/>
<line x1="0" y1="-8" x2="0" y2="3" class="film-limb film-swing-2"/>
</g>
<div class="demo-seek-sweep" aria-hidden="true"></div>
<svg class="demo-film" viewBox="0 0 160 90" preserveAspectRatio="xMidYMid slice" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<g class="film-stars" fill="#e2e8f0">
<circle class="film-star" cx="18" cy="14" r="0.8"/>
<circle class="film-star" cx="42" cy="24" r="0.6"/>
<circle class="film-star" cx="64" cy="10" r="0.9"/>
<circle class="film-star" cx="90" cy="28" r="0.6"/>
<circle class="film-star" cx="108" cy="16" r="0.5"/>
<circle class="film-star" cx="134" cy="22" r="0.8"/>
<circle class="film-star" cx="150" cy="12" r="0.5"/>
</g>
<circle class="film-moon" cx="122" cy="26" r="7.5" fill="#f1f5f9" opacity="0.92"/>
<path class="film-mtn-back" d="M-12,66 L16,46 L40,60 L66,42 L94,58 L122,44 L150,60 L172,50 L172,92 L-12,92 Z" fill="rgba(30,27,75,0.7)"/>
<path class="film-mtn-front" d="M-12,80 L14,66 L36,78 L60,62 L86,76 L112,64 L140,78 L172,68 L172,92 L-12,92 Z" fill="rgba(49,46,129,0.6)"/>
<g class="film-firefly">
<circle class="film-firefly-light" cx="0" cy="72" r="1.4" fill="#fde047"/>
</g>
</svg>
<div class="demo-play-overlay" aria-hidden="true">
@@ -456,6 +462,7 @@
{{MOCK_09}}
</label>
<select class="mock-input" id="demo-video-select" style="width: 100%; box-sizing: border-box; background: var(--card); border: 1px solid #334155; color: white; padding: 8px; border-radius: 8px; font-family: inherit; font-size: 0.75rem; outline: none; cursor: default;">
<option value="" class="demo-select-placeholder" selected hidden>{{DEMO_SELECT_PLACEHOLDER}}</option>
<option><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="12" height="12" aria-hidden="true"><rect x="2" y="2" width="20" height="20" rx="2.18" ry="2.18"/><line x1="7" y1="2" x2="7" y2="22"/><line x1="17" y1="2" x2="17" y2="22"/><line x1="2" y1="12" x2="22" y2="12"/><line x1="2" y1="7" x2="7" y2="7"/><line x1="2" y1="17" x2="7" y2="17"/><line x1="17" y1="17" x2="22" y2="17"/><line x1="17" y1="7" x2="22" y2="7"/></svg> Stranger Things - S4E1</option>
</select>
</div>