@@ -245,25 +245,33 @@ function wireOnboarding() {
245245 if ( e . target === dialog ) close ( "backdrop" ) ;
246246 } ) ;
247247
248+ // Expose a replay handle for the settings "Replay" button.
249+ function replay ( ) {
250+ stepIdx = 0 ;
251+ render ( ) ;
252+ try {
253+ dialog . showModal ( ) ;
254+ track ( "onboarding_open" ) ;
255+ } catch ( _ ) { }
256+ }
257+
248258 // Show only on first visit: no onboarded flag AND no recorded progress.
249259 let onboarded = false ;
250260 try { onboarded = localStorage . getItem ( "codeCrispies.onboarded" ) === "1" ; } catch ( _ ) { }
251261 const hasProgress = Object . keys ( lessonEngine . userProgress || { } ) . some (
252262 ( k ) => ( lessonEngine . userProgress [ k ] ?. completed ?. length || 0 ) > 0
253263 ) ;
254264 if ( ! onboarded && ! hasProgress ) {
255- stepIdx = 0 ;
256- render ( ) ;
257265 // Defer to next frame so the page paints first
258- requestAnimationFrame ( ( ) => {
259- try {
260- dialog . showModal ( ) ;
261- track ( "onboarding_open" ) ;
262- } catch ( _ ) { }
263- } ) ;
266+ requestAnimationFrame ( replay ) ;
264267 }
268+ return { replay } ;
265269}
266270
271+ // Module-scoped handle so the "Replay" settings button can re-open the
272+ // tour without rewiring listeners (which would double-bind).
273+ let _onboardingHandle = null ;
274+
267275// Track CodeMirror views for cleanup
268276let sectionCodeViews = [ ] ;
269277
@@ -3461,7 +3469,18 @@ function init() {
34613469
34623470 // Onboarding tour — shown once on first visit when user has no progress.
34633471 // 5 steps; localStorage flag prevents re-showing after Skip / completion.
3464- wireOnboarding ( ) ;
3472+ _onboardingHandle = wireOnboarding ( ) ;
3473+
3474+ // Replay onboarding from settings — clears flag + re-shows tour
3475+ // without rewiring listeners (the wireOnboarding handle is reused).
3476+ document . getElementById ( "reset-onboarding-btn" ) ?. addEventListener ( "click" , ( ) => {
3477+ try { localStorage . removeItem ( "codeCrispies.onboarded" ) ; } catch ( _ ) { }
3478+ closeSidebar ( ) ; // dismiss the settings drawer
3479+ requestAnimationFrame ( ( ) => {
3480+ _onboardingHandle ?. replay ( ) ;
3481+ track ( "onboarding_replay" ) ;
3482+ } ) ;
3483+ } ) ;
34653484
34663485 // Click on editor content to focus CodeMirror
34673486 elements . editorContent ?. addEventListener ( "click" , ( ) => {
0 commit comments