1<!DOCTYPE html><html lang="en" dir="ltr" class="2xl:text-[20px]"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="sitemap" href="/sitemap-index.xml"><link rel="icon" type="image/svg+xml" href="/_astro/symbolBlack.BBmzdhP8.svg"><link rel="mask-icon" href="/_astro/symbolBlack.BBmzdhP8.svg" color="#8D46E7"><link rel="apple-touch-icon" sizes="180x180" href="/_astro/apple-touch-icon.BH5dQIYY.png"><style> 2 :root { 3 --aw-font-sans: 'Inter Variable'; 4 --aw-font-serif: 'Inter Variable'; 5 --aw-font-heading: 'Inter Variable'; 6 7 --aw-color-primary: rgb(1 97 239); 8 --aw-color-secondary: rgb(1 84 207); 9 --aw-color-accent: rgb(109 40 217); 10 11 --aw-color-text-heading: rgb(0 0 0); 12 --aw-color-text-default: rgb(16 16 16); 13 --aw-color-text-muted: rgb(16 16 16 / 66%); 14 --aw-color-bg-page: rgb(255 255 255); 15 16 --aw-color-bg-page-dark: rgb(3 6 32); 17 18 ::selection { 19 background-color: lavender; 20 } 21 } 22 23 .dark { 24 --aw-font-sans: 'Inter Variable'; 25 --aw-font-serif: 'Inter Variable'; 26 --aw-font-heading: 'Inter Variable'; 27 28 --aw-color-primary: rgb(1 97 239); 29 --aw-color-secondary: rgb(1 84 207); 30 --aw-color-accent: rgb(109 40 217); 31 32 --aw-color-text-heading: rgb(247, 248, 248); 33 --aw-color-text-default: rgb(229 236 246); 34 --aw-color-text-muted: rgb(229 236 246 / 66%); 35 --aw-color-bg-page: rgb(3 6 32); 36 37 ::selection { 38 background-color: black; 39 color: snow; 40 } 41 } 42 43 /* GLightbox inline slides (theme-native SVG diagrams): follow the page theme 44 instead of the library's hardcoded white background */ 45 .glightbox-container .gslide-inline { 46 background: var(--aw-color-bg-page, #fff); 47 } 48</style>
48<script>(function(){const defaultTheme = "system"; 49 50 function applyTheme(theme) { 51 if (theme === 'dark') { 52 document.documentElement.classList.add('dark'); 53 } else { 54 document.documentElement.classList.remove('dark'); 55 } 56 const matches = document.querySelectorAll('[data-aw-toggle-color-scheme] > input'); 57 58 if (matches && matches.length) { 59 matches.forEach((elem) => { 60 elem.checked = theme !== 'dark'; 61 }); 62 } 63 } 64 65 if ((defaultTheme && defaultTheme.endsWith(':only')) || (!localStorage.theme && defaultTheme !== 'system')) { 66 applyTheme(defaultTheme.replace(':only', '')); 67 } else if ( 68 localStorage.theme === 'dark' || 69 (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches) 70 ) { 71 applyTheme('dark'); 72 } else { 73 applyTheme('light'); 74 } 75})();</script>
75<title>Search â cto4.ai</title> 76<meta name="description" content="Search through all blog posts, insights, and commentary"> 77<meta name="robots" content="index,follow"> 78<link rel="canonical" href="https://cto4.ai/search"> 79<meta property="og:title" content="Search"> 80<meta property="og:description" content="Search through all blog posts, insights, and commentary"> 81<meta property="og:url" content="https://cto4.ai/search"> 82<meta property="og:type" content="website"> 83<meta property="og:image" content="https://cto4.ai/_astro/brand.kHOlry1h_ZlFGr2.jpg"> 84<meta property="og:image:width" content="1200"> 85<meta property="og:image:height" content="630"> 86 87<meta property="og:locale" content="en"> 88<meta property="og:site_name" content="cto4.ai"> 89<meta name="twitter:card" content="summary_large_image"> 90<meta name="twitter:site" content="@Jackivers"> 91<meta name="twitter:creator" content="@Jackivers"><meta name="google-site-verification" content="orcPxI47GSa-cRvY11tUe6iGg2IO_RPvnA1q95iEM3M"><!-- Comment the line below to disable View Transitions --><meta name="astro-view-transitions-enabled" content="true"><meta name="astro-view-transitions-fallback" content="swap">
91<script type="module" src="/_astro/ClientRouter.astro_astro_type_script_index_0_lang.2i1RQzKf.js"></script>
91<style>.pagefind-ui{--pagefind-ui-scale:1;--pagefind-ui-primary:#3b82f6;--pagefind-ui-text:#374151;--pagefind-ui-background:#fff;--pagefind-ui-border:#d1d5db;--pagefind-ui-tag:#f3f4f6;--pagefind-ui-border-width:1px;--pagefind-ui-border-radius:.5rem}.dark .pagefind-ui{--pagefind-ui-text:#d1d5db;--pagefind-ui-background:#1f2937;--pagefind-ui-border:#374151;--pagefind-ui-tag:#374151}.pagefind-ui__search-input{border-radius:.5rem;padding:.75rem 1rem;font-size:1.125rem;color:#1f2937!important;background-color:#fff!important;border:2px solid #d1d5db!important}.pagefind-ui__search-input:focus{border-color:#3b82f6!important;outline:none!important;box-shadow:0 0 0 3px #3b82f61a!important}.pagefind-ui__search-input::placeholder{color:#6b7280!important}.dark .pagefind-ui__search-input{color:#f9fafb!important;background-color:#374151!important;border-color:#4b5563!important}.dark .pagefind-ui__search-input:focus{border-color:#60a5fa!important;box-shadow:0 0 0 3px #60a5fa1a!important}.dark .pagefind-ui__search-input::placeholder{color:#9ca3af!important}.pagefind-ui__result{border:1px solid var(--pagefind-ui-border);border-radius:.5rem;margin-bottom:1.5rem;padding:1rem}.pagefind-ui__result:hover{background-color:#f9fafb;border-color:#9ca3af}.dark .pagefind-ui__result:hover{background-color:#374151;border-color:#6b7280}.pagefind-ui__result-title{margin-bottom:.5rem;font-size:1.125rem;font-weight:600}.pagefind-ui__result-link{color:#1f2937;text-decoration:none}.dark .pagefind-ui__result-link{color:#f9fafb}.pagefind-ui__result-link:hover{color:#3b82f6}.pagefind-ui__result-excerpt{color:#6b7280;margin-bottom:.5rem;line-height:1.5}.dark .pagefind-ui__result-excerpt{color:#9ca3af}.pagefind-ui__result-nested{border-left:2px solid #e5e7eb;margin-top:.5rem;padding-left:1rem}.dark .pagefind-ui__result-nested{border-left-color:#4b5563}.pagefind-ui__result-nested-title{color:#6b7280;align-items:center;margin-bottom:.25rem;font-size:.875rem;display:inline-flex}.pagefind-ui__result-nested-title:before{content:"âª";margin-right:.5rem;font-size:.75rem}.dark .pagefind-ui__result-nested-title{color:#9ca3af}.pagefind-ui__result-tags{flex-wrap:wrap;gap:.5rem;margin-top:.5rem;display:flex}.pagefind-ui__result-tag{color:#6b7280;background-color:#f3f4f6;border-radius:.25rem;padding:.125rem .5rem;font-size:.75rem}.dark .pagefind-ui__result-tag{color:#9ca3af;background-color:#374151}.pagefind-ui__search-clear{color:#6b7280;cursor:pointer;background:0 0;border:none;padding:.5rem}.pagefind-ui__search-clear:hover{color:#374151}.dark .pagefind-ui__search-clear:hover{color:#d1d5db} 92</style><link rel="stylesheet" href="/_astro/Layout.DA15LbKO.css"><style>@font-face{font-family:Space Grotesk Variable;font-style:normal;font-display:swap;font-weight:300 700;src:url(/_astro/space-grotesk-vietnamese-wght-normal.D0rl6rjA.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Space Grotesk Variable;font-style:normal;font-display:swap;font-weight:300 700;src:url(/_astro/space-grotesk-latin-ext-wght-normal.D9tNdqV9.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Space Grotesk Variable;font-style:normal;font-display:swap;font-weight:300 700;src:url(/_astro/space-grotesk-latin-wght-normal.BhU9QXUp.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD} 93</style></head><body class="antialiased text-default bg-page tracking-tight"> 94 <header class="sticky top-0 z-40 flex-none mx-auto w-full border-b border-gray-50/0 transition-[opacity] ease-in-out" data-aw-sticky-header="true" id="header" data-pagefind-ignore><div class="absolute inset-0"></div><div class="relative text-default py-3 px-3 md:px-6 mx-auto w-full md:grid md:grid-cols-3 md:items-center max-w-7xl"><div class="flex justify-between"><a class="flex items-center" href="/"><div class="flex items-center"><!-- Light mode: Use the color/black logo --><img src="/_astro/noBgColor.CUHb9rCV_1y0B2z.svg" alt="cto4.ai" loading="lazy" decoding="async" width="120" height="40" class="h-12 w-auto dark:hidden"><!-- Dark mode: Use the white logo --><img src="/_astro/noBgWhite.D-JT5cLu_1y0B2z.svg" alt="cto4.ai" loading="lazy" decoding="async" width="120" height="40" class="h-12 w-auto hidden dark:block"></div></a><div class="flex items-center md:hidden"><button type="button" class="flex flex-col h-12 w-12 rounded justify-center items-center cursor-pointer group" aria-label="Toggle Menu" data-aw-toggle-menu><span class="sr-only">Toggle Menu</span> 95 <span aria-hidden="true" class="h-0.5 w-6 my-1 rounded-full bg-black dark:bg-white transition ease transform duration-200 opacity-80 group-[.expanded]:rotate-45 group-[.expanded]:translate-y-2.5"></span> 96 <span aria-hidden="true" class="h-0.5 w-6 my-1 rounded-full bg-black dark:bg-white transition ease transform duration-200 opacity-80 group-[.expanded]:opacity-0"></span> 97 <span aria-hidden="true" class="h-0.5 w-6 my-1 rounded-full bg-black dark:bg-white transition ease transform duration-200 opacity-80 group-[.expanded]:-rotate-45 group-[.expanded]:-translate-y-2.5"></span> 98 </button></div></div><nav class="items-center w-full md:w-auto hidden md:flex md:mx-5 text-default overflow-y-auto overflow-x-hidden md:overflow-y-visible md:overflow-x-auto md:justify-self-center" aria-label="Main navigation"><ul class="flex flex-col md:flex-row md:self-center w-full md:w-auto text-xl md:text-[0.9375rem] tracking-[0.01rem] font-medium md:justify-center"><li class>
98<a class="hover:text-primary dark:hover:text-white px-4 py-3 flex items-center whitespace-nowrap" href="/">Home</a></li><li class><a class="hover:text-primary dark:hover:text-white px-4 py-3 flex items-center whitespace-nowrap" href="/archive">Archive</a></li><li class><a class="hover:text-primary dark:hover:text-white px-4 py-3 flex items-center whitespace-nowrap aw-link-active" href="/search">Search</a></li><li class><a class="hover:text-primary dark:hover:text-white px-4 py-3 flex items-center whitespace-nowrap" href="/services">Services</a></li><li class><a class="hover:text-primary dark:hover:text-white px-4 py-3 flex items-center whitespace-nowrap" href="/about">About</a></li></ul></nav><div class="hidden md:self-center md:flex items-center md:mb-0 fixed w-full md:w-auto md:static justify-end left-0 rtl:left-auto rtl:right-0 bottom-0 p-3 md:p-0 md:justify-self-end"><div class="items-center flex justify-between w-full md:w-auto"><div class="flex"><button type="button" class="text-muted dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="Toggle between Dark and Light mode" data-aw-toggle-color-scheme><svg width="1em" height="1em" class="w-6 h-6 md:w-5 md:h-5 md:inline-block" data-icon="tabler:sun"><symbol id="ai:tabler:sun" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12a4 4 0 1 0 8 0a4 4 0 1 0-8 0m-5 0h1m8-9v1m8 8h1m-9 8v1M5.6 5.6l.7.7m12.1-.7l-.7.7m0 11.4l.7.7m-12.1-.7l-.7.7"/></symbol><use href="#ai:tabler:sun"></use></svg></button><a class="text-muted dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="RSS Feed" href="/rss.xml"><svg width="1em" height="1em" class="w-5 h-5" data-icon="tabler:rss"><symbol id="ai:tabler:rss" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 19a1 1 0 1 0 2 0a1 1 0 1 0-2 0M4 4a16 16 0 0 1 16 16M4 11a9 9 0 0 1 9 9"/></symbol><use href="#ai:tabler:rss"></use></svg></a></div></div></div></div></header> 99 <main><section class="px-4 py-16 mx-auto max-w-6xl lg:px-8 lg:py-20" data-astro-cid-wp2l4cmv><div class="max-w-4xl mx-auto" data-astro-cid-wp2l4cmv><div id="search" class="w-full" data-astro-cid-wp2l4cmv></div></div></section></main> 100 <footer class="relative border-t border-gray-200 dark:border-slate-800 not-prose" data-pagefind-ignore><div class="dark:bg-dark absolute inset-0 pointer-events-none" aria-hidden="true"></div><div class="relative max-w-7xl mx-auto px-4 sm:px-6 dark:text-slate-300 intersect-once intersect-quarter intersect-no-queue motion-safe:md:opacity-0 motion-safe:md:intersect:animate-fade"><div class="grid grid-cols-12 gap-4 gap-y-8 sm:gap-8 py-8 md:py-12"><div class="col-span-12 lg:col-span-4"><div class="mb-2"><a class="inline-block font-bold text-xl" href="/">cto4.ai</a></div><div class="text-sm text-muted flex gap-1"></div></div><div class="col-span-6 md:col-span-3 lg:col-span-2"><div class="dark:text-gray-300 font-medium mb-2">Content</div><ul class="text-sm"><li class="mb-2"><a class="text-muted hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out" href="/archive">Archive</a></li><li class="mb-2"><a class="text-muted hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out" href="/rss.xml">RSS Feed</a></li></ul></div><div class="col-span-6 md:col-span-3 lg:col-span-2"><div class="dark:text-gray-300 font-medium mb-2">Services</div><ul class="text-sm"><li class="mb-2"><a class="text-muted hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out" href="/services">Fractional CTO</a></li><li class="mb-2"><a class="text-muted hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out" href="mailto:[email protected]">Contact</a></li></ul></div><div class="col-span-6 md:col-span-3 lg:col-span-2"><div class="dark:text-gray-300 font-medium mb-2">Company</div><ul class="text-sm"><li class="mb-2"><a class="text-muted hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out" href="/about">About</a></li><li class="mb-2"><a class="text-muted hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out" href="/privacy">Privacy Policy</a></li><li class="mb-2"><a class="text-muted hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out" href="https://craftycto.com">CraftyCTO.com</a></li></ul></div></div><div class="md:flex md:items-center md:justify-between py-6 md:py-8"><ul class="flex mb-4 md:order-1 -ml-2 md:ml-4 md:mb-0 rtl:ml-0 rtl:-mr-2 rtl:md:ml-0 rtl:md:mr-4"><li><a class="text-muted dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center" aria-label="LinkedIn" href="https://www.linkedin.com/in/jackivers/"><svg width="1em" height="1em" class="w-5 h-5" data-icon="tabler:brand-linkedin">
100<symbol id="ai:tabler:brand-linkedin" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M8 11v5m0-8v.01M12 16v-5m4 5v-3a2 2 0 1 0-4 0"/><path d="M3 7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4v10a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4z"/></g></symbol><use href="#ai:tabler:brand-linkedin"></use></svg></a></li></ul><div class="text-sm mr-4 dark:text-muted"> 101 Copyright 2019-2026 <a class="text-blue-600 underline dark:text-muted" href="https://craftycto.com"> Crafty CTO</a> · All rights reserved. 102 </div></div></div></footer> 103
103<script>(function(){const defaultTheme = "system"; 104 105 (function () { 106 if (window.basic_script) { 107 return; 108 } 109 110 window.basic_script = true; 111 112 function applyTheme(theme) { 113 if (theme === 'dark') { 114 document.documentElement.classList.add('dark'); 115 } else { 116 document.documentElement.classList.remove('dark'); 117 } 118 } 119 120 const initTheme = function () { 121 if ((defaultTheme && defaultTheme.endsWith(':only')) || (!localStorage.theme && defaultTheme !== 'system')) { 122 applyTheme(defaultTheme.replace(':only', '')); 123 } else if ( 124 localStorage.theme === 'dark' || 125 (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches) 126 ) { 127 applyTheme('dark'); 128 } else { 129 applyTheme('light'); 130 } 131 }; 132 initTheme(); 133 134 function attachEvent(selector, event, fn) { 135 const matches = typeof selector === 'string' ? document.querySelectorAll(selector) : selector; 136 if (matches && matches.length) { 137 matches.forEach((elem) => { 138 elem.addEventListener(event, (e) => fn(e, elem), false); 139 }); 140 } 141 } 142 143 const onLoad = function () { 144 let lastKnownScrollPosition = window.scrollY; 145 let ticking = true; 146 147 attachEvent('#header nav', 'click', function () { 148 document.querySelector('[data-aw-toggle-menu]')?.classList.remove('expanded'); 149 document.body.classList.remove('overflow-hidden'); 150 document.getElementById('header')?.classList.remove('h-screen'); 151 document.getElementById('header')?.classList.remove('expanded'); 152 document.getElementById('header')?.classList.remove('bg-page'); 153 document.querySelector('#header nav')?.classList.add('hidden'); 154 document.querySelector('#header > div > div:last-child')?.classList.add('hidden'); 155 }); 156 157 attachEvent('[data-aw-toggle-menu]', 'click', function (_, elem) { 158 elem.classList.toggle('expanded'); 159 document.body.classList.toggle('overflow-hidden'); 160 document.getElementById('header')?.classList.toggle('h-screen'); 161 document.getElementById('header')?.classList.toggle('expanded'); 162 document.getElementById('header')?.classList.toggle('bg-page'); 163 document.querySelector('#header nav')?.classList.toggle('hidden'); 164 document.querySelector('#header > div > div:last-child')?.classList.toggle('hidden'); 165 }); 166 167 attachEvent('[data-aw-toggle-color-scheme]', 'click', function () { 168 if (defaultTheme.endsWith(':only')) { 169 return; 170 } 171 document.documentElement.classList.toggle('dark'); 172 localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light'; 173 }); 174 175 attachEvent('[data-aw-social-share]', 'click', function (_, elem) { 176 const network = elem.getAttribute('data-aw-social-share'); 177 const url = encodeURIComponent(elem.getAttribute('data-aw-url')); 178 const text = encodeURIComponent(elem.getAttribute('data-aw-text')); 179 180 let href; 181 switch (network) { 182 case 'facebook': 183 href = `https://www.facebook.com/sharer.php?u=${url}`; 184 break; 185 case 'twitter': 186 href = `https://twitter.com/intent/tweet?url=${url}&text=${text}`; 187 break; 188 case 'linkedin': 189 href = `https://www.linkedin.com/shareArticle?mini=true&url=${url}&title=${text}`; 190 break; 191 case 'whatsapp': 192 href = `https://wa.me/?text=${text}%20${url}`; 193 break; 194 case 'mail': 195 href = `mailto:?subject=%22${text}%22&body=${text}%20${url}`; 196 break; 197 198 default: 199 return; 200 } 201 202 const newlink = document.createElement('a'); 203 newlink.target = '_blank'; 204 newlink.href = href; 205 newlink.click(); 206 }); 207 208 const screenSize = window.matchMedia('(max-width: 767px)'); 209 screenSize.addEventListener('change', function () { 210 document.querySelector('[data-aw-toggle-menu]')?.classList.remove('expanded'); 211 document.body.classList.remove('overflow-hidden'); 212 document.getElementById('header')?.classList.remove('h-screen'); 213 document.getElementById('header')?.classList.remove('expanded'); 214 document.getElementById('header')?.classList.remove('bg-page'); 215 document.querySelector('#header nav')?.classList.add('hidden'); 216 document.querySelector('#header > div > div:last-child')?.classList.add('hidden'); 217 }); 218 219 function applyHeaderStylesOnScroll() { 220 const header = document.querySelector('#header[data-aw-sticky-header]'); 221 if (!header) return; 222 if (lastKnownScrollPosition > 60 && !header.classList.contains('scroll')) { 223 header.classList.add('scroll'); 224 } else if (lastKnownScrollPosition <= 60 && header.classList.contains('scroll')) { 225 header.classList.remove('scroll'); 226 } 227 ticking = false;
228 } 229 applyHeaderStylesOnScroll(); 230 231 attachEvent([document], 'scroll', function () { 232 lastKnownScrollPosition = window.scrollY; 233 234 if (!ticking) { 235 window.requestAnimationFrame(() => { 236 applyHeaderStylesOnScroll(); 237 }); 238 ticking = true; 239 } 240 }); 241 // Handle anchor link clicks for proper positioning with sticky header 242 attachEvent('a[href^="#"]', 'click', function (e, elem) { 243 const targetId = elem.getAttribute('href').slice(1); 244 if (!targetId) return; 245 246 const targetElement = document.getElementById(targetId); 247 if (!targetElement) return; 248 249 e.preventDefault(); 250 251 // Temporarily disable smooth scrolling for precise positioning 252 document.documentElement.style.scrollBehavior = 'auto'; 253 254 // Calculate position accounting for sticky header 255 const headerHeight = 96; // Header height 256 const offset = 20; // Additional offset for better visual spacing 257 const elementPosition = targetElement.getBoundingClientRect().top; 258 const offsetPosition = elementPosition + window.pageYOffset - headerHeight - offset; 259 260 window.scrollTo({ 261 top: offsetPosition, 262 behavior: 'auto', 263 }); 264 265 // Update URL hash 266 history.pushState(null, null, '#' + targetId); 267 268 // Re-enable smooth scrolling after a brief delay 269 setTimeout(() => { 270 document.documentElement.style.scrollBehavior = ''; 271 }, 100); 272 }); 273 }; 274 const onPageShow = function () { 275 document.documentElement.classList.add('motion-safe:scroll-smooth'); 276 const elem = document.querySelector('[data-aw-toggle-menu]'); 277 if (elem) { 278 elem.classList.remove('expanded'); 279 } 280 document.body.classList.remove('overflow-hidden'); 281 document.getElementById('header')?.classList.remove('h-screen'); 282 document.getElementById('header')?.classList.remove('expanded'); 283 document.querySelector('#header nav')?.classList.add('hidden'); 284 }; 285 286 window.onload = onLoad; 287 window.onpageshow = onPageShow; 288 289 document.addEventListener('astro:after-swap', () => { 290 initTheme(); 291 onLoad(); 292 onPageShow(); 293 }); 294 })(); 295})();</script>
295<script> 296 /* Inspired by: https://github.com/heidkaemper/tailwindcss-intersect */ 297 const Observer = { 298 observer: null, 299 delayBetweenAnimations: 100, 300 animationCounter: 0, 301 302 start() { 303 const selectors = [ 304 '[class*=" intersect:"]', 305 '[class*=":intersect:"]', 306 '[class^="intersect:"]', 307 '[class="intersect"]', 308 '[class*=" intersect "]', 309 '[class^="intersect "]', 310 '[class$=" intersect"]', 311 ]; 312 313 const elements = Array.from(document.querySelectorAll(selectors.join(','))); 314 315 const getThreshold = (element) => { 316 if (element.classList.contains('intersect-full')) return 0.99; 317 if (element.classList.contains('intersect-half')) return 0.5; 318 if (element.classList.contains('intersect-quarter')) return 0.25; 319 return 0; 320 }; 321 322 elements.forEach((el) => { 323 el.setAttribute('no-intersect', ''); 324 el._intersectionThreshold = getThreshold(el); 325 }); 326 327 const callback = (entries) => { 328 entries.forEach((entry) => { 329 requestAnimationFrame(() => { 330 const target = entry.target; 331 const intersectionRatio = entry.intersectionRatio; 332 const threshold = target._intersectionThreshold; 333 334 if (target.classList.contains('intersect-no-queue')) { 335 if (entry.isIntersecting) { 336 target.removeAttribute('no-intersect'); 337 if (target.classList.contains('intersect-once')) { 338 this.observer.unobserve(target); 339 } 340 } else { 341 target.setAttribute('no-intersect', ''); 342 } 343 return; 344 } 345 346 if (intersectionRatio >= threshold) { 347 if (!target.hasAttribute('data-animated')) { 348 target.removeAttribute('no-intersect'); 349 target.setAttribute('data-animated', 'true'); 350 351 const delay = this.animationCounter * this.delayBetweenAnimations; 352 this.animationCounter++; 353 354 target.style.transitionDelay = `${delay}ms`; 355 target.style.animationDelay = `${delay}ms`; 356 357 if (target.classList.contains('intersect-once')) { 358 this.observer.unobserve(target); 359 } 360 } 361 } else { 362 target.setAttribute('no-intersect', ''); 363 target.removeAttribute('data-animated'); 364 target.style.transitionDelay = ''; 365 target.style.animationDelay = ''; 366 367 this.animationCounter = 0; 368 } 369 }); 370 }); 371 }; 372 373 this.observer = new IntersectionObserver(callback.bind(this), { threshold: [0, 0.25, 0.5, 0.99] }); 374 375 elements.forEach((el) => { 376 this.observer.observe(el); 377 }); 378 }, 379 }; 380 381 Observer.start(); 382 383 document.addEventListener('astro:after-swap', () => { 384 Observer.start(); 385 }); 386</script>
386<!-- Global Lightbox Manager -->
386<script type="module" src="/_astro/Layout.astro_astro_type_script_index_0_lang.DIVGY2Yd.js"></script>
386</body></html>
386<script type="module" src="/_astro/search.astro_astro_type_script_index_0_lang.1yqxcU8t.js"></script>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.