11<!DOCTYPE html>
22< html lang ="en ">
33< head >
4+ < script > fetch ( 'https://api.countapi.xyz/hit/rmkr-dev.github.io/time' ) ; </ script >
45 < meta charset ="UTF-8 ">
56 < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
67 < title > Time Zone Overlay | RMKR Dev</ title >
1718 --color-accent : # FFC300 ; --color-text : # F0F4F8 ;
1819 --color-muted : # A0AEC0 ; --color-line : # 2D3748 ;
1920 }
20- body { font-family : 'Inter' , sans-serif; background-color : var (--color-bg ); color : var (--color-text ); }
21- .wrap { max-width : 1000 px ; margin : 0 auto; padding : 2rem ; }
21+ body { font-family : 'Inter' , sans-serif; background-color : var (--color-bg ); color : var (--color-text ); overflow-x : hidden; }
22+ .wrap { max-width : 1100 px ; margin : 0 auto; padding : 2rem ; }
2223
2324 .timeline-row {
2425 background : var (--color-card );
2526 border : 1px solid var (--color-line );
2627 border-radius : 12px ;
27- padding : 1.5rem ;
28- margin-bottom : 1rem ;
29- position : relative;
28+ padding : 1.25rem ;
29+ margin-bottom : 0.75rem ;
30+ }
31+
32+ /* The scrollable grid container */
33+ .grid-container {
34+ overflow-x : auto;
35+ padding-bottom : 8px ;
36+ scrollbar-width : thin;
37+ scrollbar-color : var (--color-line ) transparent;
3038 }
3139
3240 .hour-grid {
3341 display : grid;
34- grid-template-columns : repeat (24 , 1fr );
35- gap : 2 px ;
42+ grid-template-columns : repeat (24 , minmax ( 40 px , 1fr ) );
43+ gap : 4 px ;
3644 margin-top : 10px ;
45+ min-width : 960px ; /* Ensures cells don't get too squished */
3746 }
3847
3948 .hour-cell {
40- height : 30px ;
41- background : rgba (255 , 255 , 255 , 0.05 );
42- border-radius : 4px ;
49+ height : 45px ;
50+ background : rgba (255 , 255 , 255 , 0.03 );
51+ border : 1px solid rgba (255 , 255 , 255 , 0.05 );
52+ border-radius : 6px ;
4353 display : flex;
54+ flex-direction : column;
4455 align-items : center;
4556 justify-content : center;
46- font-size : 0.65 rem ;
57+ font-size : 0.7 rem ;
4758 color : var (--color-muted );
4859 cursor : pointer;
4960 transition : all 0.2s ;
5061 }
5162
52- .hour-cell : hover { background : rgba (255 , 195 , 0 , 0.2 ); }
53- .hour-cell .active { background : var (--color-accent ); color : var (--color-bg ); font-weight : bold; }
54- .hour-cell .business { border-bottom : 2px solid # 4ade80 ; } /* Simple indicator for 9-5 */
63+ .hour-cell : hover { background : rgba (255 , 195 , 0 , 0.15 ); border-color : var (--color-accent ); }
64+ .hour-cell .active { background : var (--color-accent ) !important ; color : var (--color-bg ) !important ; font-weight : 800 ; border-color : var (--color-accent ); transform : scale (1.05 ); z-index : 2 ; }
65+ .hour-cell .business { border-bottom : 3px solid # 4ade80 ; }
66+ .hour-cell .night { background : rgba (0 , 0 , 0 , 0.2 ); }
67+
68+ .ampm { font-size : 0.55rem ; opacity : 0.7 ; }
5569
5670 select {
5771 background : # 0C1524 ; color : white; border : 1px solid var (--color-line );
58- padding : 4 px 8px ; border-radius : 6px ; font-size : 0.8 rem ;
72+ padding : 8px 12 px ; border-radius : 6px ; font-size : 0.85 rem ; outline : none ;
5973 }
6074
61- .btn-gold { background : var (--color-accent ); color : var (--color-bg ); padding : 0.5rem 1rem ; border-radius : 6px ; font-weight : bold; font-size : 0.8rem ; }
75+ .btn-gold { background : var (--color-accent ); color : var (--color-bg ); padding : 0.5rem 1.25rem ; border-radius : 6px ; font-weight : 700 ; transition : all 0.2s ; }
76+ .btn-gold : hover { opacity : 0.9 ; transform : translateY (-1px ); }
6277 </ style >
6378</ head >
6479< body >
6580
6681< div class ="wrap ">
6782 < header class ="flex justify-between items-center mb-8 border-b border-[--color-line] pb-4 ">
6883 < div >
69- < h1 class ="text-2xl font-bold "> Time Overlay < span class ="text-[--color-accent] "> Comparison </ span > </ h1 >
70- < p class ="text-sm text-[--color-muted] " > Compare time across regions with DST support. </ p >
84+ < h1 class ="text-2xl font-bold tracking-tight "> Time < span class ="text-[--color-accent] "> Sync </ span > Overlay </ h1 >
85+ < p class ="text-xs text-[--color-muted] mt-1 uppercase tracking-widest " > Global Meeting Planner </ p >
7186 </ div >
72- < a href ="../ " class ="text-sm font-bold text-[--color-accent] hover:underline "> < i class ="fa-solid fa-house mr-1 "> </ i > Hub</ a >
87+ < a href ="../ " class ="text-sm font-bold text-[--color-accent] border border-[--color-accent] px-3 py-1 rounded hover:bg-[--color-accent] hover:text-[--color-bg] transition-all "> < i class ="fa-solid fa-house mr-1 "> </ i > Hub</ a >
7388 </ header >
7489
75- < div class ="flex flex-wrap gap-4 mb-8 items-center bg-[#18233C] p-4 rounded-xl ">
90+ < div class ="flex flex-wrap gap-4 mb-6 items-center bg-[#18233C] p-5 rounded-2xl border border-[--color-line] ">
7691 < div class ="flex flex-col ">
77- < label class ="text-[10px] uppercase font-bold text-muted mb-1 "> Add Timezone</ label >
78- < select id ="tz-selector " class ="w-64 ">
79- < option value ="UTC "> UTC (Universal)</ option >
80- < option value ="America/New_York "> New York (EST/EDT)</ option >
81- < option value ="Europe/London "> London (GMT/BST)</ option >
82- < option value ="Asia/Kolkata "> India (IST)</ option >
83- < option value ="Asia/Singapore "> Singapore / SGT</ option >
84- < option value ="America/Los_Angeles "> Pacific Time (PST/PDT)</ option >
85- < option value ="Europe/Berlin "> Berlin / CET</ option >
86- < option value ="Australia/Sydney "> Sydney / AEDT</ option >
87- </ select >
92+ < label class ="text-[10px] uppercase font-bold text-[--color-muted] mb-2 ml-1 "> Add Location</ label >
93+ < div class ="flex gap-2 ">
94+ < select id ="tz-selector " class ="w-64 ">
95+ < option value ="UTC "> UTC (Universal Time)</ option >
96+ < option value ="Asia/Kolkata "> India (IST)</ option >
97+ < option value ="America/New_York "> New York (EST/EDT)</ option >
98+ < option value ="Europe/London "> London (GMT/BST)</ option >
99+ < option value ="Asia/Singapore "> Singapore (SGT)</ option >
100+ < option value ="America/Los_Angeles "> Pacific Time (PST/PDT)</ option >
101+ < option value ="Europe/Berlin "> Berlin (CET/CEST)</ option >
102+ < option value ="Australia/Sydney "> Sydney (AEST/AEDT)</ option >
103+ < option value ="Asia/Dubai "> Dubai (GST)</ option >
104+ < option value ="Asia/Tokyo "> Tokyo (JST)</ option >
105+ </ select >
106+ < button onclick ="addTimezone() " class ="btn-gold "> Add</ button >
107+ </ div >
88108 </ div >
89- < button onclick ="addTimezone() " class ="btn-gold self-end ">
90- < i class ="fa-solid fa-plus mr-1 "> </ i > Add
91- </ button >
92- < div class ="ml-auto text-right ">
93- < p class ="text-[10px] uppercase font-bold text-muted "> Current System Time</ p >
94- < p id ="local-clock " class ="text-xl font-mono text-[--color-accent] "> 00:00:00</ p >
109+
110+ < div class ="ml-auto text-right bg-[#0C1524] px-4 py-2 rounded-lg border border-[--color-line] ">
111+ < p class ="text-[9px] uppercase font-bold text-[--color-muted] "> Your System Time</ p >
112+ < p id ="local-clock " class ="text-lg font-mono text-[--color-accent] font-bold "> 00:00:00</ p >
95113 </ div >
96114 </ div >
97115
98- < div id ="timelines-root ">
99- </ div >
116+ < div id ="timelines-root "> </ div >
117+
118+ < footer class ="mt-8 text-center text-[10px] text-[--color-muted] uppercase tracking-widest opacity-50 ">
119+ WorldTimeBuddy Logic — DST Inclusive — Client-Side Only
120+ </ footer >
100121</ div >
101122
102123< script >
103124 // Configuration
104- let selectedHour = new Date ( ) . getHours ( ) ;
105- let timezones = [ 'UTC' ] ; // Default start
106-
107- // Auto-detect local timezone and add it if not UTC
125+ // We use a "Global Reference Hour" in UTC (0-23) to sync everything
126+ let globalRefUtcHour = new Date ( ) . getUTCHours ( ) ;
127+ let timezones = [ ] ;
128+
129+ // Initialize with Local and UTC
108130 const localTZ = Intl . DateTimeFormat ( ) . resolvedOptions ( ) . timeZone ;
109- if ( localTZ !== 'UTC' ) timezones . unshift ( localTZ ) ;
131+ timezones . push ( localTZ ) ;
132+ if ( localTZ !== 'UTC' ) timezones . push ( 'UTC' ) ;
110133
111134 function updateClocks ( ) {
112135 const now = new Date ( ) ;
113- document . getElementById ( 'local-clock' ) . innerText = now . toLocaleTimeString ( ) ;
136+ document . getElementById ( 'local-clock' ) . innerText = now . toLocaleTimeString ( [ ] , { hour12 : true } ) ;
114137 }
115138
116139 function addTimezone ( ) {
@@ -127,50 +150,68 @@ <h1 class="text-2xl font-bold">Time Overlay <span class="text-[--color-accent]">
127150 render ( ) ;
128151 }
129152
153+ function selectHour ( utcHour ) {
154+ globalRefUtcHour = utcHour ;
155+ render ( ) ;
156+ }
157+
130158 function render ( ) {
131159 const root = document . getElementById ( 'timelines-root' ) ;
132160 root . innerHTML = '' ;
133161
134- timezones . forEach ( ( tz , index ) => {
162+ timezones . forEach ( ( tz , tzIndex ) => {
135163 const row = document . createElement ( 'div' ) ;
136- row . className = 'timeline-row' ;
137-
138- // Get current time in this specific timezone
164+ row . className = 'timeline-row animate-in fade-in duration-500 ' ;
165+
166+ // Get current time info for the header
139167 const now = new Date ( ) ;
140- const formatter = new Intl . DateTimeFormat ( 'en-US' , {
141- timeZone : tz ,
142- hour : 'numeric' ,
143- minute : 'numeric' ,
144- hour12 : true ,
145- weekday : 'short'
146- } ) ;
147- const parts = formatter . formatToParts ( now ) ;
148- const timeStr = formatter . format ( now ) ;
149-
168+ const timeStr = now . toLocaleTimeString ( 'en-US' , { timeZone : tz , hour : 'numeric' , minute : '2-digit' , hour12 : true } ) ;
169+ const dateStr = now . toLocaleDateString ( 'en-US' , { timeZone : tz , weekday : 'short' , month : 'short' , day : 'numeric' } ) ;
170+
150171 row . innerHTML = `
151- <div class="flex justify-between items-center mb-2 ">
152- <div>
153- <span class="font-bold text-[--color-accent]">${ tz . split ( '/' ) . pop ( ) . replace ( '_' , ' ' ) } </span>
154- <span class="text-xs text-[--color-muted] ml-2 ">${ tz } </span>
172+ <div class="flex justify-between items-end mb-3 ">
173+ <div class="flex items-baseline gap-2" >
174+ <span class="font-bold text-lg text- [--color-accent] leading-none ">${ tz . split ( '/' ) . pop ( ) . replace ( '_' , ' ' ) } </span>
175+ <span class="text-[10px] font-mono text-[--color-muted] uppercase opacity-60 ">${ tz } </span>
155176 </div>
156- <div class="flex items-center gap-4 ">
157- <span class="font-mono text-sm ">${ timeStr } </span>
158- ${ index !== 0 ? `<button onclick="removeTimezone( ${ index } )" class="text-red-400 hover: text-red-300 text-xs"><i class="fa-solid fa-trash"></i></button>` : '' }
177+ <div class="text-right ">
178+ <span class="text-xs font-bold text-white block ">${ timeStr } </span>
179+ <span class="text-[9px] text-[--color-muted] uppercase font-medium"> ${ dateStr } </span>
159180 </div>
181+ ${ tzIndex > 0 ? `<button onclick="removeTimezone(${ tzIndex } )" class="ml-4 text-[--color-line] hover:text-red-400 transition-colors"><i class="fa-solid fa-circle-minus"></i></button>` : '' }
182+ </div>
183+ <div class="grid-container">
184+ <div class="hour-grid" id="grid-${ tzIndex } "></div>
160185 </div>
161- <div class="hour-grid" id="grid-${ index } "></div>
162186 ` ;
163187 root . appendChild ( row ) ;
164188
165- // Generate 24-hour strip
166- const grid = document . getElementById ( `grid-${ index } ` ) ;
167- for ( let h = 0 ; h < 24 ; h ++ ) {
189+ const grid = document . getElementById ( `grid-${ tzIndex } ` ) ;
190+
191+ // Logic: We always render 24 blocks.
192+ // The "spine" is UTC. We calculate what hour in THIS timezone corresponds to UTC 0 to 23.
193+ for ( let utcHour = 0 ; utcHour < 24 ; utcHour ++ ) {
194+ // Create a date object set to Today at utcHour:00 UTC
195+ const refDate = new Date ( ) ;
196+ refDate . setUTCHours ( utcHour , 0 , 0 , 0 ) ;
197+
198+ // Convert that specific UTC moment to the target timezone's hour
199+ const tzHourStr = refDate . toLocaleTimeString ( 'en-US' , { timeZone : tz , hour : 'numeric' , hour12 : false } ) ;
200+ const tzHour = parseInt ( tzHourStr ) ;
201+ const isAMPM = refDate . toLocaleTimeString ( 'en-US' , { timeZone : tz , hour : 'numeric' , hour12 : true } ) ;
202+
168203 const cell = document . createElement ( 'div' ) ;
169- cell . className = `hour-cell ${ h >= 9 && h <= 18 ? 'business' : '' } ${ h === selectedHour && index === 0 ? 'active' : '' } ` ;
204+ const isBusiness = tzHour >= 9 && tzHour <= 18 ;
205+ const isNight = tzHour < 6 || tzHour >= 22 ;
206+ const isActive = utcHour === globalRefUtcHour ;
207+
208+ cell . className = `hour-cell ${ isBusiness ? 'business' : '' } ${ isNight ? 'night' : '' } ${ isActive ? 'active' : '' } ` ;
209+
210+ // Format display (e.g., "12 AM" or "5 PM")
211+ const [ hPart , ampmPart ] = isAMPM . split ( ' ' ) ;
212+ cell . innerHTML = `<span>${ hPart } </span><span class="ampm">${ ampmPart } </span>` ;
170213
171- // Calculate what time 'h' in local translates to in 'tz'
172- // This is the core logic for the "WorldTimeBuddy" overlay
173- cell . innerText = h ;
214+ cell . onclick = ( ) => selectHour ( utcHour ) ;
174215 grid . appendChild ( cell ) ;
175216 }
176217 } ) ;
0 commit comments