@@ -174,40 +174,46 @@ document.querySelectorAll('.cta-bot').forEach(a => { a.href='https://t.me/Metrid
174174} ) ( ) ;
175175
176176
177- // === Metridex Screens carousel ===
177+ /* Metridex Lightbox bootstrap (idempotent) */
178178( function ( ) {
179- const lb = document . getElementById ( 'mdxLightbox' ) ;
180- const lbImg = lb ? lb . querySelector ( 'img' ) : null ;
181- const lbClose = lb ? lb . querySelector ( '.mdx-close' ) : null ;
182- function openLB ( src ) { if ( ! lb || ! lbImg ) return ; lbImg . src = src ; lb . classList . add ( 'open' ) ; lb . removeAttribute ( 'hidden' ) ; }
183- function closeLB ( ) { if ( ! lb ) return ; lb . classList . remove ( 'open' ) ; lb . setAttribute ( 'hidden' , '' ) ; }
184- lb && ( lb . addEventListener ( 'click' , closeLB ) , lbClose && lbClose . addEventListener ( 'click' , closeLB ) ) ;
185- document . addEventListener ( 'keydown' , ( e ) => { if ( e . key === 'Escape' ) closeLB ( ) ; } ) ;
186-
187- document . querySelectorAll ( '.mdx-frame' ) . forEach ( frame => {
188- const list = ( frame . getAttribute ( 'data-images' ) || '' ) . split ( ',' ) . map ( s => s . trim ( ) ) . filter ( Boolean ) ;
189- const stage = frame . querySelector ( '.mdx-stage' ) ;
190- const img = new Image ( ) ;
191- let i = 0 ;
192- function render ( ) { img . src = list [ i ] ; counter . textContent = ( i + 1 ) + ' / ' + list . length ; }
193- img . alt = frame . getAttribute ( 'data-alt' ) || 'Metridex screenshot' ;
194- img . addEventListener ( 'click' , ( ) => openLB ( img . src ) ) ;
195- stage . appendChild ( img ) ;
196-
197- const prev = frame . querySelector ( '.mdx-prev' ) ;
198- const next = frame . querySelector ( '.mdx-next' ) ;
199- const counter = frame . querySelector ( '.mdx-counter' ) ;
200-
201- function step ( d ) { i = ( i + d + list . length ) % list . length ; render ( ) ; }
202- prev && prev . addEventListener ( 'click' , ( ) => step ( - 1 ) ) ;
203- next && next . addEventListener ( 'click' , ( ) => step ( 1 ) ) ;
204-
205- // Touch swipe
206- let sx = null ;
207- stage . addEventListener ( 'touchstart' , e => sx = e . touches [ 0 ] . clientX , { passive :true } ) ;
208- stage . addEventListener ( 'touchend' , e => { if ( sx == null ) return ; const dx = e . changedTouches [ 0 ] . clientX - sx ; if ( Math . abs ( dx ) > 40 ) step ( dx < 0 ?1 :- 1 ) ; sx = null ; } , { passive :true } ) ;
209-
210- if ( list . length ) { render ( ) ; }
211- } ) ;
179+ function ensureLightbox ( ) {
180+ var lb = document . getElementById ( 'mdxLightbox' ) ;
181+ if ( ! lb ) {
182+ lb = document . createElement ( 'div' ) ;
183+ lb . id = 'mdxLightbox' ;
184+ lb . className = 'mdx-lightbox' ;
185+ lb . setAttribute ( 'hidden' , '' ) ;
186+ var img = document . createElement ( 'img' ) ;
187+ var btn = document . createElement ( 'button' ) ;
188+ btn . className = 'mdx-close' ; btn . setAttribute ( 'aria-label' , 'Close' ) ; btn . textContent = '✕' ;
189+ lb . appendChild ( img ) ; lb . appendChild ( btn ) ;
190+ document . body . appendChild ( lb ) ;
191+ }
192+ return lb ;
193+ }
194+ function openLB ( src ) {
195+ var lb = ensureLightbox ( ) ;
196+ var img = lb . querySelector ( 'img' ) ;
197+ var btn = lb . querySelector ( '.mdx-close' ) ;
198+ img . src = src ;
199+ lb . classList . add ( 'open' ) ;
200+ lb . removeAttribute ( 'hidden' ) ;
201+ function close ( ) { lb . classList . remove ( 'open' ) ; lb . setAttribute ( 'hidden' , '' ) ; }
202+ lb . addEventListener ( 'click' , close , { once :true } ) ;
203+ btn && btn . addEventListener ( 'click' , close , { once :true } ) ;
204+ document . addEventListener ( 'keydown' , function esc ( e ) { if ( e . key === 'Escape' ) { close ( ) ; document . removeEventListener ( 'keydown' , esc ) ; } } ) ;
205+ }
206+ function bindScreens ( ) {
207+ document . querySelectorAll ( '.mdx-frame .mdx-stage img' ) . forEach ( function ( img ) {
208+ if ( ! img . dataset . lbBound ) {
209+ img . dataset . lbBound = '1' ;
210+ img . style . cursor = 'zoom-in' ;
211+ img . addEventListener ( 'click' , function ( ) { openLB ( img . currentSrc || img . src ) ; } ) ;
212+ }
213+ } ) ;
214+ }
215+ // Run on ready and after load (in case images are added later)
216+ if ( document . readyState === 'complete' || document . readyState === 'interactive' ) { bindScreens ( ) ; }
217+ else { document . addEventListener ( 'DOMContentLoaded' , bindScreens ) ; }
218+ window . addEventListener ( 'load' , bindScreens ) ;
212219} ) ( ) ;
213- // === /Carousel ===
0 commit comments