Sign In: the menu button now opens the full sign-in page (Google, Facebook and email) instead of jumping straight to Google
v5.8
Fix: event registration now works for logged-in visitors too — data calls use a lock-free path so the modal always opens and registrations save reliably.
v5.7
Fix: event registration modal would not open for logged-in visitors (an auth-session check could hang). It now opens reliably for everyone.
v5.6
Event registration: you can now sign in with Google, Facebook or email right inside the registration form to link your booking to an account
Signing in via Google/Facebook returns you to the event with the form ready to complete
Registering as a guest (no account) still works exactly as before
v5.5
Sign-in: added Continue with Facebook alongside Google
New email + password registration — create an account or sign in with a form, with a password-reset link
Login page redesigned with a sign-in / create-account toggle
v5.4
Events: added the upcoming gathering — ‘Visions of Truth: The Mystical World of Hildegard von Bingen’ (18 September 2026, venue & time TBA)
New event registration: visitors can Reserve a Place or Register Interest (which does not guarantee a place) via a guest-friendly form — no account or payment needed
Built on a multi-tenant foundation (organizers / events / registrations) so the booking system can later be offered to other event organizers
v5.2
Exercise prompt: tapping 'Begin practice' now transforms the current slide into the exercise in-place — no slide transition — keeping the user on the same reel
Practice panel and deep-link launches still insert a new exercise slide and scroll as before
v5.1
Favicon: generated from the Sacred XP logo — deep purple rounded-square background across all standard sizes (16, 32, 48, 96, 192, 512 px), .ico, and Apple touch icon
PWA web manifest added (site.webmanifest) with theme colour and home-screen icons
Theme-colour meta tag set to brand deep purple (#2d1b4e) for browser chrome on mobile
v5.0
Auth return fix: login redirects from products, account, cart, and orders pages now include a ?return= parameter so the user lands back on the originating page after OAuth completes
Products → Enter Reel: after login the user returns to products.html to complete timer selection instead of landing on account.html
Cart and Orders sign-in links now return the user to the respective page after login
v4.9
Auth return: signing in from any page now returns the user to exactly where they were — nav sign-in button, auth-gated redirects, and session-expiry all preserve the originating URL via localStorage across the OAuth round-trip
Sign-out from any page returns to the same page — auth-gated pages (reel, account) automatically redirect to login with the return URL intact
Session expired on the reel now redirects to login with a return URL so the user lands straight back on the reel after re-authenticating
Login page: already-logged-in fast-path now respects the ?return= parameter instead of always going to account.html
v4.8
Quiz attempts: every answer is recorded with an attempt_number so the full try history is tracked across sessions
Wrong answers resurface the quiz 5–8 slides later so the user gets another chance — correct answers never resurface
Feed skips quizzes the user already answered correctly in any previous session
Wrong result message now reads '✗ Not quite — this one will come back.' to set expectations
v4.7
Quiz feed fix: removed invalid PostgREST order parameter that silently prevented quizzes from loading — feed now correctly interleaves a quiz every 8–13 slides
v4.6
Quiz Reels: new 4th reel type — one question with multiple-choice options, correct/wrong feedback, and optional explanation revealed on answer
Quiz options lock immediately on tap; correct answer always highlights green, wrong pick highlights red
Action buttons (like, save, comment) unlock only after the user answers — keeps engagement intentional
Quizzes interleave in the feed every 8–13 slides; no quiz repeats within a session
User answers persisted to quiz_answers table (one per user per quiz)
Full like, save, and comment support consistent with reels, dialogues, and exercises
All audio now routes through Howler.js (shared AudioContext) — one user gesture unlocks autoplay for all subsequent sounds on iOS/Safari
Removed HTMLAudioElement usage entirely: reel TTS, dialogue turn TTS, exercise step TTS, and exercise intro TTS all use Howl instances
Global mute now calls Howler.mute() — all sounds silenced/restored instantly without per-instance tracking
Audio unlock prompt wired to Howler.ctx.resume() — reliably resumes the shared AudioContext on first tap
v4.4
Dialogue: chat bubble appears at the exact moment audio starts — typing dots show while TTS URL resolves (min 300 ms), then bubble and audio fire simultaneously
Autoplay after dialogue: 6 s reflection countdown starts once all turns finish
Autoplay on exercise prompt: 8 s countdown skips the slide if the user doesn't tap Begin — cancelled immediately if they do
startAutoplay() now accepts an explicit duration so non-reel slides can use the same progress-bar countdown
v4.3
TTS cache v2: DB triggers on reels, dialogue_turns, and exercises auto-generate audio on INSERT — no frontend request needed for pre-loaded content
Frontend TTS dedup cache: module-level Map prevents duplicate edge-function calls for the same text+voice (prewarm, playback, and retry all share one Promise)
Exercise descriptions: new description_audio_url column populated by trigger; prewarm and intro playback use it without an API call
prewarmLookahead now runs inside fillQueue's finally block — slides added to the queue are prewarmed immediately, not after the next swipe
Audio indicator removed in both reel-audio paths (prewarm hit and fresh load) — 'Loading audio…' no longer lingers when audio was pre-cached
Reel audio: removed redundant .load() call in prewarm — prevented browser from discarding already-buffered data
Audio unlock prompt: now routes through tryPlayAudio so the autoplay ended-listener is correctly wired after the first tap
v4.2
iOS audio unlock: silence element now pre-loaded at startup so play() succeeds reliably on first gesture
Dialogue audio: done-promise wired before play() — clip can never hang even if it's very short or play() is rejected
Dialogue: play() rejection (NotAllowedError) now falls back to reading-time delay instead of freezing forever
Dialogue replay: stale event listeners cleared on each replay; replay row hidden at run start for clean re-runs
Autoplay: countdown now starts after the reel audio ends, not when the slide appears
Autoplay: countdown duration scales with quote length (3 s – 12 s) instead of a fixed 5 s
v4.1
Mobile audio: first swipe/tap now proactively unlocks iOS/Safari autoplay — no more 'tap to enable audio' prompt in normal use
Audio pre-warming: entering any slide silently pre-generates TTS for the next 2 slides (reel, exercise, dialogue)
Exercises: intro TTS pre-fetched before slide enters — starts playing immediately on swipe
Dialogues: all turn audio pre-fetched — conversation flows without gaps between speakers
Reels: audio pre-buffered via .load() so playback is instant on swipe
Extracted ttsToUrl() helper — removes duplicated content-type branching across playStepTTS, playDialogueTurnTTS, and exercise intro
v4.0
Dialogue Reels: new conversational format — two speakers, turn by turn, each with their own TTS voice
Each turn reveals with a typing indicator, then the bubble slides in as audio plays
Speaker A (left, muted) and Speaker B (right, accent gold) have distinct visual bubbles
Replay button appears after all turns; Like, Save, Comment interactions enabled
Dialogue reels interleave in the feed every 5–9 slides