192192 color : var ( --primary ) ;
193193 }
194194
195+ . nav-links a . active {
196+ color : var ( --primary ) ;
197+ font-weight : 700 ;
198+ }
199+
200+ . hero-stats {
201+ display : inline-flex;
202+ gap : 24px ;
203+ margin-top : 24px ;
204+ border-top : 1px solid var ( --outline-variant ) ;
205+ padding-top : 24px ;
206+ }
207+
208+ . hero-stat {
209+ display : flex;
210+ flex-direction : column;
211+ }
212+
213+ . hero-stat strong {
214+ font-size : 1.4rem ;
215+ color : var ( --primary ) ;
216+ }
217+
218+ . hero-stat span {
219+ font-size : 0.75rem ;
220+ color : var ( --on-surface-variant ) ;
221+ text-transform : uppercase;
222+ letter-spacing : 0.5px ;
223+ }
224+
195225 . header-download {
196226 background : var ( --primary ) ;
197227 border-radius : var ( --radius ) ;
572602
573603 . download-select {
574604 appearance : none;
575- background : var ( --surface ) ;
605+ background : var ( --surface ) url ( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2372777F'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E" ) no-repeat right 12px center;
606+ background-size : 18px ;
576607 border : 1px solid var ( --outline-variant ) ;
577608 border-radius : var ( --radius ) ;
578609 color : var ( --on-background ) ;
579610 margin-bottom : 12px ;
580611 min-height : 46px ;
581- padding : 10px 12px ;
612+ padding : 10px 38 px 10 px 12px ;
582613 width : 100% ;
583614 }
584615
863894 < a href ="#screenshots "> Screenshots</ a >
864895 < a href ="#download "> Download</ a >
865896 < a href ="#privacy "> Privacy</ a >
866- < a href ="https://github.com/Coding-Meet/DevAnalyzer " rel ="noopener noreferrer "
867- target ="_blank "> GitHub</ a >
868897 </ div >
869898 < a class ="button header-download " href ="#download "> Download</ a >
870899 </ nav >
@@ -906,6 +935,16 @@ <h1>DevAnalyzer</h1>
906935 < span class ="chip "> Windows, macOS, Linux</ span >
907936 < span class ="chip "> Android & Kotlin Projects</ span >
908937 </ div >
938+ < div class ="hero-stats ">
939+ < div class ="hero-stat ">
940+ < strong data-stat ="stars "> Loading</ strong >
941+ < span > GitHub Stars</ span >
942+ </ div >
943+ < div class ="hero-stat ">
944+ < strong data-stat ="downloads "> Loading</ strong >
945+ < span > Total Downloads</ span >
946+ </ div >
947+ </ div >
909948 </ div >
910949 < div class ="showcase animate-right " aria-label ="DevAnalyzer interface preview ">
911950 < div class ="window-frame ">
@@ -1130,19 +1169,30 @@ <h2>Get the installer made for your system.</h2>
11301169 < h2 > Private by default.</ h2 >
11311170 < p > DevAnalyzer is designed to inspect development folders, project metadata, and toolchain paths locally.</ p >
11321171 </ div >
1133- < div class ="privacy-list ">
1134- < article class ="privacy-item ">
1135- < h3 > Local processing</ h3 >
1136- < p > Project analysis and storage scans run on your machine.</ p >
1137- </ article >
1138- < article class ="privacy-item ">
1139- < h3 > Optional diagnostics</ h3 >
1140- < p > Crash reporting and usage analytics can be managed from the app settings.</ p >
1141- </ article >
1142- < article class ="privacy-item ">
1143- < h3 > No project upload</ h3 >
1144- < p > Source code, project names, and file paths are never uploaded or sent to remote servers.</ p >
1145- </ article >
1172+ < div class ="gallery ">
1173+ < div class ="privacy-list " style ="grid-template-columns: 1fr; ">
1174+ < article class ="privacy-item ">
1175+ < h3 > Local processing</ h3 >
1176+ < p > Project analysis and storage scans run on your machine.</ p >
1177+ </ article >
1178+ < article class ="privacy-item ">
1179+ < h3 > Optional diagnostics</ h3 >
1180+ < p > Crash reporting and usage analytics can be managed from the app settings.</ p >
1181+ </ article >
1182+ < article class ="privacy-item ">
1183+ < h3 > No project upload</ h3 >
1184+ < p > Source code, project names, and file paths are never uploaded or sent to remote servers.</ p >
1185+ </ article >
1186+ </ div >
1187+ < div class ="window-frame " style ="align-self: start; ">
1188+ < div class ="window-bar ">
1189+ < span class ="dot "> </ span >
1190+ < span class ="dot "> </ span >
1191+ < span class ="dot "> </ span >
1192+ </ div >
1193+ < img alt ="DevAnalyzer privacy settings and diagnostics switches "
1194+ src ="screenshot/setting/img_2_diagnostics_section_all_feature_switch_crash_analytics.png ">
1195+ </ div >
11461196 </ div >
11471197 </ div >
11481198 </ section >
@@ -1260,9 +1310,9 @@ <h3>No project upload</h3>
12601310
12611311 const meta = document . querySelector ( "[data-release-meta]" ) ;
12621312 if ( asset ) {
1263- meta . textContent = `${ asset . name } selected from the latest GitHub release.` ;
1313+ if ( meta ) meta . textContent = `${ asset . name } selected from the latest GitHub release.` ;
12641314 } else {
1265- meta . textContent = "Could not match a release asset. The button opens the GitHub releases page." ;
1315+ if ( meta ) meta . textContent = "Could not match a release asset. The button opens the GitHub releases page." ;
12661316 }
12671317 }
12681318
@@ -1277,25 +1327,32 @@ <h3>No project upload</h3>
12771327 if ( repoResponse . ok ) {
12781328 const repo = await repoResponse . json ( ) ;
12791329 state . stars = repo . stargazers_count ;
1280- document . querySelector ( "[data-stat='stars']" ) . textContent = formatNumber ( state . stars ) ;
1330+ document . querySelectorAll ( "[data-stat='stars']" ) . forEach ( el => {
1331+ el . textContent = formatNumber ( state . stars ) ;
1332+ } ) ;
12811333 }
12821334
12831335 if ( latestResponse . ok ) {
12841336 const latest = await latestResponse . json ( ) ;
12851337 state . version = cleanVersion ( latest . tag_name || latest . name ) ;
12861338 state . assets = Array . isArray ( latest . assets ) ? latest . assets : [ ] ;
1287- document . querySelector ( "[data-stat='version']" ) . textContent = state . version || "Latest" ;
1339+ document . querySelectorAll ( "[data-stat='version']" ) . forEach ( el => {
1340+ el . textContent = state . version || "Latest" ;
1341+ } ) ;
12881342 }
12891343
12901344 if ( releasesResponse . ok ) {
12911345 const releases = await releasesResponse . json ( ) ;
12921346 state . downloads = releases . reduce ( ( total , release ) => {
12931347 return total + ( release . assets || [ ] ) . reduce ( ( sum , asset ) => sum + ( asset . download_count || 0 ) , 0 ) ;
12941348 } , 0 ) ;
1295- document . querySelector ( "[data-stat='downloads']" ) . textContent = formatNumber ( state . downloads ) ;
1349+ document . querySelectorAll ( "[data-stat='downloads']" ) . forEach ( el => {
1350+ el . textContent = formatNumber ( state . downloads ) ;
1351+ } ) ;
12961352 }
12971353 } catch ( error ) {
1298- document . querySelector ( "[data-release-meta]" ) . textContent = "GitHub release data is unavailable right now. The button opens the releases page." ;
1354+ const meta = document . querySelector ( "[data-release-meta]" ) ;
1355+ if ( meta ) meta . textContent = "GitHub release data is unavailable right now. The button opens the releases page." ;
12991356 } finally {
13001357 updateDownloadUi ( ) ;
13011358 }
@@ -1316,12 +1373,14 @@ <h3>No project upload</h3>
13161373
13171374 async function initDownloads ( ) {
13181375 const select = document . querySelector ( "#installer-select" ) ;
1376+ if ( ! select ) return ;
13191377 state . selected = await detectInstaller ( ) ;
13201378 select . value = state . selected ;
1321- document . querySelector ( "[data-detected-os]" ) . textContent = `Detected: ${ installers [ state . selected ] . detect } ` ;
1379+ const detectedOs = document . querySelector ( "[data-detected-os]" ) ;
1380+ if ( detectedOs ) detectedOs . textContent = `Detected: ${ installers [ state . selected ] . detect } ` ;
13221381 select . addEventListener ( "change" , ( ) => {
13231382 state . selected = select . value ;
1324- document . querySelector ( "[data-detected-os]" ) . textContent = `Selected: ${ installers [ state . selected ] . detect } ` ;
1383+ if ( detectedOs ) detectedOs . textContent = `Selected: ${ installers [ state . selected ] . detect } ` ;
13251384 updateDownloadUi ( ) ;
13261385 } ) ;
13271386 await loadReleaseData ( ) ;
@@ -1360,10 +1419,32 @@ <h3>No project upload</h3>
13601419 document . querySelectorAll ( ".reveal" ) . forEach ( el => observer . observe ( el ) ) ;
13611420 }
13621421
1422+ function initScrollSpy ( ) {
1423+ const links = document . querySelectorAll ( ".nav-links a[href^='#']" ) ;
1424+ const sections = Array . from ( links ) . map ( link => document . querySelector ( link . getAttribute ( "href" ) ) ) ;
1425+
1426+ window . addEventListener ( "scroll" , ( ) => {
1427+ let current = "" ;
1428+ const scrollPos = window . scrollY + 120 ;
1429+
1430+ sections . forEach ( section => {
1431+ if ( section && scrollPos >= section . offsetTop ) {
1432+ current = section . getAttribute ( "id" ) ;
1433+ }
1434+ } ) ;
1435+
1436+ links . forEach ( link => {
1437+ link . classList . toggle ( "active" , link . getAttribute ( "href" ) === `#${ current } ` ) ;
1438+ } ) ;
1439+ } ) ;
1440+ }
1441+
13631442 document . addEventListener ( "DOMContentLoaded" , ( ) => {
13641443 initGallery ( ) ;
13651444 initDownloads ( ) ;
13661445 initReveal ( ) ;
1446+ initScrollSpy ( ) ;
1447+ loadReleaseData ( ) ;
13671448 } ) ;
13681449</ script >
13691450</ body >
0 commit comments