@networkpro/web 1.6.3 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CODE_OF_CONDUCT.md +2 -2
  2. package/LICENSE.md +20 -9
  3. package/README.md +21 -19
  4. package/_redirects +1 -0
  5. package/cspell.json +2 -0
  6. package/package.json +5 -6
  7. package/playwright.config.js +1 -0
  8. package/scripts/bundleCss.js +2 -2
  9. package/src/app.html +18 -1
  10. package/src/hooks.server.js +42 -45
  11. package/src/lib/components/FullWidthSection.svelte +19 -4
  12. package/src/lib/components/LegalNav.svelte +31 -29
  13. package/src/lib/components/PostHog.svelte +20 -8
  14. package/src/lib/components/layout/Footer.svelte +1 -1
  15. package/src/lib/components/layout/HeaderDefault.svelte +2 -2
  16. package/src/lib/components/layout/HeaderHome.svelte +2 -2
  17. package/src/lib/images.js +3 -2
  18. package/src/lib/img/logo-web.png +0 -0
  19. package/src/lib/img/logo-web.webp +0 -0
  20. package/src/lib/index.js +2 -1
  21. package/src/lib/meta.js +6 -1
  22. package/src/lib/pages/AboutContent.svelte +4 -5
  23. package/src/lib/pages/HomeContent.svelte +1 -1
  24. package/src/lib/pages/LicenseContent.svelte +19 -20
  25. package/src/lib/pages/PrivacyContent.svelte +149 -6
  26. package/src/lib/pages/PrivacyDashboard.svelte +240 -0
  27. package/src/lib/pages/TermsConditionsContent.svelte +1 -1
  28. package/src/lib/pages/TermsUseContent.svelte +3 -4
  29. package/src/lib/styles/css/default.css +32 -11
  30. package/src/lib/styles/css/normalize.css +2 -2
  31. package/src/lib/styles/css/style.css +2 -2
  32. package/src/lib/styles/global.min.css +2 -6
  33. package/src/lib/utils/privacy.js +38 -0
  34. package/src/lib/utils/trackingCookies.js +40 -0
  35. package/src/lib/utils/trackingStatus.js +46 -0
  36. package/src/lib/utils/utm.js +8 -1
  37. package/src/routes/+layout.svelte +25 -12
  38. package/src/routes/about/+page.svelte +1 -7
  39. package/src/routes/foss-spotlight/+page.svelte +1 -7
  40. package/src/routes/license/+page.svelte +2 -8
  41. package/src/routes/privacy/+page.server.js +18 -0
  42. package/src/routes/{privacy-policy → privacy}/+page.svelte +5 -11
  43. package/src/routes/{privacy-policy → privacy-dashboard}/+page.server.js +2 -2
  44. package/src/routes/privacy-dashboard/+page.svelte +69 -0
  45. package/src/routes/terms-conditions/+page.svelte +2 -8
  46. package/src/routes/terms-of-use/+page.svelte +2 -8
  47. package/src/service-worker.js +31 -6
  48. package/static/sitemap.xml +10 -22
  49. package/tests/e2e/app.spec.js +21 -63
@@ -1,4 +1,4 @@
1
- /*! ==========================================================================
1
+ /* ==========================================================================
2
2
  src/lib/styles/default.css
3
3
 
4
4
  Copyright © 2025 Network Pro Strategies (Network Pro™)
@@ -26,6 +26,12 @@ This file is part of Network Pro.
26
26
  max-width: 1200px;
27
27
  }
28
28
 
29
+ /* Constrain paragraph/text-heavy content to 900px */
30
+ .readable {
31
+ margin: 0 auto;
32
+ max-width: 900px;
33
+ }
34
+
29
35
  /* Header & Footer follow the same container width */
30
36
  header,
31
37
  footer {
@@ -168,26 +174,21 @@ footer .container {
168
174
 
169
175
  .bnav {
170
176
  margin: 0 auto;
177
+ text-align: center;
171
178
  border-collapse: collapse;
172
179
  border-spacing: 0;
173
180
  }
174
181
 
175
- .bnav td {
176
- padding: 10px;
177
- font-size: 0.875rem;
178
- font-weight: bold;
179
- line-height: 1.125rem;
180
- border-style: none;
181
- overflow: hidden;
182
- word-break: normal;
183
- }
184
-
182
+ .bnav td,
185
183
  .bnav th {
186
184
  padding: 10px;
187
185
  font-size: 0.875rem;
186
+ font-weight: bold; /* Only needed for <td>, if desired */
188
187
  line-height: 1.125rem;
188
+ text-align: center; /* Center horizontally */
189
189
  border-style: none;
190
190
  overflow: hidden;
191
+ vertical-align: middle; /* Center vertically */
191
192
  word-break: normal;
192
193
  }
193
194
 
@@ -362,6 +363,14 @@ footer .container {
362
363
  text-align: center;
363
364
  }
364
365
 
366
+ .index4 {
367
+ font-size: 1.5rem;
368
+ line-height: 1.75rem;
369
+ letter-spacing: -0.035em;
370
+ text-align: center;
371
+ text-decoration: underline;
372
+ }
373
+
365
374
  .subhead {
366
375
  font-size: 1.5rem;
367
376
  line-height: 1.75rem;
@@ -369,6 +378,18 @@ footer .container {
369
378
  font-variant: small-caps;
370
379
  }
371
380
 
381
+ .bold {
382
+ font-weight: bold;
383
+ }
384
+
385
+ .emphasis {
386
+ font-style: italic;
387
+ }
388
+
389
+ .uline {
390
+ text-decoration: underline;
391
+ }
392
+
372
393
  .bolditalic {
373
394
  font-weight: bold;
374
395
  font-style: italic;
@@ -1,10 +1,10 @@
1
- /*! ==========================================================================
1
+ /* ==========================================================================
2
2
  src/lib/styles/normalize.css
3
3
 
4
4
  Copyright © 2025 Network Pro Strategies (Network Pro™)
5
5
  SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
6
  This file is part of Network Pro.
7
- =========================================================================== */
7
+ ========================================================================== */
8
8
 
9
9
  /*! Modified from normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
10
10
 
@@ -1,10 +1,10 @@
1
- /*! ==========================================================================
1
+ /* ==========================================================================
2
2
  src/lib/styles/style.css
3
3
 
4
4
  Copyright © 2025 Network Pro Strategies (Network Pro™)
5
5
  SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
6
  This file is part of Network Pro.
7
- =========================================================================== */
7
+ ========================================================================== */
8
8
 
9
9
  /*! Modified from HTML5 Boilerplate v9.0.1 | MIT License | https://html5boilerplate.com/ */
10
10
 
@@ -1,10 +1,6 @@
1
1
  /*! ==========================================================================
2
- src/lib/styles/global.min.css
3
-
4
2
  Copyright © 2025 Network Pro Strategies (Network Pro™)
5
3
  SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
4
  This file is part of Network Pro.
7
- =========================================================================== */
8
- /*! Modified from normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
9
- /*! Modified from HTML5 Boilerplate v9.0.1 | MIT License | https://html5boilerplate.com/ */
10
- html{-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{margin:.67em 0;font-size:2em}hr{box-sizing:content-box}pre{font-family:monospace;font-size:1em}a{background-color:#0000}abbr[title]{border-bottom:none;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted buttontext}fieldset{padding:.35em .75em .625em}legend{color:inherit;box-sizing:border-box;white-space:normal;max-width:100%;padding:0;display:table}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}details{display:block}summary{display:list-item}template{display:none}html{color:#222;scroll-behavior:smooth;font-size:1em;line-height:1.4}::-moz-selection{text-shadow:none;background:#191919}::selection{text-shadow:none;background:#191919}hr{border:0;border-top:1px solid #ccc;height:1px;margin:1em 0;padding:0;display:block;overflow:visible}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}body{color:#fafafa;background-color:#191919;margin:10px;font-family:Arial,Helvetica,sans-serif}a{text-decoration:none}a:link{color:#ffc627}a:hover,a:active{color:#ffc627;text-decoration:underline}a:focus{color:#191919;background-color:#ffc627}a:visited,a:visited:hover{color:#7f6227}.hidden,[hidden]{display:none!important}.visually-hidden{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.visually-hidden.focusable:active,.visually-hidden.focusable:focus{clip:auto;width:auto;height:auto;white-space:inherit;margin:0;position:static;overflow:visible}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}@media print{*,:before,:after{color:#000!important;box-shadow:none!important;text-shadow:none!important;background:#fff!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href)")"}abbr[title]:after{content:" (" attr(title)")"}a[href^=\#]:after,a[href^=javascript\:]:after{content:""}pre{white-space:pre-wrap!important}pre,blockquote{page-break-inside:avoid;border:1px solid #999}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.full-width-section{background-position:50%;background-size:cover;width:100%;max-width:1920px;margin:0 auto}.container{max-width:1200px;margin:0 auto;padding:0 12px}header,footer{width:100%}header .container,footer .container{max-width:1200px;margin:0 auto;padding:20px 12px}.gh{border-collapse:collapse;border-spacing:0;margin:0 auto}.gh td,.gh th{border-collapse:collapse;word-break:normal;padding:10px 5px;overflow:hidden}.gh .gh-tcell{text-align:center;vertical-align:middle}@media screen and (width<=767px){.gh,.gh col{width:auto!important}.gh-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.soc{border-collapse:collapse;border-spacing:0;margin:0 auto}.soc td,.soc th{border-collapse:collapse;word-break:normal;padding:8px;overflow:hidden}.soc .soc-fa{text-align:center;vertical-align:middle}@media screen and (width<=767px){.soc,.soc col{width:auto!important}.soc-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.foss{border-collapse:collapse;border-spacing:0}.foss td,.foss th{border-collapse:collapse;word-break:normal;padding:10px 5px;overflow:hidden}.foss .foss-cell{text-align:center;vertical-align:middle}@media screen and (width<=767px){.foss,.foss col{width:auto!important}.foss-wrap{-webkit-overflow-scrolling:touch;overflow-x:auto}}.bnav{border-collapse:collapse;border-spacing:0;margin:0 auto}.bnav td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;font-weight:700;line-height:1.125rem;overflow:hidden}.bnav th{word-break:normal;border-style:none;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.bnav .bnav-cell{text-align:center;vertical-align:middle;align-content:center}@media screen and (width<=767px){.bnav,.bnav col{width:auto!important}.bnav-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.bnav2{border-collapse:collapse;border-spacing:0;margin:0 auto}.bnav2 td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;font-weight:700;line-height:1.125rem;overflow:hidden}.bnav2 th{word-break:normal;border-style:none;padding:12px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.bnav2 .bnav2-cell{text-align:center;vertical-align:middle;align-content:center}@media screen and (width<=767px){.bnav2,.bnav2 col{width:auto!important}.bnav2-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.pgp{border-collapse:collapse;border-spacing:0;margin:0 auto}.pgp td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.pgp th{word-break:normal;border:1px solid #000;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.pgp .pgp-col1{text-align:right;vertical-align:middle;padding-right:1rem}.pgp .pgp-col2{text-align:left;vertical-align:middle;padding-left:1rem}@media screen and (width<=767px){.pgp,.pgp col{width:auto!important}.pgp-wrap{-webkit-overflow-scrolling:touch;margin:2rem 0 auto;overflow-x:auto}}.logo{margin-left:auto;margin-right:auto;display:block}.index-title1{text-align:center;font-style:italic;font-weight:700}.index-title2{letter-spacing:-.015em;text-align:center;font-variant:small-caps;font-size:1.25rem;line-height:1.625rem}.index1{letter-spacing:-.035em;text-align:center;font-style:italic;font-weight:700;line-height:2.125rem}.index2{letter-spacing:-.035em;text-align:center;font-variant:small-caps;font-size:1.5rem;line-height:1.75rem}.index3{letter-spacing:-.035em;text-align:center;font-size:1.5rem;line-height:1.75rem}.subhead{letter-spacing:-.035em;font-variant:small-caps;font-size:1.5rem;line-height:1.75rem}.bolditalic{font-style:italic;font-weight:700}.bquote{border-left:3px solid #9e9e9e;margin-left:30px;padding-left:10px;font-style:italic}.small-text{font-size:.75rem;line-height:1.125rem}.large-text-center{text-align:center;font-size:1.25rem;line-height:1.75rem}.prewrap{white-space:pre-wrap;display:block}.hr-styled{width:75%;margin:auto}.center-text{text-align:center}.copyright{text-align:center;font-size:.75rem;line-height:1.125rem}.visited{color:#7f6227}.center-nav{text-align:center;padding:5px;font-size:.875rem;line-height:1.125rem}.block{resize:none;background:0 0;border:none;border-radius:0;outline:none;width:100%;font-size:.75rem;line-height:1.125rem}.fingerprint{white-space:pre-line;font-weight:700;display:block}.pgp-image{width:125px;height:125px}.spacer{margin:2rem 0}.separator{margin:0 .5rem}
5
+ ========================================================================== */
6
+ html{-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{margin:.67em 0;font-size:2em}hr{box-sizing:content-box}pre{font-family:monospace;font-size:1em}a{background-color:#0000}abbr[title]{border-bottom:none;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted buttontext}fieldset{padding:.35em .75em .625em}legend{color:inherit;box-sizing:border-box;white-space:normal;max-width:100%;padding:0;display:table}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}details{display:block}summary{display:list-item}template{display:none}html{color:#222;scroll-behavior:smooth;font-size:1em;line-height:1.4}::-moz-selection{text-shadow:none;background:#191919}::selection{text-shadow:none;background:#191919}hr{border:0;border-top:1px solid #ccc;height:1px;margin:1em 0;padding:0;display:block;overflow:visible}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}body{color:#fafafa;background-color:#191919;margin:10px;font-family:Arial,Helvetica,sans-serif}a{text-decoration:none}a:link{color:#ffc627}a:hover,a:active{color:#ffc627;text-decoration:underline}a:focus{color:#191919;background-color:#ffc627}a:visited,a:visited:hover{color:#7f6227}.hidden,[hidden]{display:none!important}.visually-hidden{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.visually-hidden.focusable:active,.visually-hidden.focusable:focus{clip:auto;width:auto;height:auto;white-space:inherit;margin:0;position:static;overflow:visible}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}@media print{*,:before,:after{color:#000!important;box-shadow:none!important;text-shadow:none!important;background:#fff!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href)")"}abbr[title]:after{content:" (" attr(title)")"}a[href^=\#]:after,a[href^=javascript\:]:after{content:""}pre{white-space:pre-wrap!important}pre,blockquote{page-break-inside:avoid;border:1px solid #999}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.full-width-section{background-position:50%;background-size:cover;width:100%;max-width:1920px;margin:0 auto}.container{max-width:1200px;margin:0 auto;padding:0 12px}.readable{max-width:900px;margin:0 auto}header,footer{width:100%}header .container,footer .container{max-width:1200px;margin:0 auto;padding:20px 12px}.gh{border-collapse:collapse;border-spacing:0;margin:0 auto}.gh td,.gh th{border-collapse:collapse;word-break:normal;padding:10px 5px;overflow:hidden}.gh .gh-tcell{text-align:center;vertical-align:middle}@media screen and (width<=767px){.gh,.gh col{width:auto!important}.gh-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.soc{border-collapse:collapse;border-spacing:0;margin:0 auto}.soc td,.soc th{border-collapse:collapse;word-break:normal;padding:8px;overflow:hidden}.soc .soc-fa{text-align:center;vertical-align:middle}@media screen and (width<=767px){.soc,.soc col{width:auto!important}.soc-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.foss{border-collapse:collapse;border-spacing:0}.foss td,.foss th{border-collapse:collapse;word-break:normal;padding:10px 5px;overflow:hidden}.foss .foss-cell{text-align:center;vertical-align:middle}@media screen and (width<=767px){.foss,.foss col{width:auto!important}.foss-wrap{-webkit-overflow-scrolling:touch;overflow-x:auto}}.bnav{text-align:center;border-collapse:collapse;border-spacing:0;margin:0 auto}.bnav td,.bnav th{text-align:center;vertical-align:middle;word-break:normal;border-style:none;padding:10px;font-size:.875rem;font-weight:700;line-height:1.125rem;overflow:hidden}.bnav .bnav-cell{text-align:center;vertical-align:middle;align-content:center}@media screen and (width<=767px){.bnav,.bnav col{width:auto!important}.bnav-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.bnav2{border-collapse:collapse;border-spacing:0;margin:0 auto}.bnav2 td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;font-weight:700;line-height:1.125rem;overflow:hidden}.bnav2 th{word-break:normal;border-style:none;padding:12px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.bnav2 .bnav2-cell{text-align:center;vertical-align:middle;align-content:center}@media screen and (width<=767px){.bnav2,.bnav2 col{width:auto!important}.bnav2-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.pgp{border-collapse:collapse;border-spacing:0;margin:0 auto}.pgp td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.pgp th{word-break:normal;border:1px solid #000;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.pgp .pgp-col1{text-align:right;vertical-align:middle;padding-right:1rem}.pgp .pgp-col2{text-align:left;vertical-align:middle;padding-left:1rem}@media screen and (width<=767px){.pgp,.pgp col{width:auto!important}.pgp-wrap{-webkit-overflow-scrolling:touch;margin:2rem 0 auto;overflow-x:auto}}.logo{margin-left:auto;margin-right:auto;display:block}.index-title1{text-align:center;font-style:italic;font-weight:700}.index-title2{letter-spacing:-.015em;text-align:center;font-variant:small-caps;font-size:1.25rem;line-height:1.625rem}.index1{letter-spacing:-.035em;text-align:center;font-style:italic;font-weight:700;line-height:2.125rem}.index2{letter-spacing:-.035em;text-align:center;font-variant:small-caps;font-size:1.5rem;line-height:1.75rem}.index3{letter-spacing:-.035em;text-align:center;font-size:1.5rem;line-height:1.75rem}.index4{letter-spacing:-.035em;text-align:center;font-size:1.5rem;line-height:1.75rem;text-decoration:underline}.subhead{letter-spacing:-.035em;font-variant:small-caps;font-size:1.5rem;line-height:1.75rem}.bold{font-weight:700}.emphasis{font-style:italic}.uline{text-decoration:underline}.bolditalic{font-style:italic;font-weight:700}.bquote{border-left:3px solid #9e9e9e;margin-left:30px;padding-left:10px;font-style:italic}.small-text{font-size:.75rem;line-height:1.125rem}.large-text-center{text-align:center;font-size:1.25rem;line-height:1.75rem}.prewrap{white-space:pre-wrap;display:block}.hr-styled{width:75%;margin:auto}.center-text{text-align:center}.copyright{text-align:center;font-size:.75rem;line-height:1.125rem}.visited{color:#7f6227}.center-nav{text-align:center;padding:5px;font-size:.875rem;line-height:1.125rem}.block{resize:none;background:0 0;border:none;border-radius:0;outline:none;width:100%;font-size:.75rem;line-height:1.125rem}.fingerprint{white-space:pre-line;font-weight:700;display:block}.pgp-image{width:125px;height:125px}.spacer{margin:2rem 0}.separator{margin:0 .5rem}
@@ -0,0 +1,38 @@
1
+ /* ==========================================================================
2
+ src/lib/utils/privacy.js
3
+
4
+ Copyright © 2025 Network Pro Strategies (Network Pro™)
5
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
+ This file is part of Network Pro.
7
+ ========================================================================== */
8
+
9
+ /**
10
+ * @file privacy.js
11
+ * @description Determines whether the user allows tracking based on DNT, GPC, or manual opt-out.
12
+ * @module src/lib/utils/
13
+ * @author SunDevil311
14
+ * @updated 2025-05-28
15
+ */
16
+
17
+ /**
18
+ * @returns {boolean}
19
+ */
20
+ export function shouldTrackUser() {
21
+ const windowDNT = /** @type {any} */ (window).doNotTrack;
22
+ const navigatorGPC = /** @type {any} */ (navigator).globalPrivacyControl;
23
+
24
+ const dnt = navigator.doNotTrack === "1" || windowDNT === "1";
25
+ const gpc = navigatorGPC === true;
26
+
27
+ const manualOptOut = document.cookie.includes("disable_tracking=true");
28
+ const manualOptIn = document.cookie.includes("enable_tracking=true");
29
+
30
+ console.log("[Privacy] Opt-in cookie present:", manualOptIn);
31
+ console.log("[Privacy] Opt-out cookie present:", manualOptOut);
32
+
33
+ // Opt-in overrides everything; opt-out disables regardless of DNT/GPC
34
+ if (manualOptIn) return true;
35
+ if (manualOptOut) return false;
36
+
37
+ return !dnt && !gpc;
38
+ }
@@ -0,0 +1,40 @@
1
+ /* ==========================================================================
2
+ src/lib/utils/trackingCookies.js
3
+
4
+ Copyright © 2025 Network Pro Strategies (Network Pro™)
5
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
+ This file is part of Network Pro.
7
+ ========================================================================== */
8
+
9
+ /**
10
+ * @file trackingCookies.js
11
+ * @description Handles setting, clearing, and toggling tracking preference cookies.
12
+ * @module src/lib/utils/
13
+ * @author SunDevil311
14
+ * @updated 2025-05-28
15
+ */
16
+
17
+ /**
18
+ * Set a tracking preference cookie.
19
+ * @param {"enable" | "disable"} type
20
+ */
21
+ export function setTrackingPreference(type) {
22
+ const maxAge = 60 * 60 * 24 * 365 * 10; // 10 years
23
+ const cookieSettings = `path=/; max-age=${maxAge}; SameSite=Lax`;
24
+
25
+ if (type === "enable") {
26
+ document.cookie = `enable_tracking=true; ${cookieSettings}`;
27
+ document.cookie = `disable_tracking=; path=/; max-age=0; SameSite=Lax`;
28
+ } else if (type === "disable") {
29
+ document.cookie = `disable_tracking=true; ${cookieSettings}`;
30
+ document.cookie = `enable_tracking=; path=/; max-age=0; SameSite=Lax`;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Clear both tracking cookies.
36
+ */
37
+ export function clearTrackingPreferences() {
38
+ document.cookie = `enable_tracking=; path=/; max-age=0; SameSite=Lax`;
39
+ document.cookie = `disable_tracking=; path=/; max-age=0; SameSite=Lax`;
40
+ }
@@ -0,0 +1,46 @@
1
+ /* ==========================================================================
2
+ src/lib/utils/trackingStatus.js
3
+
4
+ Copyright © 2025 Network Pro Strategies (Network Pro™)
5
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
+ This file is part of Network Pro.
7
+ ========================================================================== */
8
+
9
+ /**
10
+ * @file trackingStatus.js
11
+ * @description Get tracking preferences based on cookies and browser privacy signals.
12
+ * @module src/lib/utils/
13
+ * @author SunDevil311
14
+ * @updated 2025-05-28
15
+ */
16
+
17
+ /**
18
+ * @returns {{
19
+ * optedOut: boolean,
20
+ * optedIn: boolean,
21
+ * dnt: boolean,
22
+ * gpc: boolean,
23
+ * status: string
24
+ * }}
25
+ */
26
+ export function getTrackingPreferences() {
27
+ const cookies = document.cookie;
28
+ const optedOut = cookies.includes("disable_tracking=true");
29
+ const optedIn = cookies.includes("enable_tracking=true");
30
+ const dnt = navigator.doNotTrack === "1";
31
+
32
+ // @ts-expect-error: 'globalPrivacyControl' is a non-standard property
33
+ const gpc = navigator.globalPrivacyControl === true;
34
+
35
+ let status = "⚙️ Using default settings (tracking enabled)";
36
+
37
+ if (optedOut) {
38
+ status = "🔒 Tracking disabled (manual opt-out)";
39
+ } else if (optedIn) {
40
+ status = "✅ Tracking enabled (manual opt-in)";
41
+ } else if (dnt || gpc) {
42
+ status = "🛑 Tracking disabled (via browser signal)";
43
+ }
44
+
45
+ return { optedOut, optedIn, dnt, gpc, status };
46
+ }
@@ -7,7 +7,14 @@ This file is part of Network Pro.
7
7
  ========================================================================== */
8
8
 
9
9
  /**
10
- * Append UTM parameter from window.location to a given URL.
10
+ * @file utm.js
11
+ * @description Append UTM parameter from window.location to a given URL.
12
+ * @module src/lib/utils/
13
+ * @author SunDevil311
14
+ * @updated 2025-05-28
15
+ */
16
+
17
+ /**
11
18
  * Returns `null` if not in a browser context.
12
19
  * @param {string} url - The base URL to append to
13
20
  * @returns {string | null}
@@ -14,10 +14,12 @@ This file is part of Network Pro.
14
14
  import HeaderDefault from "$lib/components/layout/HeaderDefault.svelte";
15
15
  import HeaderHome from "$lib/components/layout/HeaderHome.svelte";
16
16
  import PWAInstallButton from "$lib/components/PWAInstallButton.svelte";
17
+ import { shouldTrackUser } from "$lib/utils/privacy.js";
17
18
  import { onMount } from "svelte";
18
19
  import { registerServiceWorker } from "$lib/registerServiceWorker.js";
19
20
  import { browser } from "$app/environment";
20
- import "$lib/styles";
21
+ import "$lib/styles/global.min.css";
22
+ import "$lib/styles/fa-global.css";
21
23
 
22
24
  // Import favicon images
23
25
  import logoPng from "$lib/img/logo-web.png";
@@ -30,25 +32,36 @@ This file is part of Network Pro.
30
32
  let PostHog = null;
31
33
 
32
34
  if (browser) {
33
- // Preload logo images
34
- [logoPng, logoWbp].forEach((src) => {
35
+ // Preload all core images (logos + apple touch)
36
+ [logoPng, logoWbp, appleTouchIcon].forEach((src) => {
35
37
  const img = new Image();
36
38
  img.src = src;
37
39
  });
38
40
 
39
- // Preload Apple Touch icon
40
- const touchImg = new Image();
41
- touchImg.src = appleTouchIcon;
42
-
43
- // Register the service worker only in the browser
41
+ // Run setup when component mounts (only in browser)
44
42
  onMount(() => {
45
43
  console.log("[APP] onMount triggered in +layout.svelte");
46
44
  registerServiceWorker();
47
45
 
48
- // Dynamically import PostHog component only in the browser
49
- import("$lib/components/PostHog.svelte").then((module) => {
50
- PostHog = module.default;
51
- });
46
+ const isDev = import.meta.env.MODE === "development";
47
+
48
+ console.log("ENV MODE =", import.meta.env.MODE); // Should be "development"
49
+ console.log("isDev =", isDev);
50
+ console.log("shouldTrackUser =", shouldTrackUser());
51
+
52
+ if (isDev || shouldTrackUser()) {
53
+ import("$lib/components/PostHog.svelte").then((module) => {
54
+ PostHog = module.default;
55
+
56
+ if (isDev) {
57
+ console.log("[Dev] ✅ PostHog component loaded (tracking enabled)");
58
+ }
59
+ });
60
+ } else {
61
+ console.log(
62
+ "[Privacy] ⛔ Skipping PostHog component due to DNT or GPC signal.",
63
+ );
64
+ }
52
65
  });
53
66
  }
54
67
 
@@ -14,12 +14,6 @@ This file is part of Network Pro.
14
14
  import SocialMedia from "$lib/components/SocialMedia.svelte";
15
15
  import MetaTags from "$lib/components/MetaTags.svelte";
16
16
 
17
- /**
18
- * @type {string}
19
- * Style class for the horizontal rule element.
20
- */
21
- const hrStyle = "hr-styled";
22
-
23
17
  /**
24
18
  * @type {string}
25
19
  * Style class for the div element.
@@ -48,7 +42,7 @@ This file is part of Network Pro.
48
42
  <SocialMedia />
49
43
  </section>
50
44
 
51
- <hr class={hrStyle} />
45
+ <hr />
52
46
 
53
47
  <div class={spaceStyle}></div>
54
48
 
@@ -14,12 +14,6 @@ This file is part of Network Pro.
14
14
  import SocialMedia from "$lib/components/SocialMedia.svelte";
15
15
  import MetaTags from "$lib/components/MetaTags.svelte";
16
16
 
17
- /**
18
- * @type {string}
19
- * Style class for the horizontal rule element.
20
- */
21
- const hrStyle = "hr-styled";
22
-
23
17
  /**
24
18
  * @type {string}
25
19
  * Style class for the div element.
@@ -49,7 +43,7 @@ This file is part of Network Pro.
49
43
  </section>
50
44
  <!-- END SOCIAL MEDIA -->
51
45
 
52
- <hr class={hrStyle} />
46
+ <hr />
53
47
 
54
48
  <div class={spaceStyle}></div>
55
49
 
@@ -14,12 +14,6 @@ This file is part of Network Pro.
14
14
  import SocialMedia from "$lib/components/SocialMedia.svelte";
15
15
  import MetaTags from "$lib/components/MetaTags.svelte";
16
16
 
17
- /**
18
- * @type {string}
19
- * Style class for the horizontal rule element.
20
- */
21
- const hrStyle = "hr-styled";
22
-
23
17
  /**
24
18
  * @type {string}
25
19
  * Style class for the div element.
@@ -34,7 +28,7 @@ This file is part of Network Pro.
34
28
  <link rel="canonical" href="https://netwk.pro/license" />
35
29
 
36
30
  <section id="license">
37
- <FullWidthSection>
31
+ <FullWidthSection containerClass="readable">
38
32
  <!-- BEGIN LEGAL, COPYRIGHT, AND LICENSING -->
39
33
  <section id="main-content">
40
34
  <LicenseContent />
@@ -49,7 +43,7 @@ This file is part of Network Pro.
49
43
  </section>
50
44
  <!-- END SOCIAL MEDIA -->
51
45
 
52
- <hr class={hrStyle} />
46
+ <hr />
53
47
 
54
48
  <div class={spaceStyle}></div>
55
49
 
@@ -0,0 +1,18 @@
1
+ /* ==========================================================================
2
+ src/routes/privacy/+page.server.js
3
+
4
+ Copyright © 2025 Network Pro Strategies (Network Pro™)
5
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
+ This file is part of Network Pro.
7
+ ========================================================================== */
8
+
9
+ import { defaultMeta, meta } from "$lib/meta.js";
10
+
11
+ export const prerender = false;
12
+
13
+ /** @type {import('./$types').PageServerLoad} */
14
+ export function load() {
15
+ return {
16
+ meta: meta["/privacy"] || defaultMeta,
17
+ };
18
+ }
@@ -1,5 +1,5 @@
1
1
  <!-- ==========================================================================
2
- src/routes/privacy-policy/+page.svelte
2
+ src/routes/privacy/+page.svelte
3
3
 
4
4
  Copyright © 2025 Network Pro Strategies (Network Pro™)
5
5
  SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
@@ -14,12 +14,6 @@ This file is part of Network Pro.
14
14
  import SocialMedia from "$lib/components/SocialMedia.svelte";
15
15
  import MetaTags from "$lib/components/MetaTags.svelte";
16
16
 
17
- /**
18
- * @type {string}
19
- * Style class for the horizontal rule element.
20
- */
21
- const hrStyle = "hr-styled";
22
-
23
17
  /**
24
18
  * @type {string}
25
19
  * Style class for the div element.
@@ -31,10 +25,10 @@ This file is part of Network Pro.
31
25
 
32
26
  <MetaTags title={data.meta.title} description={data.meta.description} />
33
27
 
34
- <link rel="canonical" href="https://netwk.pro/privacy-policy" />
28
+ <link rel="canonical" href="https://netwk.pro/privacy" />
35
29
 
36
- <section id="privacy-policy">
37
- <FullWidthSection>
30
+ <section id="privacy">
31
+ <FullWidthSection containerClass="readable">
38
32
  <!-- BEGIN PRIVACY POLICY -->
39
33
  <section id="main-content">
40
34
  <PrivacyContent />
@@ -49,7 +43,7 @@ This file is part of Network Pro.
49
43
  </section>
50
44
  <!-- END SOCIAL MEDIA -->
51
45
 
52
- <hr class={hrStyle} />
46
+ <hr />
53
47
 
54
48
  <div class={spaceStyle}></div>
55
49
 
@@ -1,5 +1,5 @@
1
1
  /* ==========================================================================
2
- src/routes/privacy-policy/+page.server.js
2
+ src/routes/privacy/+page.server.js
3
3
 
4
4
  Copyright © 2025 Network Pro Strategies (Network Pro™)
5
5
  SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
@@ -13,6 +13,6 @@ export const prerender = false;
13
13
  /** @type {import('./$types').PageServerLoad} */
14
14
  export function load() {
15
15
  return {
16
- meta: meta["/privacy-policy"] || defaultMeta,
16
+ meta: meta["/privacy-dashboard"] || defaultMeta,
17
17
  };
18
18
  }
@@ -0,0 +1,69 @@
1
+ <!-- ==========================================================================
2
+ src/routes/privacy-dashboard/+page.svelte
3
+
4
+ Copyright © 2025 Network Pro Strategies (Network Pro™)
5
+ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
+ This file is part of Network Pro.
7
+ ========================================================================== -->
8
+
9
+ <script>
10
+ import Badges from "$lib/components/Badges.svelte";
11
+ import FullWidthSection from "$lib/components/FullWidthSection.svelte";
12
+ import PrivacyDashboard from "$lib/pages/PrivacyDashboard.svelte";
13
+ import LegalNav from "$lib/components/LegalNav.svelte";
14
+ import SocialMedia from "$lib/components/SocialMedia.svelte";
15
+ import MetaTags from "$lib/components/MetaTags.svelte";
16
+
17
+ /**
18
+ * @type {string}
19
+ * Style class for the horizontal rule element.
20
+ */
21
+ const hrStyle = "hr-styled";
22
+
23
+ /**
24
+ * @type {string}
25
+ * Style class for the div element.
26
+ */
27
+ const spaceStyle = "spacer";
28
+
29
+ export let data;
30
+ </script>
31
+
32
+ <MetaTags title={data.meta.title} description={data.meta.description} />
33
+
34
+ <link rel="canonical" href="https://netwk.pro/privacy-dashboard" />
35
+
36
+ <section id="privacy">
37
+ <FullWidthSection containerClass="readable">
38
+ <!-- BEGIN PRIVACY DASHBOARD -->
39
+ <section id="main-content">
40
+ <PrivacyDashboard />
41
+ </section>
42
+ <!-- END PRIVACY DASHBOARD -->
43
+
44
+ <div class={spaceStyle}></div>
45
+
46
+ <!-- BEGIN SOCIAL MEDIA -->
47
+ <section id="social-media">
48
+ <SocialMedia />
49
+ </section>
50
+ <!-- END SOCIAL MEDIA -->
51
+
52
+ <hr />
53
+
54
+ <div class={spaceStyle}></div>
55
+
56
+ <!-- BEGIN LEGAL -->
57
+ <section id="legal-nav">
58
+ <LegalNav />
59
+ </section>
60
+ <!-- END LEGAL -->
61
+
62
+ <div class={spaceStyle}></div>
63
+
64
+ <!-- BEGIN BADGES -->
65
+ <section id="badges">
66
+ <Badges />
67
+ </section>
68
+ </FullWidthSection>
69
+ </section>
@@ -14,12 +14,6 @@ This file is part of Network Pro.
14
14
  import SocialMedia from "$lib/components/SocialMedia.svelte";
15
15
  import MetaTags from "$lib/components/MetaTags.svelte";
16
16
 
17
- /**
18
- * @type {string}
19
- * Style class for the horizontal rule element.
20
- */
21
- const hrStyle = "hr-styled";
22
-
23
17
  /**
24
18
  * @type {string}
25
19
  * Style class for the div element.
@@ -34,7 +28,7 @@ This file is part of Network Pro.
34
28
  <link rel="canonical" href="https://netwk.pro/terms-conditions" />
35
29
 
36
30
  <section id="terms-conditions">
37
- <FullWidthSection>
31
+ <FullWidthSection containerClass="readable">
38
32
  <!-- BEGIN TERMS AND CONDITIONS -->
39
33
  <section id="main-content">
40
34
  <TermsConditionsContent />
@@ -49,7 +43,7 @@ This file is part of Network Pro.
49
43
  </section>
50
44
  <!-- END SOCIAL MEDIA -->
51
45
 
52
- <hr class={hrStyle} />
46
+ <hr />
53
47
 
54
48
  <div class={spaceStyle}></div>
55
49
 
@@ -14,12 +14,6 @@ This file is part of Network Pro.
14
14
  import SocialMedia from "$lib/components/SocialMedia.svelte";
15
15
  import MetaTags from "$lib/components/MetaTags.svelte";
16
16
 
17
- /**
18
- * @type {string}
19
- * Style class for the horizontal rule element.
20
- */
21
- const hrStyle = "hr-styled";
22
-
23
17
  /**
24
18
  * @type {string}
25
19
  * Style class for the div element.
@@ -34,7 +28,7 @@ This file is part of Network Pro.
34
28
  <link rel="canonical" href="https://netwk.pro/terms-of-use" />
35
29
 
36
30
  <section id="terms-of-use">
37
- <FullWidthSection>
31
+ <FullWidthSection containerClass="readable">
38
32
  <!-- BEGIN TERMS OF USE -->
39
33
  <section id="main-content">
40
34
  <TermsUseContent />
@@ -49,7 +43,7 @@ This file is part of Network Pro.
49
43
  </section>
50
44
  <!-- END SOCIAL MEDIA -->
51
45
 
52
- <hr class={hrStyle} />
46
+ <hr />
53
47
 
54
48
  <div class={spaceStyle}></div>
55
49