1<!DOCTYPE html> 2<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> 3<head> 4 <meta charset="utf-8" /> 5 <meta name="generator" content="pandoc" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> 7 <meta name="author" content="author" /> 8 <title>Checkout</title> 9 <style> 10 code{white-space: pre-wrap;} 11 span.smallcaps{font-variant: small-caps;} 12 span.underline{text-decoration: underline;} 13 div.column{display: inline-block; vertical-align: top; width: 50%;} 14 div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 15 ul.task-list{list-style: none;} 16 .display.math{display: block; text-align: center; margin: 0.5rem auto;} 17 </style> 18 <link rel="stylesheet" href="/static/style.css?v=1376469157" /> 19
19<script defer src="/static/js/htmx.min.js?v=1376469157"></script>
19 20
20<script defer src="/static/js/idiomorph-ext.min.js?v=1376469157"></script>
20 21
21<script> 22 (function () { 23 try { 24 var host = window.location.hostname || ''; 25 var path = window.location.pathname || ''; 26 if (path === '/artificer' || path.indexOf('/artificer/') === 0) { 27 document.documentElement.classList.add('artificer-web-route'); 28 } 29 } catch (_err) { 30 // Ignore early route detection failures. 31 } 32 })(); 33 </script>
33 34 <style id="private-app-route-guard"> 35 html.artificer-web-route, 36 html.artificer-web-route body { 37 background: #111418 !important; 38 } 39 40 html.artificer-web-route nav.site-nav, 41 html.artificer-web-route footer.site-footer, 42 html.artificer-web-route #title-block-header { 43 display: none !important; 44 } 45 46 html.artificer-web-route body, 47 html.artificer-web-route main, 48 html.artificer-web-route .page, 49 html.artificer-web-route .content { 50 margin: 0 !important; 51 max-width: none !important; 52 padding: 0 !important; 53 } 54 55 </style> 56
56<script src="/static/site-bootstrap.js?v=1376469157"></script>
56 57
57<script> 58 (function () { 59 window.__wizardryThemeStylesheetVersion = '20260622-lapidarist-restore1'; 60 var theme = 'lapidarist'; 61 try { 62 var bootstrap = window.__wizardrySiteBootstrap || {}; 63 var config = bootstrap && bootstrap.config && typeof bootstrap.config === 'object' ? bootstrap.config : {}; 64 var hasConfiguredTheme = Object.prototype.hasOwnProperty.call(config, 'theme'); 65 var cachedTheme = hasConfiguredTheme ? '' : (localStorage.getItem('wizardry_blog_theme_v1') || ''); 66 var nextTheme = String(hasConfiguredTheme ? config.theme : cachedTheme).trim(); 67 var routeSlug = String(window.location.pathname || '').replace(/^\/+/, '').split('/')[0].replace(/\.html?$/i, ''); 68 var publicationThemes = config.publication_themes && typeof config.publication_themes === 'object' ? config.publication_themes : {}; 69 if (routeSlug && publicationThemes[routeSlug]) { 70 nextTheme = String(publicationThemes[routeSlug]).trim(); 71 } 72 if (nextTheme) { 73 theme = nextTheme; 74 } 75 } catch (_err) { 76 // Ignore storage failures. 77 } 78 var href = '/static/themes/' + encodeURIComponent(theme) + '.css?v=' + encodeURIComponent(window.__wizardryThemeStylesheetVersion); 79 var markup = '<link id="theme-stylesheet" rel="stylesheet" href="' + href + '" data-theme-href="' + href + '">'; 80 if (document.readyState === 'loading' && typeof document.write === 'function') { 81 document.write(markup); 82 return; 83 } 84 var link = document.createElement('link'); 85 link.id = 'theme-stylesheet'; 86 link.rel = 'stylesheet'; 87 link.href = href; 88 link.setAttribute('data-theme-href', href); 89 (document.head || document.documentElement).appendChild(link); 90 })(); 91 </script>
91 92 <noscript><link id="theme-stylesheet" rel="stylesheet" href="/static/themes/lapidarist.css?v=1376469157" data-theme-href="/static/themes/lapidarist.css?v=1376469157" /></noscript> 93 <style id="blog-tag-recovery-style"> 94 html body .blog-post-item .tag, 95 html body .blog-post-item .tag:hover, 96 html body .blog-post-item .tag:focus-visible, 97 html body .blog-post-item .blog-type-pill, 98 html body .blog-post-item .blog-type-pill:hover, 99 html body .blog-post-item .blog-type-pill:focus-visible, 100 html body .blog-post-item .blog-year-pill, 101 html body .blog-post-item .blog-year-pill:hover, 102 html body .blog-post-item .blog-year-pill:focus-visible { 103 --lapidarist-control-shadow: none; 104 --action-soft-shadow: none; 105 --action-soft-hover-shadow: none; 106 box-shadow: none !important; 107 -webkit-box-shadow: none !important; 108 filter: none !important; 109 -webkit-filter: none !important; 110 text-shadow: none !important; 111 } 112 113 html body .blog-post-item :is(a, button).blog-type-pill, 114 html body .blog-post-item :is(a, button).blog-type-pill:hover, 115 html body .blog-post-item :is(a, button).blog-type-pill:focus-visible, 116 html body .post-single-item :is(a, button).blog-type-pill, 117 html body .post-single-item :is(a, button).blog-type-pill:hover, 118 html body .post-single-item :is(a, button).blog-type-pill:focus-visible { 119 border-color: var(--post-tag-type-border) !important; 120 background: var(--post-tag-type-bg) !important; 121 background-color: var(--post-tag-type-bg) !important; 122 color: var(--post-tag-type-text) !important; 123 -webkit-text-fill-color: var(--post-tag-type-text) !important; 124 } 125 126 html body .blog-post-item :is(a, button).blog-year-pill, 127 html body .blog-post-item :is(a, button).blog-year-pill:hover, 128 html body .blog-post-item :is(a, button).blog-year-pill:focus-visible, 129 html body .post-single-item :is(a, button).blog-year-pill, 130 html body .post-single-item :is(a, button).blog-year-pill:hover, 131 html body .post-single-item :is(a, button).blog-year-pill:focus-visible { 132 border-color: var(--post-tag-year-border) !important; 133 background: var(--post-tag-year-bg) !important; 134 background-color: var(--post-tag-year-bg) !important; 135 color: var(--post-tag-year-text) !important; 136 -webkit-text-fill-color: var(--post-tag-year-text) !important; 137 } 138 139 </style> 140 <!-- Page bundles in the body call these shared helpers during initialization. --> 141
141<script src="/static/page-head.js?v=1376469157"></script>
141 142
142<script defer src="/static/zap-ui.js?v=1376469157"></script>
142 143
143<script defer src="/static/post-context.js?v=1376469157"></script>
143 144 <link id="rss-alternate" rel="alternate" type="application/rss+xml" title="RSS Feed" href="/rss.xml" /> 145 <link id="atom-alternate" rel="alternate" type="application/atom+xml" title="Atom Feed" href="/atom.xml" /> 146
146<script> 147 (function () { 148 var config = (window.__wizardrySiteBootstrap || {}).config || {}; 149 var slug = String(window.location.pathname || '').replace(/^\/+/, '').split('/')[0].replace(/\.html?$/i, ''); 150 if (!slug || !Array.isArray(config.publication_slugs) || config.publication_slugs.indexOf(slug) < 0) return; 151 var rss = document.getElementById('rss-alternate'); 152 var atom = document.getElementById('atom-alternate'); 153 if (rss) rss.href = '/' + slug + '/rss.xml'; 154 if (atom) atom.href = '/' + slug + '/atom.xml'; 155 })(); 156 </script>
156 157 <meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate, max-age=0" /> 158 <meta http-equiv="Pragma" content="no-cache" /> 159 <meta http-equiv="Expires" content="0" /> 160 <meta name="description" content="Nostr-enabled blog template" /> 161 <meta property="og:site_name" content="gazeta" /> 162 <meta property="og:type" content="website" /> 163 <meta name="twitter:card" content="summary_large_image" /> 164</head> 165<body>
166<script type="module"> 167(function () { 168 var docEl = document.documentElement; 169 var navReady = false; 170 var pageReady = false; 171 var revealed = false; 172 173 function hasDynamicPageRoot() { 174 return !!( 175 document.getElementById('blog-page-root') || 176 document.getElementById('nip23-page-root') || 177 document.getElementById('list-page-root') || 178 document.getElementById('public-ranking-root') || 179 document.getElementById('overworld-page-root') || 180 document.getElementById('contact-page-root') || 181 document.getElementById('archive-page-root') || 182 document.getElementById('tags-page-root') || 183 document.getElementById('search-page-root') || 184 document.getElementById('admin-panel') 185 ); 186 } 187 188 function reveal() { 189 if (revealed) { 190 return; 191 } 192 revealed = true; 193 if (docEl) { 194 docEl.classList.remove('app-hydrating'); 195 } 196 } 197 198 function maybeReveal() { 199 if (navReady && pageReady) { 200 reveal(); 201 } 202 } 203 204 window.__wizardryHydration = { 205 markNavReady: function () { 206 navReady = true; 207 maybeReveal(); 208 }, 209 markPageReady: function () { 210 pageReady = true; 211 maybeReveal(); 212 }, 213 forceReveal: reveal 214 }; 215 216 setTimeout(function () { 217 reveal(); 218 }, 6000); 219})(); 220</script>
220 221<a class="skip-link" href="#main-content">Skip to content</a>
222<script> 223(function () { 224 var docEl = document.documentElement; 225 if (docEl && docEl.classList.contains('app-hydrating')) { 226 docEl.classList.add('nav-overflow-booting'); 227 } 228})(); 229</script>
229 230<nav class="site-nav"> 231<a id="nav-site-signature" class="nav-site-signature" href="/">Site</a> 232<div class="nav-center"> 233<a href="/" data-page="index" data-nav-rank="1">Writing</a> 234<a href="/blog" data-page="blog" data-nav-rank="2">Blog</a> 235<a href="/oeuvre" data-page="oeuvre" data-nav-rank="3">Oeuvre</a> 236<a href="/projects" data-page="projects" data-nav-rank="4">Projects</a> 237<a href="/reading-list" data-page="reading-list" data-nav-rank="5">Reading list</a> 238<a href="/contact" data-page="contact" data-nav-rank="6">Contact</a> 239<a href="/overworld" data-page="overworld" data-nav-rank="7">Overworld</a> 240<div class="nav-overflow-menu" id="nav-overflow-menu" hidden> 241 <button class="nav-menu-btn nav-overflow-btn" id="nav-overflow-btn" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="More pages"> 242 <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"> 243 <path d="M3 4.25H13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> 244 <path d="M3 8H13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> 245 <path d="M3 11.75H13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> 246 </svg> 247 <span class="nav-overflow-count" id="nav-overflow-count" hidden>0</span> 248 </button> 249 <div class="nav-menu-panel nav-overflow-panel" id="nav-overflow-panel" role="menu" hidden></div> 250</div> 251</div> 252<div class="nav-right"> 253<form class="nav-search" method="get" action="/search"> 254<input type="text" name="q" placeholder="Search..." /> 255<button type="submit" aria-label="Search"> 256<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> 257<circle cx="7" cy="7" r="5.5" stroke="currentColor" stroke-width="1.9"/> 258<path d="M11 11L14.5 14.5" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"/> 259</svg> 260</button> 261</form> 262<div class="nav-compose-tools" id="nav-compose-tools" style="display:none;"> 263<a href="/admin#compose" class="nav-compose nav-compose-icon" aria-label="Compose post" title="Compose post"> 264<!-- Icon is replaced by nav-auth.js --> 265<svg width="21" height="21" viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"> 266<path fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" d="M4 20h4l10-10-4-4L4 16v4zM13 7l4 4"/> 267</svg> 268</a> 269</div> 270<button id="nav-cart-toggle" class="nav-cart-toggle" type="button" aria-label="Open cart" aria-expanded="false" hidden> 271<svg width="19" height="19" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"> 272<path d="M3 4H5L7 16H18L21 7H6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/> 273<circle cx="9" cy="20" r="1.7" fill="currentColor"/> 274<circle cx="17" cy="20" r="1.7" fill="currentColor"/> 275</svg> 276<span id="nav-cart-count" class="nav-cart-count" hidden>0</span> 277</button> 278<a id="nav-user-name" class="nav-username" href="/admin#account" style="display:none;"></a> 279<div class="nav-user-menu" id="nav-user-menu" style="display:none;"> 280 <button class="nav-menu-btn" id="nav-menu-btn" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="User menu"><svg class="overflow-menu-icon-svg" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="5.5" r="1.9" fill="currentColor"/><circle cx="12" cy="12" r="1.9" fill="currentColor"/><circle cx="12" cy="18.5" r="1.9" fill="currentColor"/></svg></button> 281 <div class="nav-menu-panel" id="nav-menu-panel" role="menu" hidden> 282 <a id="nav-menu-primary-link" class="nav-menu-item" href="/admin" role="menuitem">Admin</a> 283 <div class="nav-menu-logout-row" id="nav-menu-logout-row"> 284 <button id="nav-menu-logout" class="nav-menu-item nav-menu-item-danger" type="button" role="menuitem">Logout</button> 285 <button id="nav-menu-logout-more" class="nav-menu-logout-more" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="More logout actions" title="More logout actions" style="display:none;"><svg class="overflow-menu-icon-svg" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewB
285ox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="5.5" r="1.9" fill="currentColor"/><circle cx="12" cy="12" r="1.9" fill="currentColor"/><circle cx="12" cy="18.5" r="1.9" fill="currentColor"/></svg></button> 286 <div class="nav-menu-logout-submenu" id="nav-menu-logout-submenu" role="menu" hidden> 287 <button id="nav-menu-logout-everywhere" class="nav-menu-item" type="button" role="menuitem" style="display:none;">Log out other sessions</button> 288 </div> 289 </div> 290 </div> 291</div> 292<div class="nav-login-split" id="nav-login-split" style="display:none;"> 293 <button class="btn-login btn-login-main" id="login-btn" type="button">Login</button> 294 <button class="btn-login btn-login-caret" id="login-more-btn" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="More login options">â¼</button> 295 <div class="nav-login-menu" id="nav-login-menu" role="menu" hidden> 296 <button id="login-menu-register" class="nav-menu-item" type="button" role="menuitem">Use browser signer...</button> 297 <button id="login-menu-phone" class="nav-menu-item" type="button" role="menuitem">Use phone signer (QR)</button> 298 <button id="login-menu-manual" class="nav-menu-item" type="button" role="menuitem">Advanced...</button> 299 <button id="login-menu-learn" class="nav-menu-item" type="button" role="menuitem">Learn about Nostr sign-in</button> 300 </div> 301</div> 302</div> 303</nav>
304<script> 305(function () { 306 function seedInitialOverflowMenu() { 307 var docEl = document.documentElement; 308 if (!docEl || !docEl.classList.contains('app-hydrating')) { 309 return; 310 } 311 try { 312 seedInitialOverflowMenuNow(); 313 } finally { 314 docEl.classList.remove('nav-overflow-booting'); 315 } 316 } 317 318 function seedInitialOverflowMenuNow() { 319 var navCenter = document.querySelector('nav.site-nav .nav-center'); 320 var navRight = document.querySelector('nav.site-nav .nav-right'); 321 var menu = document.getElementById('nav-overflow-menu'); 322 var button = document.getElementById('nav-overflow-btn'); 323 var count = document.getElementById('nav-overflow-count'); 324 var panel = document.getElementById('nav-overflow-panel'); 325 if (!navCenter || !menu || !button || !count || !panel) { 326 return; 327 } 328 329 function esc(text) { 330 return String(text || '') 331 .replace(/&/g, '&') 332 .replace(/</g, '<') 333 .replace(/>/g, '>') 334 .replace(/"/g, '"') 335 .replace(/'/g, '''); 336 } 337 338 function normalizeNavPath(path) { 339 var p = String(path || '').trim(); 340 if (!p) { 341 return '/'; 342 } 343 if (p.indexOf('http://') === 0 || p.indexOf('https://') === 0) { 344 try { 345 p = new URL(p, window.location.href).pathname || '/'; 346 } catch (_urlErr) { 347 p = '/'; 348 } 349 } 350 p = p.split('?', 1)[0].replace(/\/+$/, '') || '/'; 351 if (p.indexOf('/pages/') === 0) { 352 p = '/' + p.slice('/pages/'.length).replace(/\.html?$/i, ''); 353 } 354 return p || '/'; 355 } 356 357 function initialNavbarPages() { 358 var bootstrap = window.__wizardrySiteBootstrap; 359 if (bootstrap && Array.isArray(bootstrap.navbar_pages) && bootstrap.navbar_pages.length) { 360 return bootstrap.navbar_pages; 361 } 362 try { 363 var cached = JSON.parse(localStorage.getItem('cached_navbar_pages_v1') || '[]'); 364 if (Array.isArray(cached) && cached.length) { 365 return cached; 366 } 367 } catch (_cacheErr) {
368 // Ignore invalid cached navbar rows. 369 } 370 return null; 371 } 372 373 function renderInitialNavbarPages() { 374 var pages = initialNavbarPages(); 375 if (!pages || !pages.length) { 376 return; 377 } 378 var current = normalizeNavPath(window.location.pathname); 379 var seen = {}; 380 var html = ''; 381 pages.forEach(function (page, index) { 382 var slug = String(page && page.slug || '').trim(); 383 var title = String(page && page.title || '').trim(); 384 var path = String(page && page.path || '').trim(); 385 if (!slug || !path || seen[slug]) { 386 return; 387 } 388 seen[slug] = true; 389 var active = normalizeNavPath(path) === current; 390 html += '<a href="' + esc(path) + '" data-page="' + esc(slug) + '" data-nav-rank="' + String(index + 1) + '"' + (active ? ' class="active" aria-current="page"' : '') + '>' + esc(title || slug) + '</a>'; 391 }); 392 if (!html) { 393 return; 394 } 395 navCenter.innerHTML = html; 396 navCenter.appendChild(menu); 397 } 398 399 renderInitialNavbarPages(); 400 401 var links = Array.prototype.slice.call(navCenter.querySelectorAll('a[data-page][href]')); 402 if (!links.length) { 403 return; 404 } 405 406 function rectVisible(rect) { 407 return !!rect && rect.width > 0 && rect.height > 0; 408 } 409 410 function rectsVerticallyOverlap(a, b) { 411 return !!(a && b && a.bottom > b.top && b.bottom > a.top); 412 } 413 414 function rightmostVisibleLinkRect() { 415 for (var idx = links.length - 1; idx >= 0; idx -= 1) { 416 var link = links[idx]; 417 if (link.classList.contains('is-nav-overflow-hidden')) { 418 continue; 419 } 420 var rect = link.getBoundingClientRect(); 421 if (rectVisible(rect)) { 422 return rect; 423 } 424 } 425 return null; 426 } 427 428 function navCollisionLeft() { 429 if (!navRight) { 430 return null; 431 } 432 var search = navRight.querySelector('.nav-search'); 433 var target = search && !search.hidden ? search : navRight; 434 var rect = target.getBoundingClientRect(); 435 if (!rectVisible(rect)) { 436 return null; 437 } 438 return rect.left; 439 } 440 441 function hasRightSideCollision() { 442 var linkRect = rightmostVisibleLinkRect(); 443 var collisionLeft = navCollisionLeft(); 444 if (!linkRect || collisionLeft === null) { 445 return false; 446 } 447 var centerRect = navCenter.getBoundingClientRect(); 448 var rightRect = navRight ? navRight.getBoundingClientRect() : null; 449 if (!rectsVerticallyOverlap(centerRect, rightRect)) { 450 return false; 451 } 452 return linkRect.right > (collisionLeft - 8); 453 } 454 455 function hasNavPressure() { 456 return navCenter.scrollWidth > (navCenter.clientWidth + 1) || hasRightSideCollision(); 457 } 458 459 links.forEach(function (link) { 460 link.classList.remove('is-nav-overflow-hidden'); 461 }); 462 menu.hidden = true; 463 panel.innerHTML = ''; 464 465 var useMobileOverflowTier = !!(window.matchMedia && window.matchMedia('(max-width: 780px)').matches); 466 if (useMobileOverflowTier) { 467 links.forEach(function (link) { 468 var rank = Number(link.getAttribute('data-nav-rank') || 0); 469 if (rank >= 6) { 470 link.classList.add('is-nav-overflow-hidden'); 471 } 472 }); 473 } 474 475 var activeLink = links.find(function (link) { 476 return link.classList.contains('active') || link.getAttribute('aria-current') === 'page'; 477 }) || null; 478 if (hasNavPressure()) { 479 menu.hidden = false; 480 var guard = 0; 481 while (hasNavPressure() && guard < links.length) { 482 var hide = null; 483 for (var i = links.length - 1; i >= 0; i -= 1) { 484 if (links[i].classList.contains('is-nav-overflow-hidden')) { 485 continue; 486 } 487 if (activeLink && links[i] === activeLink) { 488 continue; 489 } 490 hide = links[i]; 491 break; 492 } 493 if (!hide && activeLink && !activeLink.classList.contains('is-nav-overflow-hidden')) { 494 hide = activeLink; 495 } 496 if (!hide) { 497 break; 498 } 499 hide.classList.add('is-nav-overflow-hidden'); 500 guard += 1; 501 } 502 } 503 504 var hiddenLinks = links.filter(function (link) { 505 return link.classList.contains('is-nav-overflow-hidden'); 506 }); 507 if (!hiddenLinks.length) { 508 count.textContent = '0'; 509 count.hidden = true; 510 button.setAttribute('aria-label', 'More pages'); 511 menu.hidden = true; 512 return; 513 } 514 515 panel.innerHTML = ''; 516 hiddenLinks.forEach(function (link) { 517 var item = document.createElement('a'); 518 item.className = 'nav-menu-item'; 519 item.setAttribute('role', 'menuitem'); 520 item.href = link.getAttribute('href') || '/'; 521 item.textContent = String(link.textContent || '').trim() || 'Page'; 522 panel.appendChild(item); 523 }); 524 count.textContent = String(hiddenLinks.length); 525 count.hidden = false;
526 button.setAttribute('aria-label', 'More pages (' + String(hiddenLinks.length) + ' hidden)'); 527 menu.hidden = false; 528 } 529 530 seedInitialOverflowMenu(); 531})(); 532</script>
vendor: 1 bytes, line 532
532
533<script type="module"> 534(function () { 535 function setupExpandableSearch() { 536 var forms = document.querySelectorAll('form.nav-search'); 537 for (var i = 0; i < forms.length; i += 1) { 538 (function (form) { 539 if (!form || form.getAttribute('data-expandable-search-ready') === 'true') { 540 return; 541 } 542 form.setAttribute('data-expandable-search-ready', 'true'); 543 var input = form.querySelector('input[type="text"]'); 544 var button = form.querySelector('button[type="submit"], button:not([type])'); 545 if (!input || !button) { 546 return; 547 } 548 549 function hasValue() { 550 return String(input.value || '').trim().length > 0; 551 } 552 553 function setExpanded(expanded) { 554 var nav = form.closest ? form.closest('nav.site-nav') : null; 555 var nextExpanded = !!expanded || hasValue(); 556 form.classList.toggle('is-search-expanded', !!expanded); 557 form.classList.toggle('has-search-value', hasValue()); 558 if (nav) { 559 nav.classList.toggle('has-expanded-search', nextExpanded); 560 } 561 button.setAttribute('aria-expanded', expanded ? 'true' : 'false'); 562 } 563 564 function expand() { 565 setExpanded(true); 566 } 567 568 function collapseIfEmpty() { 569 var active = document.activeElement; 570 var hasFormFocus = !!(active && (active === form || form.contains(active))); 571 if (!hasValue() && !hasFormFocus) { 572 setExpanded(false); 573 } else { 574 setExpanded(true); 575 } 576 } 577 578 setExpanded(hasValue()); 579 input.addEventListener('focus', expand); 580 input.addEventListener('input', function () { 581 setExpanded(true); 582 }); 583 button.addEventListener('click', function (event) { 584 if (!form.classList.contains('is-search-expanded') && !hasValue()) { 585 event.preventDefault(); 586 expand(); 587 input.focus(); 588 } 589 }); 590 form.addEventListener('submit', function (event) { 591 if (!hasValue()) { 592 event.preventDefault(); 593 expand(); 594 input.focus(); 595 } 596 }); 597 document.addEventListener('pointerdown', function (event) { 598 if (!form.contains(event.target) && !hasValue()) { 599 setExpanded(false); 600 } 601 }); 602 })(forms[i]); 603 } 604 } 605 606 if (document.readyState === 'loading') { 607 document.addEventListener('DOMContentLoaded', setupExpandableSearch, { once: true }); 608 } else { 609 setupExpandableSearch(); 610 } 611})(); 612 613(function () { 614 function dedupeTopLevelNav() { 615 try { 616 var navs = document.querySelectorAll('nav.site-nav'); 617 if (navs && navs.length > 1) { 618 for (var i = 1; i < navs.length; i += 1) { 619 var node = navs[i]; 620 if (node && node.parentNode) { 621 node.parentNode.removeChild(node); 622 } 623 } 624 } 625 var skips = document.querySelectorAll('.skip-link'); 626 if (skips && skips.length > 1) { 627 for (var j = 1; j < skips.length; j += 1) { 628 var skip = skips[j]; 629 if (skip && skip.parentNode) { 630 skip.parentNode.removeChild(skip); 631 } 632 } 633 } 634 } catch (_dedupeErr) { 635 // Ignore non-fatal nav dedupe issues. 636 } 637 } 638 639 dedupeTopLevelNav(); 640 if (document.readyState === 'loading') { 641 document.addEventListener('DOMContentLoaded', dedupeTopLevelNav, { once: true }); 642 } else { 643 setTimeout(dedupeTopLevelNav, 0); 644 } 645 646 try { 647 var SITE_TITLE_CACHE_KEY = 'wizardry_blog_site_title_v1'; 648 var siteSignature = document.getElementById('nav-site-signature'); 649 function normalizeSiteTitle(value) { 650 var text = String(value || '').replace(/\s+/g, ' ').trim(); 651 return text || 'Site'; 652 } 653 function applySiteTitleSignature(value) { 654 if (!siteSignature) { 655 return; 656 } 657 var title = normalizeSiteTitle(value); 658 siteSignature.textContent = title; 659 siteSignature.setAttribute('title', title); 660 } 661 function syncSiteTitleDestination() { 662 if (!siteSignature || !siteSignature.setAttribute) { 663 return; 664 }
665 var firstNavLink = document.querySelector('.nav-center a[data-page][href]'); 666 var href = firstNavLink ? String(firstNavLink.getAttribute('href') || '').trim() : ''; 667 siteSignature.setAttribute('href', href || '/'); 668 } 669 try { 670 applySiteTitleSignature(localStorage.getItem(SITE_TITLE_CACHE_KEY) || ''); 671 } catch (_siteTitleErr) { 672 applySiteTitleSignature('Site'); 673 } 674 syncSiteTitleDestination(); 675 676 var token = String(localStorage.getItem('session_token') || '').trim(); 677 var hasToken = !!token && token !== 'null' && token !== 'undefined'; 678 var cachedPlayerName = String(localStorage.getItem('last_auth_player_name') || '').trim(); 679 var loginSplit = document.getElementById('nav-login-split'); 680 var userMenu = document.getElementById('nav-user-menu'); 681 var userName = document.getElementById('nav-user-name'); 682 var composeTools = document.getElementById('nav-compose-tools'); 683 var cachedIsAdmin = String(localStorage.getItem('last_auth_is_admin') || '') === '1'; 684 685 if (loginSplit) { 686 loginSplit.style.display = 'none'; 687 } 688 if (userMenu) { 689 userMenu.style.display = 'none'; 690 } 691 if (userName) { 692 userName.style.display = 'none'; 693 userName.textContent = ''; 694 userName.setAttribute('href', '/admin#account'); 695 } 696 697 if (hasToken) { 698 if (composeTools) { 699 composeTools.style.display = cachedIsAdmin ? 'inline-flex' : 'none'; 700 } 701 if (userMenu) { 702 userMenu.style.display = 'inline-flex'; 703 } 704 if (userName) { 705 userName.style.display = 'inline-block'; 706 userName.textContent = cachedPlayerName || 'signed-in'; 707 userName.setAttribute('aria-label', 'Open account settings'); 708 userName.setAttribute('href', '/admin#account'); 709 } 710 } else if (loginSplit) { 711 loginSplit.style.display = 'inline-flex'; 712 } 713 } catch (_err) { 714 // Ignore storage failures and let nav-auth.js reconcile state. 715 } 716 717 try {
718 var navCenter = document.querySelector('.nav-center'); 719 var cachedRaw = localStorage.getItem('cached_navbar_pages_v1'); 720 function normalizeNavPath(path) { 721 var p = String(path || '').trim(); 722 var search = ''; 723 if (!p) { 724 return '/'; 725 } 726 if (p.indexOf('http://') === 0 || p.indexOf('https://') === 0) { 727 try { 728 var parsed = new URL(p, window.location.href); 729 p = parsed.pathname || '/'; 730 search = parsed.search || ''; 731 } catch (_urlErr) { 732 p = '/'; 733 search = ''; 734 } 735 } 736 if (!search && p.indexOf('?') >= 0) { 737 var split = p.split('?', 2); 738 p = split[0] || '/'; 739 search = split[1] ? ('?' + split[1]) : ''; 740 } 741 p = p.replace(/\/+$/, '') || '/'; 742 if (p === '/pages/index' || p === '/pages/index.html') { 743 try { 744 var params = new URLSearchParams(search || ''); 745 var slug = String(params.get('page_slug') || params.get('slug') || '').trim().toLowerCase(); 746 slug = slug.replace(/[^a-z0-9-]+/g, '-').replace(/-+/g, '-').replace(/^-+|-+$/g, ''); 747 if (slug && slug !== 'index') { 748 return '/' + slug; 749 } 750 } catch (_paramErr) { 751 // Ignore malformed page query strings. 752 } 753 return '/'; 754 } 755 if (p.indexOf('/pages/') === 0) { 756 p = '/' + p.slice('/pages/'.length); 757 p = p.replace(/\.html?$/i, ''); 758 } 759 return p || '/'; 760 } 761 function highlightCurrentNavNow() { 762 if (!navCenter) { 763 return; 764 } 765 var current = normalizeNavPath(window.location.href); 766 if (current.indexOf('/posts/') === 0 || current === '/cgi/blog-open-post' || current.indexOf('/cgi/blog-open-post/') === 0) { 767 current = '/'; 768 } 769 var links = navCenter.querySelectorAll('a[data-page]'); 770 var selected = null; 771 links.forEach(function (link) { 772 var active = !selected && normalizeNavPath(link.getAttribute('href') || '') === current; 773 if (active) { 774 selected = link; 775 } 776 link.classList.toggle('active', active); 777 if (active) { 778 link.setAttribute('aria-current', 'page'); 779 link.removeAttribute('aria-disabled'); 780 link.removeAttribute('tabindex'); 781 } else { 782 link.removeAttribute('aria-current'); 783 link.removeAttribute('aria-disabled'); 784 link.removeAttribute('tabindex'); 785 } 786 }); 787 } 788 function collapseOverflowingNavLinksNow() { 789 if (!navCenter) { 790 return; 791 } 792 var links = Array.prototype.slice.call(navCenter.querySelectorAll('a[data-page]')); 793 if (links.length < 2) { 794 return; 795 } 796 links.forEach(function (link) { 797 link.classList.remove('is-nav-overflow-hidden'); 798 }); 799 var activeLink = links.find(function (link) { 800 return link.classList.contains('active'); 801 }) || null; 802 var guard = 0; 803 while (navCenter.scrollWidth > (navCenter.clientWidth + 1) && guard < links.length) { 804 var hide = null; 805 for (var i = links.length - 1; i >= 0; i -= 1) { 806 if (links[i].classList.contains('is-nav-overflow-hidden')) { 807 continue; 808 } 809 if (activeLink && links[i] === activeLink) { 810 continue; 811 } 812 hide = links[i]; 813 break; 814 } 815 if (!hide && activeLink && !activeLink.classList.contains('is-nav-overflow-hidden')) { 816 hide = activeLink; 817 } 818 if (!hide) { 819 break; 820 } 821 hide.classList.add('is-nav-overflow-hidden'); 822 guard += 1; 823 } 824 } 825 function syncInitialOverflowPanelNow() { 826 var overflowMenu = document.getElementById('nav-overflow-menu'); 827 var overflowButton = document.getElementById('nav-overflow-btn'); 828 var overflowCount = document.getElementById('nav-overflow-count'); 829 var overflowPanel = document.getElementById('nav-overflow-panel'); 830 if (!overflowMenu || !overflowButton || !overflowCount || !overflowPanel) { 831 return; 832 } 833 var hiddenLinks = Array.prototype.slice.call(navCenter.querySelectorAll('a[data-page].is-nav-overflow-hidden')); 834 overflowPanel.innerHTML = ''; 835 hiddenLinks.forEach(function (link) { 836 var item = document.createElement('a'); 837 item.className = 'nav-menu-item'; 838 item.setAttribute('role', 'menuitem'); 839 item.href = link.getAttribute('href') || '/'; 840 item.textContent = String(link.textContent || '').trim() || 'Page'; 841 overflowPanel.appendChild(item); 842 }); 843 if (!hiddenLinks.length) { 844 overflowCount.textContent = '0'; 845 overflowCount.hidden = true; 846 overflowButton.setAttribute('aria-label', 'More pages'); 847 overflowMenu.hidden = true; 848 return; 849 } 850 overflowCount.textContent = String(hiddenLinks.length); 851 overflowCount.hidden = false;
852 overflowButton.setAttribute('aria-label', 'More pages (' + String(hiddenLinks.length) + ' hidden)'); 853 overflowMenu.hidden = false; 854 } 855 if (navCenter && cachedRaw) { 856 var cachedPages = JSON.parse(cachedRaw); 857 if (!Array.isArray(cachedPages)) { 858 cachedPages = []; 859 } 860 var basePages = [ 861 { slug: 'index', title: 'Writing', path: '/' } 862 ]; 863 var seen = {}; 864 var html = ''; 865 function esc(text) { 866 return String(text || '') 867 .replace(/&/g, '&') 868 .replace(/</g, '<') 869 .replace(/>/g, '>') 870 .replace(/"/g, '"') 871 .replace(/'/g, '''); 872 } 873 basePages.forEach(function (page) { 874 seen[page.slug] = true; 875 html += '<a href="' + esc(page.path) + '" data-page="' + esc(page.slug) + '">' + esc(page.title) + '</a>'; 876 }); 877 cachedPages.forEach(function (page) { 878 var slug = String(page && page.slug || '').trim(); 879 var title = String(page && page.title || '').trim(); 880 var path = String(page && page.path || '').trim(); 881 if (!slug || !path || seen[slug]) { 882 return; 883 } 884 seen[slug] = true; 885 html += '<a href="' + esc(path) + '" data-page="' + esc(slug) + '">' + esc(title || slug) + '</a>'; 886 }); 887 if (html) { 888 var overflowMenu = document.getElementById('nav-overflow-menu'); 889 navCenter.innerHTML = html; 890 if (overflowMenu) { 891 navCenter.appendChild(overflowMenu); 892 } 893 syncSiteTitleDestination(); 894 } 895 } 896 highlightCurrentNavNow(); 897 collapseOverflowingNavLinksNow(); 898 syncInitialOverflowPanelNow(); 899 } catch (_err2) { 900 // Ignore cache parse failures and let runtime fetch reconcile state. 901 } 902 903 document.addEventListener('DOMContentLoaded', function () { 904 var hasDynamicNostrPage = !!( 905 document.getElementById('blog-page-root') || 906 document.getElementById('nip23-page-root') || 907 document.getElementById('list-page-root') || 908 document.getElementById('public-ranking-root') || 909 document.getElementById('overworld-page-root') || 910 document.getElementById('contact-page-root') || 911 document.getElementById('archive-page-root') || 912 document.getElementById('tags-page-root') || 913 document.getElementById('search-page-root') || 914 document.getElementById('admin-panel') 915 ); 916 if (hasDynamicNostrPage) { 917 return; 918 } 919 var gate = window.__wizardryHydration; 920 if (gate && typeof gate.markPageReady === 'function') { 921 gate.markPageReady(); 922 } 923 }); 924})(); 925</script>
925 926 927<div id="nav-top-toast-host" class="nav-top-toast-host" aria-live="polite" aria-atomic="true"></div> 928<aside id="nav-cart-drawer" class="nav-cart-drawer" hidden> 929 <div class="nav-cart-drawer-head"> 930 <h2>Shopping Cart</h2> 931 <button id="nav-cart-close" type="button" aria-label="Close cart">×</button> 932 </div> 933 <p id="nav-cart-empty" class="nav-cart-empty">Your cart is empty.</p> 934 <ul id="nav-cart-items" class="nav-cart-items"></ul> 935 <div class="nav-cart-drawer-footer"> 936 <div class="nav-cart-subtotal-row"><span>Subtotal</span><strong id="nav-cart-subtotal">$0.00</strong></div> 937 <div class="nav-cart-drawer-links"> 938 <a href="/cart" class="nav-cart-link-button">View Cart</a> 939 <a href="/checkout" class="nav-cart-link-button nav-cart-link-button-primary">Checkout</a> 940 </div> 941 </div> 942</aside> 943
944<script defer src="/static/vendor/citrine-nostr-web.js?v=1376469157"></script>
vendor: 1 bytes, line 944
944
945<script defer src="/static/nav-auth.js?v=1376469157"></script>
vendor: 1 bytes, line 945
945
946<script defer src="/static/shop-cart.js?v=1376469157"></script>
vendor: 1 bytes, line 946
946
947<script async src="https://cdn.jsdelivr.net/npm/[email protected]/lib/nostr.bundle.js"></script>
vendor: 1 bytes, line 947
947
948<script async src="https://cdn.jsdelivr.net/npm/qrcodejs/qrcode.min.js"></script>
948 949<header id="title-block-header"> 950<h1 class="title">Checkout</h1> 951<p class="author">author</p> 952</header> 953<section id="checkout-page-root" class="checkout-shell" data-page-slug="checkout" data-page-type="checkout"> 954<div class="checkout-head"> 955<h1> 956Checkout 957</h1> 958<p> 959Choose BTCPay or credit card, then complete payment in-panel. 960</p> 961</div> 962<div id="checkout-page-content" class="checkout-page-content"> 963 964</div> 965</section>
966<script src="/static/checkout-page.js?v=1376469157"></script>
966 967<footer class="site-footer"> 968 <nav id="footer-pages" class="footer-pages" aria-label="Footer pages" hidden></nav> 969 <div class="footer-feeds" aria-label="Syndication feeds"> 970 <a href="/rss.xml" class="footer-feed-link" aria-label="RSS feed" title="RSS feed"> 971 <svg width="15" height="15" viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"> 972 <circle cx="6" cy="18" r="2.2" fill="currentColor"/> 973 <path d="M4 10a10 10 0 0 1 10 10" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round"/> 974 <path d="M4 4a16 16 0 0 1 16 16" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round"/> 975 </svg> 976 <span>RSS</span> 977 </a> 978 <a href="/atom.xml" class="footer-feed-link" aria-label="Atom feed" title="Atom feed"> 979 <svg width="15" height="15" viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"> 980 <circle cx="12" cy="12" r="2.1" fill="currentColor"/> 981 <ellipse cx="12" cy="12" rx="8.6" ry="3.6" fill="none" stroke="currentColor" stroke-width="1.6"/> 982 <ellipse cx="12" cy="12" rx="8.6" ry="3.6" transform="rotate(60 12 12)" fill="none" stroke="currentColor" stroke-width="1.6"/> 983 <ellipse cx="12" cy="12" rx="8.6" ry="3.6" transform="rotate(120 12 12)" fill="none" stroke="currentColor" stroke-width="1.6"/> 984 </svg> 985 <span>Atom</span> 986 </a> 987 <span class="footer-version" aria-label="Site version">v0.7.60</span> 988 <a href="https://github.com/andersaamodt/gazeta" class="footer-feed-link" aria-label="GitHub repository" title="GitHub repository" rel="noopener noreferrer"> 989 <svg width="15" height="15" viewBox="0 0 24 24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"> 990 <path fill="currentColor" d="M12 1C5.93 1 1 5.93 1 12c0 4.86 3.15 8.98 7.52 10.44.55.1.75-.24.75-.53 0-.26-.01-1.13-.02-2.05-3.06.66-3.71-1.3-3.71-1.3-.5-1.27-1.22-1.61-1.22-1.61-.99-.68.08-.66.08-.66 1.1.08 1.68 1.13 1.68 1.13.98 1.67 2.56 1.19 3.19.91.1-.71.38-1.19.7-1.47-2.44-.28-5.01-1.22-5.01-5.43 0-1.2.43-2.18 1.13-2.94-.11-.28-.49-1.4.11-2.91 0 0 .92-.29 3.02 1.13.88-.24 1.82-.37 2.75-.37.93 0 1.87.12 2.75.37 2.1-1.42 3.02-1.13 3.02-1.13.6 1.51.22 2.63.11 2.91.7.77 1.13 1.74 1.13 2.94 0 4.22-2.57 5.15-5.02 5.42.39.34.74 1.01.74 2.04 0 1.47-.01 2.66-.01 3.02 0 .29.2.64.76.53A11.01 11.01 0 0 0 23 12c0-6.07-4.93-11-11-11Z"/> 991 </svg> 992 <span>GitHub</span> 993 </a> 994 </div> 995</footer>
996<script defer src="/static/footer-pages.js?v=1376469157"></script>
996 997</body> 998</html>
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.