/* ============================================================ HeroWelten — 3-Welten-Hero (heller Aurora-Look) als SPA-Sektion. Ersetzt Splash + alten Hero. Wahl der Welt setzt die Pfad-Logik darunter (ha→altbau, nb→neubau, lox→gewerbe) via onPick(). Markup + Interaktion 1:1 aus „Smartmacherei - 3 Welten v3". CSS unter .smw gescopet; Welt-Farb-Variablen leben global in index.html. Hero-Rework v4 (Feedback-Runde): Bühne ist jetzt ein festes Mit/Ohne-Kachelpaar links vom Phone (keine ?stage=a|b|c-Varianten mehr), öffnet ausschließlich beim Hover auf #smPhone, einheitlicher Geräte-Bezel statt Doppelrahmen, Boot-Animation beim Laden, Mikro-Interaktionen (Hotspot-Scale, Detail-Slide, Chip-Press) und ein "Echte App"-Tab, der den Phone-Screen live per
Original Home Assistant App
Mit Smartmacherei
Ohne

↑ Auswahl ändern, um die App zu wechseln
`; // Init: house-demo + phone-hover (einmalig); world-getriebene Visuals separat. React.useEffect(() => { const root = ref.current; if (!root) return; const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches; // Welt-Auswahl -> nach oben melden const choices = root.querySelectorAll('.choice'); const onChoiceClick = (e) => { const c = e.currentTarget; if (onPickRef.current) onPickRef.current(c.dataset.phone); if (phoneWorldRef.current) phoneWorldRef.current(c.dataset.phone); }; choices.forEach((c) => c.addEventListener('click', onChoiceClick)); // Smooth-scroll CTAs const scrollers = root.querySelectorAll('[data-scroll]'); const onScrollClick = (e) => { e.preventDefault(); const id = e.currentTarget.dataset.scroll; if (window.smoothScrollTo) window.smoothScrollTo(id); else { const el = document.getElementById(id); if (el) el.scrollIntoView({ behavior: 'smooth' }); } }; scrollers.forEach((a) => a.addEventListener('click', onScrollClick)); // Original-Screenshot-Phone: Hotspots, Detail-Overlay, Slider (ersetzt frühere Mini-Screen-Repliken) const A = window.SM_HERO_ASSETS; const phoneScreen = root.querySelector('#phoneScreen'); const phoneScreen2 = root.querySelector('#phoneScreen2'); const phone2El = root.querySelector('#smPhone2'); const phoneShot = root.querySelector('#phoneShot'); const hotspotHost = root.querySelector('#phoneHotspots'); const detail = root.querySelector('#phoneDetail'); const detailShot = root.querySelector('#detailShot'); const detailDrag = root.querySelector('#detailDrag'); const detailHandle = root.querySelector('#detailHandle'); const detailPresets = root.querySelector('#detailPresets'); const detailBack = root.querySelector('#detailBack'); const phoneTag = root.querySelector('#phoneTag'); const stageHint = root.querySelector('.stage-hint'); let currentEx = null; let haApp = null; let loxApp = null; let loxApp2 = null; // zweites Phone (Loxone) fuer die Neubau-Welt let currentWorld = 'ha'; let dragLevel = 1; let tweenRaf = null; const clamp01 = (v) => Math.max(0, Math.min(1, v)); // Task 5: Boot-Animation (weißer Screen + Spinner/Skeleton) beim Mount und bei jedem // Welt-Wechsel. Rein zeitgesteuert (kein echtes Warten auf Bildladen nötig — die // Screenshots sind winzige lokale Assets), ~700ms wie gefordert. let bootTimer = null; const showBoot = () => { if (phoneScreen) phoneScreen.classList.add('booting'); }; const hideBoot = () => { if (phoneScreen) phoneScreen.classList.remove('booting'); }; const bootPulse = (ms) => { showBoot(); if (bootTimer) clearTimeout(bootTimer); bootTimer = setTimeout(hideBoot, ms || 700); }; const setPhoneWorld = (w0) => { if (!A || !phoneShot) return; const w = (w0 === 'lox') ? 'lox' : (w0 === 'nb') ? 'nb' : 'ha'; currentWorld = w; setMode('guided'); if (liveTab) liveTab.hidden = (w !== 'ha') || !liveEnabled; if (stageHint) stageHint.style.display = ((w !== 'ha') || !liveEnabled) ? 'none' : ''; // Neubau (nb) = beide Systeme nebeneinander -> keine Tabs, zwei Phones. if (phoneTabs) phoneTabs.style.display = (w === 'nb') ? 'none' : ''; if (stage) stage.classList.toggle('two-phones', w === 'nb'); bootPulse(700); if (phoneScreen) phoneScreen.dataset.world = (w === 'lox') ? 'lox' : 'ha'; if (phoneTag) phoneTag.textContent = w === 'lox' ? 'Original Loxone App' : 'Home Assistant App'; closeDetail(); phoneShot.style.display = 'none'; hotspotHost.style.display = 'none'; hotspotHost.innerHTML = ''; // Phone 1 (#phoneScreen): lox -> Loxone-App, sonst (ha/nb) -> HA-App. if (w === 'lox') { if (haApp) haApp.hide(); if (!loxApp && window.LoxAppDemo) loxApp = window.LoxAppDemo.mount(phoneScreen, { actionTarget: root, world: 'lox' }); if (loxApp) { loxApp.show(); loxApp.showHome(); } } else { if (loxApp) loxApp.hide(); if (!haApp && window.HaAppDemo) haApp = window.HaAppDemo.mount(phoneScreen, { actionTarget: root, world: 'ha' }); if (haApp) { haApp.show(); haApp.showHome(); } } // Phone 2 (#phoneScreen2): nur in nb -> Loxone-App neben dem HA-Phone. if (phone2El) phone2El.style.display = (w === 'nb') ? '' : 'none'; if (w === 'nb') { // Beide Apps "laden": Phone 2 (Loxone) bekommt denselben Boot-Puls wie Phone 1. if (phoneScreen2) { phoneScreen2.classList.add('booting'); setTimeout(() => phoneScreen2.classList.remove('booting'), 700); } if (!loxApp2 && window.LoxAppDemo && phoneScreen2) loxApp2 = window.LoxAppDemo.mount(phoneScreen2, { actionTarget: root, world: 'lox' }); if (loxApp2) { loxApp2.show(); loxApp2.showHome(); } } else if (loxApp2) { loxApp2.hide(); } }; // Task 7: "Echte App ausprobieren" — Tabs schalten den Phone-Screen zwischen der // geführten Screenshot-Demo und einem echten