1
+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
2
+ // --- Elements ---
3
+ const profilePicButton = document . getElementById ( 'profilePicButton' ) ;
4
+ const imagePopup = document . getElementById ( 'imagePopup' ) ;
5
+ const closePopupButton = document . getElementById ( 'closePopup' ) ;
6
+ const currentYearSpan = document . getElementById ( 'current-year' ) ;
7
+ const links = document . querySelectorAll ( '.link-item' ) ; // Get all link items
8
+
9
+ // --- Popup Logic ---
10
+ const openPopup = ( ) => {
11
+ if ( imagePopup && closePopupButton ) {
12
+ imagePopup . classList . add ( 'visible' ) ;
13
+ imagePopup . setAttribute ( 'aria-hidden' , 'false' ) ;
14
+ // Delay focus slightly to allow transition to start
15
+ setTimeout ( ( ) => closePopupButton . focus ( ) , 50 ) ;
16
+ }
17
+ } ;
18
+
19
+ const closePopup = ( ) => {
20
+ if ( imagePopup && profilePicButton ) {
21
+ imagePopup . classList . remove ( 'visible' ) ;
22
+ imagePopup . setAttribute ( 'aria-hidden' , 'true' ) ;
23
+ profilePicButton . focus ( ) ; // Return focus to the button that opened it
24
+ }
25
+ } ;
26
+
27
+ // --- Event Listeners ---
28
+
29
+ // Open popup
30
+ if ( profilePicButton ) {
31
+ profilePicButton . addEventListener ( 'click' , openPopup ) ;
32
+ }
33
+
34
+ // Close popup with button
35
+ if ( closePopupButton ) {
36
+ closePopupButton . addEventListener ( 'click' , closePopup ) ;
37
+ }
38
+
39
+ // Close popup clicking overlay
40
+ if ( imagePopup ) {
41
+ imagePopup . addEventListener ( 'click' , ( event ) => {
42
+ // Only close if the click is directly on the overlay
43
+ if ( event . target === imagePopup ) {
44
+ closePopup ( ) ;
45
+ }
46
+ } ) ;
47
+ }
48
+
49
+ // Close popup with Escape key
50
+ document . addEventListener ( 'keydown' , ( event ) => {
51
+ if ( event . key === 'Escape' && imagePopup ?. classList . contains ( 'visible' ) ) {
52
+ closePopup ( ) ;
53
+ }
54
+ } ) ;
55
+
56
+ // --- Footer Year ---
57
+ if ( currentYearSpan ) {
58
+ currentYearSpan . textContent = new Date ( ) . getFullYear ( ) ;
59
+ }
60
+
61
+ // --- Staggered Link Animation on Load ---
62
+ if ( links . length > 0 ) {
63
+ links . forEach ( ( link , index ) => {
64
+ // Calculate delay based on index
65
+ const delay = index * 75 + 200 ; // Base delay + stagger (in milliseconds)
66
+ link . style . transition = `opacity 0.4s ease-out ${ delay } ms, transform 0.4s ease-out ${ delay } ms` ;
67
+
68
+ // Trigger reflow/repaint to apply initial styles before setting final styles
69
+ // Using requestAnimationFrame for better performance/reliability than offsetWidth
70
+ requestAnimationFrame ( ( ) => {
71
+ link . style . opacity = '1' ;
72
+ link . style . transform = 'translateY(0)' ;
73
+ } ) ;
74
+ } ) ;
75
+ }
76
+
77
+ } ) ; // End DOMContentLoaded
0 commit comments