1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+
4+ < head >
5+ < title > {{ page.pagetitle | default: site.title }}</ title >
6+ < meta charset ="UTF-8 " />
7+ < meta http-equiv ="content-type " content ="text/html; charset=UTF-8 " />
8+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0, user-scalable=yes " />
9+ < link rel ="stylesheet " href ="{{ site.url }}{{ site.baseurl }}/styles/{{ page.pgname }}.css ">
10+ < link rel ="preconnect " href ="https://fonts.googleapis.com ">
11+ < link rel ="preconnect " href ="https://fonts.gstatic.com " crossorigin >
12+ < link rel ="preload " href ="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&display=swap " as ="style "
13+ onload ="this.rel='stylesheet' ">
14+ < noscript >
15+ < link href ="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&display=swap " rel ="stylesheet ">
16+ </ noscript >
17+ < link rel ="preload " href ="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css " as ="style "
18+ onload ="this.rel='stylesheet' ">
19+ < noscript >
20+ < link rel ="stylesheet " href ="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css ">
21+ </ noscript >
22+ < style >
23+ : root {
24+ --cookie-banner-height : 0px ;
25+ }
26+
27+ # cookieConsent {
28+ position : fixed;
29+ left : 0 ;
30+ right : 0 ;
31+ bottom : 0 ;
32+ z-index : 9999 ;
33+ box-sizing : border-box;
34+ background : # 222 ;
35+ color : # fff ;
36+ padding : 12px 16px ;
37+ padding-bottom : calc (12px + env (safe-area-inset-bottom));
38+ display : flex;
39+ gap : 12px ;
40+ align-items : center;
41+ justify-content : space-between;
42+ box-shadow : 0 -6px 18px rgba (0 , 0 , 0 , 0.25 );
43+ }
44+
45+ @supports (padding-bottom : constant (safe-area-inset-bottom)) {
46+ # cookieConsent {
47+ padding-bottom : calc (12px + constant (safe-area-inset-bottom));
48+ }
49+ }
50+
51+ # consent-div {
52+ display : flex;
53+ gap : 8px ;
54+ }
55+
56+ # cookieConsent button {
57+ padding : 8px 12px ;
58+ border-radius : 6px ;
59+ border : none;
60+ cursor : pointer;
61+ }
62+
63+ # btn-accept {
64+ background : # 0a84ff ;
65+ color : white;
66+ }
67+
68+ # btn-reject {
69+ background : transparent;
70+ color : # ddd ;
71+ border : 1px solid rgba (255 , 255 , 255 , 0.08 );
72+ }
73+ </ style >
74+ < link rel ="icon " type ="image/x-icon " href ="{{ site.url }}/favicon.ico " />
75+ < meta name ="application-name " content ="{{ site.title }} " />
76+ < meta name ="author " content ="{{ site.author }} " />
77+ < meta name ="description " content ="{{ site.ogdescription }} " />
78+ < meta name ="keywords " content ="{{ site.keywords }} ">
79+ < meta name ="robots " content ="index, follow " />
80+ < meta property ="og:type " content ="website " />
81+ < meta property ="og:site_name " content ="{{ site.title }} " />
82+ < meta property ="og:title " content ="{{ site.title }}{{ page.ogsuffix }} " />
83+ < meta property ="og:description " content ="{{ site.ogdescription }} " />
84+ < meta property ="og:url " content ="{{ site.url }}{{ site.baseurl }}/ " />
85+ < meta property ="og:image " content ="{{ site.url }}{{ site.baseurl }}{{ site.bannerpath }} " />
86+ < meta property ="og:image:secure_url " content ="{{ site.url }}{{ site.baseurl }}{{ site.bannerpath }} " />
87+ < meta property ="og:image:alt " content ="{{ site.title }} " />
88+ < meta name ="twitter:card " content ="summary " />
89+ < meta name ="twitter:site " content ="@{{ site.titleabbr }} " />
90+ < meta name ="twitter:title " content ="{{ site.title }}{{ page.ogsuffix }} " />
91+ < meta name ="twitter:description " content ="{{ site.ogdescription }} " />
92+ < meta name ="twitter:image " content ="{{ site.url }}{{ site.baseurl }}{{ site.bannerpath }} " />
93+ < meta name ="twitter:image:alt " content ="{{ site.title }} " />
94+ < meta name ="google-site-verification " content ="{{ site.googlesearchkey }} " />
95+ </ head >
96+
97+ < body >
98+ {% include header.html %}
99+ < main >
100+ {{ content }}
101+ </ main >
102+ {% include footer.html %}
103+ < script >
104+ const KEY = 'cookieConsentStatus' ;
105+ const banner = document . getElementById ( 'cookieConsent' ) ;
106+
107+ function setBodyPaddingForBanner ( ) {
108+ const h = banner . offsetHeight || 0 ;
109+ document . documentElement . style . setProperty ( '--cookie-banner-height' , h + 'px' ) ;
110+ document . body . style . paddingBottom = h + 'px' ;
111+ }
112+
113+ function hideBanner ( ) {
114+ banner . style . display = 'none' ;
115+ document . body . style . paddingBottom = '' ;
116+ }
117+
118+ function showBanner ( ) {
119+ banner . style . display = 'flex' ;
120+ requestAnimationFrame ( setBodyPaddingForBanner ) ;
121+ }
122+
123+ function injectTrackingScript ( ) {
124+ if ( window . __gaInjected ) return ;
125+ window . __gaInjected = true ;
126+ const gaScript = document . createElement ( 'script' ) ;
127+ gaScript . src = "https://www.googletagmanager.com/gtag/js?id={{ site.googleanalyticsid }}" ;
128+ gaScript . async = true ;
129+ document . head . appendChild ( gaScript ) ;
130+ gaScript . onload = function ( ) {
131+ window . dataLayer = window . dataLayer || [ ] ;
132+ function gtag ( ) { dataLayer . push ( arguments ) ; }
133+ gtag ( 'js' , new Date ( ) ) ;
134+ gtag ( 'config' , '{{ site.googleanalyticsid }}' ) ;
135+ } ;
136+ }
137+
138+ function setConsent ( status ) {
139+ localStorage . setItem ( KEY , status ) ;
140+ if ( status === 'accepted' ) injectTrackingScript ( ) ;
141+ hideBanner ( ) ;
142+ }
143+
144+ document . getElementById ( 'btn-accept' ) . addEventListener ( 'click' , ( ) => setConsent ( 'accepted' ) ) ;
145+ document . getElementById ( 'btn-reject' ) . addEventListener ( 'click' , ( ) => setConsent ( 'rejected' ) ) ;
146+
147+ const saved = localStorage . getItem ( KEY ) ;
148+ if ( saved === 'accepted' ) {
149+ injectTrackingScript ( ) ;
150+ hideBanner ( ) ;
151+ } else if ( saved === 'rejected' ) hideBanner ( ) ;
152+ else showBanner ( ) ;
153+
154+ window . addEventListener ( 'resize' , setBodyPaddingForBanner ) ;
155+ window . addEventListener ( 'orientationchange' , setBodyPaddingForBanner ) ;
156+
157+ window . addEventListener ( 'focusin' , setBodyPaddingForBanner ) ;
158+ window . addEventListener ( 'focusout' , setBodyPaddingForBanner ) ;
159+
160+ window . addEventListener ( 'load' , ( ) => setTimeout ( setBodyPaddingForBanner , 50 ) ) ;
161+ </ script >
162+
163+ </ body >
164+
165+ </ html >
0 commit comments