@@ -107,7 +107,7 @@ <h1>Make Smarter <br /><span class="gradient-text">Tech Decisions.</span>
107107 Just clear guidance on the tech that powers modern work.</ p >
108108
109109 </ div >
110- <!-- Pull-Out Animated Deck -->
110+ <!-- Pull-Out Animated Deck -->
111111 < div class ="hero-visual ">
112112 < style >
113113 .deck-container {
@@ -119,9 +119,12 @@ <h1>Make Smarter <br /><span class="gradient-text">Tech Decisions.</span>
119119 perspective : 1200px ;
120120 transform-style : preserve-3d;
121121 }
122+
122123 .deck-card {
123124 position : absolute;
124- top : 0 ; left : 0 ; right : 0 ;
125+ top : 0 ;
126+ left : 0 ;
127+ right : 0 ;
125128 background : rgba (15 , 23 , 42 , 0.7 );
126129 backdrop-filter : blur (16px );
127130 border : 1px solid var (--border-glass );
@@ -138,45 +141,134 @@ <h1>Make Smarter <br /><span class="gradient-text">Tech Decisions.</span>
138141 /* Smooth transitions when dropping or clicking next */
139142 transition : transform 0.4s cubic-bezier (0.2 , 0.8 , 0.2 , 1 ), opacity 0.4s linear;
140143 }
144+
141145 .deck-card : active {
142146 cursor : grabbing;
143147 }
148+
144149 .deck-card img {
145- width : 100% ; height : auto; border-radius : 8px ; margin-bottom : 1rem ; aspect-ratio : 16 / 9 ; object-fit : cover; pointer-events : none;
150+ width : 100% ;
151+ height : auto;
152+ border-radius : 8px ;
153+ margin-bottom : 1rem ;
154+ aspect-ratio : 16 / 9 ;
155+ object-fit : cover;
156+ pointer-events : none;
157+ }
158+
159+ .deck-card h3 {
160+ font-size : 1.4rem ;
161+ margin-bottom : 0.5rem ;
162+ line-height : 1.3 ;
163+ color : white;
164+ }
165+
166+ .deck-card p {
167+ color : var (--text-secondary );
168+ font-size : 0.95rem ;
169+ margin-bottom : 1.5rem ;
170+ line-height : 1.5 ;
171+ pointer-events : none;
172+ flex-grow : 1 ;
146173 }
147- .deck-card h3 { font-size : 1.4rem ; margin-bottom : 0.5rem ; line-height : 1.3 ; color : white; }
148- .deck-card p { color : var (--text-secondary ); font-size : 0.95rem ; margin-bottom : 1.5rem ; line-height : 1.5 ; pointer-events : none; flex-grow : 1 ; }
149-
174+
150175 /* The pull indicator */
151176 .pull-indicator {
152- position : absolute; top : -30px ; right : 10px ; font-size : 0.85rem ; color : var (--accent ); opacity : 0 ;
153- font-weight : 600 ; text-transform : uppercase; letter-spacing : 1px ; z-index : 10 ;
177+ position : absolute;
178+ top : -30px ;
179+ right : 10px ;
180+ font-size : 0.85rem ;
181+ color : var (--accent );
182+ opacity : 0 ;
183+ font-weight : 600 ;
184+ text-transform : uppercase;
185+ letter-spacing : 1px ;
186+ z-index : 10 ;
154187 animation : bounceX 2s infinite ease-in-out;
155188 pointer-events : none;
156189 }
190+
157191 @keyframes bounceX {
158- 0% , 100% { transform : translateX (0 ); opacity : 0.8 ;}
159- 50% { transform : translateX (-10px ); opacity : 0.4 ;}
192+
193+ 0% ,
194+ 100% {
195+ transform : translateX (0 );
196+ opacity : 0.8 ;
197+ }
198+
199+ 50% {
200+ transform : translateX (-10px );
201+ opacity : 0.4 ;
202+ }
160203 }
161-
204+
162205 /* Deck states based on data-depth attributes controlled by JS */
163- .deck-card [data-depth = "0" ] { transform : translateZ (0 ) translateY (0 ) scale (1 ); z-index : 3 ; opacity : 1 ; }
164- .deck-card [data-depth = "1" ] { transform : translateZ (-80px ) translateY (25px ) scale (0.95 ); z-index : 2 ; opacity : 0.8 ; }
165- .deck-card [data-depth = "2" ] { transform : translateZ (-160px ) translateY (50px ) scale (0.9 ); z-index : 1 ; opacity : 0.4 ; }
166-
206+ .deck-card [data-depth = "0" ] {
207+ transform : translateZ (0 ) translateY (0 ) scale (1 );
208+ z-index : 3 ;
209+ opacity : 1 ;
210+ }
211+
212+ .deck-card [data-depth = "1" ] {
213+ transform : translateZ (-80px ) translateY (25px ) scale (0.95 );
214+ z-index : 2 ;
215+ opacity : 0.8 ;
216+ }
217+
218+ .deck-card [data-depth = "2" ] {
219+ transform : translateZ (-160px ) translateY (50px ) scale (0.9 );
220+ z-index : 1 ;
221+ opacity : 0.4 ;
222+ }
223+
167224 /* Thrown away states */
168- .deck-card .throw-left { transform : translateZ (0 ) translateX (-150% ) rotate (-15deg ) !important ; opacity : 0 !important ; }
169- .deck-card .throw-right { transform : translateZ (0 ) translateX (150% ) rotate (15deg ) !important ; opacity : 0 !important ; }
225+ .deck-card .throw-left {
226+ transform : translateZ (0 ) translateX (-150% ) rotate (-15deg ) !important ;
227+ opacity : 0 !important ;
228+ }
229+
230+ .deck-card .throw-right {
231+ transform : translateZ (0 ) translateX (150% ) rotate (15deg ) !important ;
232+ opacity : 0 !important ;
233+ }
170234
171235 /* Controls */
172236 .deck-controls {
173- display : flex; justify-content : space-between; align-items : center; max-width : 400px ; margin : 0 auto; position : relative; z-index : 10 ;
237+ display : flex;
238+ justify-content : center;
239+ align-items : center;
240+ gap : 1.5rem ;
241+ max-width : 400px ;
242+ margin : 0.5rem auto 0 ;
243+ position : relative;
244+ z-index : 10 ;
174245 }
246+
175247 .deck-controls button {
176- background : rgba (255 , 255 , 255 , 0.05 ); border : 1px solid var (--border-glass ); color : white; width : 45px ; height : 45px ; border-radius : 50% ; cursor : pointer; transition : 0.2s ; display : flex; align-items : center; justify-content : center;
248+ background : rgba (15 , 23 , 42 , 0.8 );
249+ backdrop-filter : blur (10px );
250+ border : 1px solid var (--border-glass );
251+ color : white;
252+ width : 45px ;
253+ height : 45px ;
254+ border-radius : 50% ;
255+ cursor : pointer;
256+ transition : 0.2s ;
257+ display : flex;
258+ align-items : center;
259+ justify-content : center;
260+ box-shadow : 0 4px 10px rgba (0 , 0 , 0 , 0.3 );
261+ }
262+
263+ .deck-controls button : hover {
264+ background : var (--accent );
265+ color : # 000 ;
266+ transform : scale (1.1 );
267+ }
268+
269+ .deck-controls button i {
270+ font-size : 1.1rem ;
177271 }
178- .deck-controls button : hover { background : var (--accent ); color : # 000 ; }
179- .deck-controls button i { font-size : 1.1rem ; }
180272 </ style >
181273
182274 < div class ="deck-container " id ="reviewDeck ">
@@ -185,67 +277,77 @@ <h1>Make Smarter <br /><span class="gradient-text">Tech Decisions.</span>
185277
186278 <!-- Card 0: Sony -->
187279 < div class ="deck-card " data-index ="0 ">
188- < div style ="font-size: 0.75rem; color: var(--accent); font-weight: bold; text-transform: uppercase; margin-bottom: 0.5rem; ">
280+ < div
281+ style ="font-size: 0.75rem; color: var(--accent); font-weight: bold; text-transform: uppercase; margin-bottom: 0.5rem; ">
189282 < i class ="fa-solid fa-headphones "> </ i > Audio
190283 </ div >
191284 < img src ="posts/images/sony-wh-1000xm5-front.jpg " alt ="Sony WH-1000XM5 " loading ="lazy ">
192285 < h3 > Sony WH-1000XM5</ h3 >
193286 < p > Top-tier active noise cancellation and supreme all-day comfort for deep focus sessions.</ p >
194- < a class ="read-more " href ="posts/sony-wh-1000xm5-review.html " style ="font-weight: 700; display:inline-block; margin-top: auto; "> Read Review < i class ="fa-solid fa-arrow-right " style ="margin-left: 5px; "> </ i > </ a >
287+ < a class ="read-more " href ="posts/sony-wh-1000xm5-review.html "
288+ style ="font-weight: 700; display:inline-block; margin-top: auto; "> Read Review < i
289+ class ="fa-solid fa-arrow-right " style ="margin-left: 5px; "> </ i > </ a >
195290 </ div >
196291
197292 <!-- Card 1: Shure -->
198293 < div class ="deck-card " data-index ="1 ">
199- < div style ="font-size: 0.75rem; color: var(--accent); font-weight: bold; text-transform: uppercase; margin-bottom: 0.5rem; ">
294+ < div
295+ style ="font-size: 0.75rem; color: var(--accent); font-weight: bold; text-transform: uppercase; margin-bottom: 0.5rem; ">
200296 < i class ="fa-solid fa-microphone "> </ i > Broadcasting
201297 </ div >
202298 < img src ="posts/images/shure-sm7db-primary.jpg " alt ="Shure SM7dB Microphone " loading ="lazy ">
203299 < h3 > Shure SM7dB</ h3 >
204300 < p > The industry standard podcast microphone, now powered with a built-in clean preamp.</ p >
205- < a class ="read-more " href ="posts/shure-sm7db-review.html " style ="font-weight: 700; display:inline-block; margin-top: auto; "> Read Review < i class ="fa-solid fa-arrow-right " style ="margin-left: 5px; "> </ i > </ a >
301+ < a class ="read-more " href ="posts/shure-sm7db-review.html "
302+ style ="font-weight: 700; display:inline-block; margin-top: auto; "> Read Review < i
303+ class ="fa-solid fa-arrow-right " style ="margin-left: 5px; "> </ i > </ a >
206304 </ div >
207305
208306 <!-- Card 2: Alienware -->
209307 < div class ="deck-card " data-index ="2 ">
210- < div style ="font-size: 0.75rem; color: var(--accent); font-weight: bold; text-transform: uppercase; margin-bottom: 0.5rem; ">
308+ < div
309+ style ="font-size: 0.75rem; color: var(--accent); font-weight: bold; text-transform: uppercase; margin-bottom: 0.5rem; ">
211310 < i class ="fa-solid fa-desktop "> </ i > Displays
212311 </ div >
213312 < img src ="posts/images/alienware-aw3423dwf-front.jpg " alt ="Alienware AW3423DWF " loading ="lazy ">
214313 < h3 > Alienware AW3423DWF</ h3 >
215314 < p > Stunning QD-OLED ultrawide performance delivering flawless visual immersion.</ p >
216- < a class ="read-more " href ="posts/alienware-aw3423dwf-review.html " style ="font-weight: 700; display:inline-block; margin-top: auto; "> Read Review < i class ="fa-solid fa-arrow-right " style ="margin-left: 5px; "> </ i > </ a >
315+ < a class ="read-more " href ="posts/alienware-aw3423dwf-review.html "
316+ style ="font-weight: 700; display:inline-block; margin-top: auto; "> Read Review < i
317+ class ="fa-solid fa-arrow-right " style ="margin-left: 5px; "> </ i > </ a >
217318 </ div >
218319 </ div >
219-
320+
220321 < div class ="deck-controls ">
221322 < button id ="deckPrev " aria-label ="Previous Review "> < i class ="fa-solid fa-arrow-left "> </ i > </ button >
222- < span style ="font-size: 0.9rem; color: var(--text-muted); font-weight: 600; letter-spacing: 1px; " id ="deckCount "> 1 / 3</ span >
323+ < span style ="font-size: 0.9rem; color: var(--text-muted); font-weight: 600; letter-spacing: 1px; "
324+ id ="deckCount "> 1 / 3</ span >
223325 < button id ="deckNext " aria-label ="Next Review "> < i class ="fa-solid fa-arrow-right "> </ i > </ button >
224326 </ div >
225327
226328 < script >
227329 document . addEventListener ( 'DOMContentLoaded' , ( ) => {
228330 const deck = document . getElementById ( 'reviewDeck' ) ;
229- if ( ! deck ) return ;
230-
331+ if ( ! deck ) return ;
332+
231333 const cards = Array . from ( deck . querySelectorAll ( '.deck-card' ) ) ;
232334 const prevBtn = document . getElementById ( 'deckPrev' ) ;
233335 const nextBtn = document . getElementById ( 'deckNext' ) ;
234336 const countEl = document . getElementById ( 'deckCount' ) ;
235337 const hint = document . getElementById ( 'pullHint' ) ;
236-
237- let topIndex = 0 ;
338+
339+ let topIndex = 0 ;
238340 const total = cards . length ;
239341
240342 function updateDeck ( ) {
241343 cards . forEach ( ( card , i ) => {
242- card . classList . remove ( 'throw-left' , 'throw-right' ) ;
243- card . style . transition = '' ; // reset to CSS transition
244- card . style . transform = '' ; // clears inline drag transforms
245-
246- // Distance from current top card
247- let depth = ( i - topIndex + total ) % total ;
248- card . setAttribute ( 'data-depth' , depth . toString ( ) ) ;
344+ card . classList . remove ( 'throw-left' , 'throw-right' ) ;
345+ card . style . transition = '' ; // reset to CSS transition
346+ card . style . transform = '' ; // clears inline drag transforms
347+
348+ // Distance from current top card
349+ let depth = ( i - topIndex + total ) % total ;
350+ card . setAttribute ( 'data-depth' , depth . toString ( ) ) ;
249351 } ) ;
250352 countEl . textContent = `${ topIndex + 1 } / ${ total } ` ;
251353 }
@@ -254,18 +356,18 @@ <h3>Alienware AW3423DWF</h3>
254356 const currentTopCard = cards [ topIndex ] ;
255357 // Apply the throw animation class
256358 currentTopCard . classList . add ( direction === 'left' ? 'throw-left' : 'throw-right' ) ;
257-
359+
258360 // Hide hint after first interaction
259- if ( hint ) hint . style . display = 'none' ;
361+ if ( hint ) hint . style . display = 'none' ;
260362
261363 // Wait enough time for the throw animation to clear visually before re-stacking
262364 setTimeout ( ( ) => {
263- if ( direction === 'left' || direction === 'next' ) {
264- topIndex = ( topIndex + 1 ) % total ;
265- } else {
266- topIndex = ( topIndex - 1 + total ) % total ;
267- }
268- updateDeck ( ) ;
365+ if ( direction === 'left' || direction === 'next' ) {
366+ topIndex = ( topIndex + 1 ) % total ;
367+ } else {
368+ topIndex = ( topIndex - 1 + total ) % total ;
369+ }
370+ updateDeck ( ) ;
269371 } , 300 ) ; // 300ms matches CSS transition timing
270372 }
271373
@@ -279,53 +381,53 @@ <h3>Alienware AW3423DWF</h3>
279381
280382 function onStart ( x , y , target ) {
281383 // Ignore clicks on links/buttons
282- if ( target . closest ( 'a' ) || target . closest ( 'button' ) ) return ;
384+ if ( target . closest ( 'a' ) || target . closest ( 'button' ) ) return ;
283385 isDragging = true ;
284386 startX = x ;
285387 currentX = x ;
286388 // Remove transition visually to make dragging instantaneous
287389 cards [ topIndex ] . style . transition = 'none' ;
288-
289- if ( hint ) hint . style . display = 'none' ;
390+
391+ if ( hint ) hint . style . display = 'none' ;
290392 }
291393
292394 function onMove ( x ) {
293- if ( ! isDragging ) return ;
395+ if ( ! isDragging ) return ;
294396 currentX = x ;
295397 const diffX = currentX - startX ;
296- const rotate = diffX * 0.05 ;
398+ const rotate = diffX * 0.05 ;
297399 // Instantly update transform
298400 cards [ topIndex ] . style . transform = `translateZ(0) translateY(0) translateX(${ diffX } px) rotate(${ rotate } deg)` ;
299401 }
300402
301403 function onEnd ( ) {
302- if ( ! isDragging ) return ;
404+ if ( ! isDragging ) return ;
303405 isDragging = false ;
304406 const diffX = currentX - startX ;
305-
306- if ( Math . abs ( diffX ) > 80 ) { // threshold passed
307- throwCard ( diffX < 0 ? 'left' : 'right' ) ;
407+
408+ if ( Math . abs ( diffX ) > 80 ) { // threshold passed
409+ throwCard ( diffX < 0 ? 'left' : 'right' ) ;
308410 } else {
309- // return to center smoothly
310- updateDeck ( ) ;
411+ // return to center smoothly
412+ updateDeck ( ) ;
311413 }
312414 }
313415
314416 deck . addEventListener ( 'mousedown' , ( e ) => onStart ( e . clientX , e . clientY , e . target ) ) ;
315417 window . addEventListener ( 'mousemove' , ( e ) => onMove ( e . clientX ) ) ;
316418 window . addEventListener ( 'mouseup' , onEnd ) ;
317-
318- deck . addEventListener ( 'touchstart' , ( e ) => onStart ( e . touches [ 0 ] . clientX , e . touches [ 0 ] . clientY , e . target ) , { passive : false } ) ;
419+
420+ deck . addEventListener ( 'touchstart' , ( e ) => onStart ( e . touches [ 0 ] . clientX , e . touches [ 0 ] . clientY , e . target ) , { passive : false } ) ;
319421 deck . addEventListener ( 'touchmove' , ( e ) => {
320- if ( isDragging ) { e . preventDefault ( ) ; onMove ( e . touches [ 0 ] . clientX ) ; }
321- } , { passive : false } ) ;
422+ if ( isDragging ) { e . preventDefault ( ) ; onMove ( e . touches [ 0 ] . clientX ) ; }
423+ } , { passive : false } ) ;
322424 deck . addEventListener ( 'touchend' , onEnd ) ;
323425
324426 // Init
325427 updateDeck ( ) ;
326-
428+
327429 // Show hint briefly on load
328- setTimeout ( ( ) => { if ( hint ) hint . style . opacity = '1' ; } , 1500 ) ;
430+ setTimeout ( ( ) => { if ( hint ) hint . style . opacity = '1' ; } , 1500 ) ;
329431 } ) ;
330432 </ script >
331433 </ div >
0 commit comments