// ============================================================ // ATHAR — Router (hash-based) // Routes: // #/ -> Landing // #/select -> Number Selection // #/select/:n -> Perfume Reveal // #/checkout -> Checkout // #/confirmation -> Confirmation // #/r/:token -> Message Reveal // #/r/:token/expired -> Expired // ============================================================ const { useState, useEffect, useRef, useCallback } = React; function parseHash() { const h = window.location.hash || '#/'; const path = h.replace(/^#/, '') || '/'; const parts = path.split('/').filter(Boolean); return { path, parts }; } function navigate(to) { window.location.hash = to.startsWith('#') ? to : '#' + to; window.scrollTo({ top: 0, behavior: 'auto' }); } window.athNavigate = navigate; function useRoute() { const [route, setRoute] = useState(parseHash()); useEffect(() => { const onHash = () => { setRoute(parseHash()); window.scrollTo({ top: 0, behavior: 'auto' }); }; window.addEventListener('hashchange', onHash); return () => window.removeEventListener('hashchange', onHash); }, []); return route; } // ============================================================ // Selected number persistence (so checkout/confirm know which #) // ============================================================ function getSelectedNumber() { const n = parseInt(sessionStorage.getItem('athar.selected'), 10); return Number.isFinite(n) && window.PERFUMES[n] ? n : 7; // default 7 per spec sample } function setSelectedNumber(n) { sessionStorage.setItem('athar.selected', String(n)); } // ============================================================ // Shared nav (pages 1–5 only) // ============================================================ function Nav({ showBack }) { return ( ); } // ============================================================ // App // ============================================================ function App() { const { parts } = useRoute(); // route resolution let view = 'landing'; let params = {}; if (parts.length === 0) { view = 'landing'; } else if (parts[0] === 'select' && parts.length === 1) { view = 'select'; } else if (parts[0] === 'select' && parts.length === 2) { view = 'perfume'; params.n = parseInt(parts[1], 10); } else if (parts[0] === 'checkout') { view = 'checkout'; } else if (parts[0] === 'confirmation') { view = 'confirmation'; } else if (parts[0] === 'r' && parts.length === 2) { view = 'reveal'; params.token = parts[1]; } else if (parts[0] === 'r' && parts.length === 3 && parts[2] === 'expired') { view = 'expired'; params.token = parts[1]; } else { view = 'landing'; } const isStandalone = view === 'reveal' || view === 'expired'; const showBack = !isStandalone && view !== 'landing'; // Page key drives the fade transition on every route change const pageKey = view + ':' + JSON.stringify(params); let body = null; if (view === 'landing') body = ; else if (view === 'select') body =