@@ -110,12 +110,18 @@ class V2Announcement {
110110 btn . addEventListener ( 'click' , ( ) => this . prevStep ( ) ) ;
111111 } ) ;
112112
113- // Progress dots
114- const dots = document . querySelectorAll ( '.v2-progress-dot' ) ;
115- dots . forEach ( ( dot , index ) => {
116- dot . addEventListener ( 'click' , ( ) => this . showStep ( index + 1 ) ) ;
113+ // Progress dots (both desktop and mobile sets)
114+ const dotSets = document . querySelectorAll ( '.v2-progress-dots' ) ;
115+ dotSets . forEach ( container => {
116+ const dots = container . querySelectorAll ( '.v2-progress-dot' ) ;
117+ dots . forEach ( ( dot , index ) => {
118+ dot . addEventListener ( 'click' , ( ) => this . showStep ( index + 1 ) ) ;
119+ } ) ;
117120 } ) ;
118121
122+ // Swipe navigation for touch devices
123+ this . setupSwipeNavigation ( ) ;
124+
119125 // Continue as guest
120126 const guestBtn = document . getElementById ( 'v2-guest-btn' ) ;
121127 if ( guestBtn ) {
@@ -143,6 +149,32 @@ class V2Announcement {
143149 }
144150 }
145151
152+ setupSwipeNavigation ( ) {
153+ const wrapper = document . querySelector ( '.v2-modal-content-wrapper' ) ;
154+ if ( ! wrapper ) return ;
155+
156+ let startX = 0 ;
157+ let startY = 0 ;
158+
159+ wrapper . addEventListener ( 'touchstart' , ( e ) => {
160+ startX = e . touches [ 0 ] . clientX ;
161+ startY = e . touches [ 0 ] . clientY ;
162+ } , { passive : true } ) ;
163+
164+ wrapper . addEventListener ( 'touchend' , ( e ) => {
165+ if ( ! this . modalShown ) return ;
166+ const dx = e . changedTouches [ 0 ] . clientX - startX ;
167+ const dy = e . changedTouches [ 0 ] . clientY - startY ;
168+ // only count horizontal swipes (ignore vertical scrolls)
169+ if ( Math . abs ( dx ) < 50 || Math . abs ( dy ) > Math . abs ( dx ) ) return ;
170+ if ( dx < 0 ) {
171+ this . nextStep ( ) ;
172+ } else {
173+ this . prevStep ( ) ;
174+ }
175+ } , { passive : true } ) ;
176+ }
177+
146178 openModal ( ) {
147179 if ( this . modalShown ) return ;
148180
@@ -285,34 +317,27 @@ class V2Announcement {
285317
286318 animateProgressForDot ( stepNumber ) {
287319 if ( this . prefersReducedMotion ) return ;
288- const dots = document . querySelectorAll ( '.v2-progress- dot' ) ;
289- dots . forEach ( ( dot , idx ) => {
290- // ensure relative positioning for fill
320+ // Animate across all dot containers (desktop + mobile)
321+ const allDots = document . querySelectorAll ( '.v2-progress-dot' ) ;
322+ allDots . forEach ( ( dot ) => {
291323 dot . style . position = 'relative' ;
292- // remove existing fill
293324 const existing = dot . querySelector ( '.v2-progress-fill' ) ;
294325 if ( existing ) existing . remove ( ) ;
295- // only add fill to active dot
296- if ( idx + 1 === stepNumber ) {
326+
327+ if ( dot . classList . contains ( 'active' ) ) {
297328 const fill = document . createElement ( 'span' ) ;
298329 fill . className = 'v2-progress-fill' ;
299- // initial styles
300330 fill . style . position = 'absolute' ;
301331 fill . style . left = '0' ;
302332 fill . style . top = '0' ;
303333 fill . style . height = '100%' ;
304334 fill . style . width = '0%' ;
305335 fill . style . borderRadius = '999px' ;
306- fill . style . background = 'linear-gradient(90deg, rgba(124,58,237,0.9), rgba(99,102,241,0.9) )' ;
336+ fill . style . background = 'rgba(124, 58, 237, 0.85 )' ;
307337 fill . style . zIndex = '0' ;
308338 fill . style . transition = `width ${ this . autoAdvanceInterval } ms linear` ;
309339 dot . appendChild ( fill ) ;
310- // force layout then animate to full width
311- // expand to match the dot's computed width
312340 requestAnimationFrame ( ( ) => {
313- // ensure the dot has been sized (active dot may be wider)
314- const targetW = dot . clientWidth + 'px' ;
315- // use percentage to fill entire dot
316341 fill . style . width = '100%' ;
317342 } ) ;
318343 }
@@ -362,16 +387,21 @@ class V2Announcement {
362387 }
363388
364389 updateProgressDots ( activeStep ) {
365- const dots = document . querySelectorAll ( '.v2-progress-dot' ) ;
366- dots . forEach ( ( dot , index ) => {
367- if ( index + 1 === activeStep ) {
368- dot . classList . add ( 'active' ) ;
369- // ensure active dot has progress animation started
370- this . animateProgressForDot ( activeStep ) ;
371- } else {
372- dot . classList . remove ( 'active' ) ;
373- }
390+ // There are two sets of dots (desktop footer + mobile nav), both use
391+ // .v2-progress-dots containers. Update every dot across all containers.
392+ const dotSets = document . querySelectorAll ( '.v2-progress-dots' ) ;
393+ dotSets . forEach ( container => {
394+ const dots = container . querySelectorAll ( '.v2-progress-dot' ) ;
395+ dots . forEach ( ( dot , index ) => {
396+ if ( index + 1 === activeStep ) {
397+ dot . classList . add ( 'active' ) ;
398+ } else {
399+ dot . classList . remove ( 'active' ) ;
400+ }
401+ } ) ;
374402 } ) ;
403+ // animate progress fill across all active dots
404+ this . animateProgressForDot ( activeStep ) ;
375405 }
376406
377407 nextStep ( ) {
0 commit comments