commit ed9703176742c3c3c03bb51238ce91f8b0ab6d80
parent 0d9c4b430d95a3a919866ec4a1956144917b1202
Author: $: DAΞMON <zer0sec.xp@icloud.com>
Date: Sat, 15 Aug 2026 20:29:25 +0100
π§ Update [main] | 15 Aug 2026 20:29:25 BST
π Stats: +336 / -3 across 9 file(s)
π Breakdown: β2 βοΈ7 ποΈ0 π0
π€ Author: $: DAΞMON
π Changes:
βοΈ Modified package-lock.json
βοΈ Modified package.json
βοΈ Modified src/components/Header.astro
βοΈ Modified src/pages/index.astro
βοΈ Modified src/scripts/app.ts
βοΈ Modified src/styles/global.css
βοΈ Modified src/styles/tokens.css
β Added test/homepage-mirrors.test.mjs
β Added test/mobile-nav.test.mjs
π Line changes per file:
β’ package-lock.json +95 -0
β’ package.json +2 -0
β’ src/components/Header.astro +22 -0
β’ src/pages/index.astro +21 -1
β’ src/scripts/app.ts +32 -0
β’ src/styles/global.css +94 -2
β’ src/styles/tokens.css +4 -0
β’ test/homepage-mirrors.test.mjs +20 -0
β’ test/mobile-nav.test.mjs +46 -0
Diffstat:
9 files changed, 336 insertions(+), 3 deletions(-)
diff --git a/package-lock.json b/package-lock.json
@@ -14,6 +14,7 @@
},
"devDependencies": {
"github-slugger": "^2.0.0",
+ "happy-dom": "^20.11.2",
"pagefind": "^1.3.0"
}
},
@@ -1836,6 +1837,23 @@
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
"license": "MIT"
},
+ "node_modules/@types/whatwg-mimetype": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz",
+ "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/ws": {
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@ungap/structured-clone": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz",
@@ -2159,6 +2177,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/buffer-image-size": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/buffer-image-size/-/buffer-image-size-0.6.4.tgz",
+ "integrity": "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/camelcase": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz",
@@ -2924,6 +2955,38 @@
"uncrypto": "^0.1.3"
}
},
+ "node_modules/happy-dom": {
+ "version": "20.11.2",
+ "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.11.2.tgz",
+ "integrity": "sha512-7MB+bJLkxu3SowAfBJbjW+c55kNz5tkR45gu2qzrxznezhLeN5YIlJbwUgSzlGc+qWoZ8Ykg71H5ezz69xixrw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": ">=20.0.0",
+ "@types/whatwg-mimetype": "^3.0.2",
+ "@types/ws": "^8.18.1",
+ "buffer-image-size": "^0.6.4",
+ "entities": "^7.0.1",
+ "whatwg-mimetype": "^3.0.0",
+ "ws": "^8.21.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/happy-dom/node_modules/entities": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+ "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/hast-util-from-html": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
@@ -6384,6 +6447,16 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/whatwg-mimetype": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+ "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/which-pm-runs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz",
@@ -6425,6 +6498,28 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/ws": {
+ "version": "8.21.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
+ "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/xxhash-wasm": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz",
diff --git a/package.json b/package.json
@@ -7,6 +7,7 @@
"scripts": {
"dev": "astro dev",
"build": "astro build && pagefind --site dist && npm run pagefind:public",
+ "test": "astro build && node --test",
"preview": "astro preview",
"pagefind:public": "rm -rf public/pagefind && cp -R dist/pagefind public/pagefind",
"astro": "astro"
@@ -18,6 +19,7 @@
},
"devDependencies": {
"github-slugger": "^2.0.0",
+ "happy-dom": "^20.11.2",
"pagefind": "^1.3.0"
}
}
diff --git a/src/components/Header.astro b/src/components/Header.astro
@@ -68,8 +68,30 @@ const isActive = (href: string, exact?: boolean) => {
<a class="icon-btn" href={GITHUB} target="_blank" rel="noopener" aria-label="GitHub repository">
<Icon name="github" />
</a>
+ <button
+ class="icon-btn mobile-nav-trigger"
+ data-mobile-nav-toggle
+ type="button"
+ aria-label="Open navigation"
+ aria-controls="mobile-primary-nav"
+ aria-expanded="false"
+ >
+ <span class="mobile-nav-glyph" aria-hidden="true"><i></i><i></i><i></i></span>
+ </button>
</div>
</div>
+
+ <nav id="mobile-primary-nav" class="mobile-nav" data-mobile-nav aria-label="Primary mobile" hidden>
+ {NAV.map((item) => (
+ <a
+ href={item.href}
+ style={`--acc: var(--${item.acc});`}
+ aria-current={isActive(item.href, item.exact) ? 'page' : undefined}
+ >
+ <span class="n">{item.n}</span><span class="lbl">{item.label}</span>
+ </a>
+ ))}
+ </nav>
</header>
<style>
diff --git a/src/pages/index.astro b/src/pages/index.astro
@@ -8,6 +8,7 @@ import Icon from '../components/Icon.astro';
import { CATEGORIES, categoryOf } from '../lib/taxonomy';
import { allSheets, categoryCounts, sheetHref } from '../lib/sheets';
import { payloadsByTopic } from '../lib/payloads';
+import { internalBySection, internalRootPages } from '../lib/internal';
import { url } from '../lib/url';
const sheets = await allSheets();
@@ -18,6 +19,10 @@ const domains = CATEGORIES.filter((c) => (counts[c.slug] ?? 0) > 0).length;
const payloadTopics = await payloadsByTopic();
const payloadPages = payloadTopics.reduce((n, g) => n + g.count, 0);
+const internalSections = await internalBySection();
+const internalRoot = await internalRootPages();
+const internalPages = internalSections.reduce((n, g) => n + g.count, 0) + internalRoot.length;
+
const marqueeItems = CATEGORIES.map((cat) => ({ cat, count: counts[cat.slug] ?? 0 }));
const featured = [...sheets]
@@ -71,13 +76,28 @@ const featured = [...sheets]
</div>
</a>
+ <a class="cta-band cta-band--internal bleed section" href={url('internal')}>
+ <div class="wrap cta-band__body">
+ <div>
+ <p class="cta-band__eyebrow">03 ^: Full mirror Β· credit upstream</p>
+ <h2>InternalAllTheThings</h2>
+ <p>
+ The complete {internalSections.length}-section, {internalPages}-page internal-network
+ reference by <strong>swisskyrepo</strong> β Active Directory, cloud, containers and
+ red-team tradecraft, mirrored on-site and searchable offline.
+ </p>
+ </div>
+ <span class="btn">Browse internal <Icon name="arrow" /></span>
+ </div>
+ </a>
+
{featured.length > 0 && (
<div class="wrap">
<section class="section" id="featured">
<div class="section-head">
<div>
<p class="eyebrow" style="--acc: var(--gold);">
- <span class="eyebrow__n">03</span>
+ <span class="eyebrow__n">04</span>
<span class="eyebrow__mark">^:</span>
<span>Freshly modernized</span>
<span class="eyebrow__rule" aria-hidden="true"></span>
diff --git a/src/scripts/app.ts b/src/scripts/app.ts
@@ -43,6 +43,37 @@ function initTheme(): void {
});
}
+function initMobileNav(): void {
+ const toggles = document.querySelectorAll<HTMLButtonElement>('[data-mobile-nav-toggle]');
+ toggles.forEach((toggle) => {
+ if (toggle.dataset.bound) return;
+ const menuId = toggle.getAttribute('aria-controls');
+ const menu = menuId ? document.getElementById(menuId) : null;
+ if (!menu) return;
+
+ const setOpen = (open: boolean): void => {
+ toggle.setAttribute('aria-expanded', String(open));
+ toggle.setAttribute('aria-label', open ? 'Close navigation' : 'Open navigation');
+ menu.hidden = !open;
+ };
+
+ toggle.dataset.bound = '1';
+ toggle.addEventListener('click', () => {
+ setOpen(toggle.getAttribute('aria-expanded') !== 'true');
+ });
+
+ menu.addEventListener('click', (event) => {
+ if ((event.target as Element).closest('a')) setOpen(false);
+ });
+
+ toggle.closest('.site-header')?.addEventListener('keydown', (event) => {
+ if (event.key !== 'Escape' || toggle.getAttribute('aria-expanded') !== 'true') return;
+ setOpen(false);
+ toggle.focus();
+ });
+ });
+}
+
/**
* Every code block becomes the archive's terminal block: the language at
* the left of a caption bar, the copy control at the right, both in the
@@ -137,6 +168,7 @@ function initTOC(): void {
function init(): void {
initTheme();
+ initMobileNav();
enhanceCode();
wrapTables();
initTOC();
diff --git a/src/styles/global.css b/src/styles/global.css
@@ -148,6 +148,76 @@ main, .site-header, .site-footer { position: relative; z-index: 2; }
@media (max-width: 900px) { .mast-nav .lbl { display: none; } }
@media (max-width: 640px) { .mast-nav { display: none; } }
+.icon-btn.mobile-nav-trigger { display: none; }
+.mobile-nav-glyph {
+ display: grid;
+ gap: 4px;
+ width: 16px;
+}
+.mobile-nav-glyph i {
+ display: block;
+ width: 100%;
+ height: 1px;
+ background: currentColor;
+ transform-origin: center;
+ transition: transform 180ms ease, opacity 140ms ease;
+}
+.mobile-nav-trigger[aria-expanded='true'] .mobile-nav-glyph i:first-child {
+ transform: translateY(5px) rotate(45deg);
+}
+.mobile-nav-trigger[aria-expanded='true'] .mobile-nav-glyph i:nth-child(2) { opacity: 0; }
+.mobile-nav-trigger[aria-expanded='true'] .mobile-nav-glyph i:last-child {
+ transform: translateY(-5px) rotate(-45deg);
+}
+
+.mobile-nav { display: none; }
+@media (max-width: 640px) {
+ .icon-btn.mobile-nav-trigger { display: grid; }
+ .mobile-nav:not([hidden]) {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ right: 0;
+ display: grid;
+ background: var(--base);
+ border-bottom: 1px solid var(--fg);
+ }
+ .mobile-nav a {
+ position: relative;
+ display: grid;
+ grid-template-columns: 2.25rem 1fr;
+ align-items: center;
+ gap: 0.8rem;
+ min-height: 48px;
+ padding: 0.65rem clamp(1.15rem, 3.2vw, 2.75rem);
+ border-bottom: 1px solid var(--rule);
+ font-family: var(--font-mono);
+ font-size: 11px;
+ letter-spacing: var(--track-micro);
+ text-transform: uppercase;
+ color: var(--fg-dim);
+ }
+ .mobile-nav a:last-child { border-bottom: 0; }
+ .mobile-nav a::before {
+ content: '';
+ position: absolute;
+ inset: 0 auto 0 0;
+ width: 3px;
+ background: var(--acc);
+ transform: scaleY(0);
+ transform-origin: 50% 100%;
+ transition: transform 180ms var(--ease-in);
+ }
+ .mobile-nav a:hover,
+ .mobile-nav a[aria-current='page'] {
+ color: var(--fg);
+ background: color-mix(in oklab, var(--acc) 9%, transparent);
+ }
+ .mobile-nav a:hover::before,
+ .mobile-nav a[aria-current='page']::before { transform: scaleY(1); }
+ .mobile-nav .n { color: var(--acc); }
+}
+
.mast-actions {
display: flex;
align-items: center;
@@ -185,6 +255,26 @@ main, .site-header, .site-footer { position: relative; z-index: 2; }
.search-trigger .st-label { display: none; }
@media (min-width: 560px) { .search-trigger .st-label { display: inline; } }
+@media (max-width: 420px) {
+ .site-header .wrap {
+ gap: 0.35rem;
+ padding-inline: 0.65rem;
+ }
+ .brand { font-size: 0.93rem; }
+ .mast-actions {
+ gap: 0.25rem;
+ padding-left: 0.35rem;
+ }
+ .icon-btn,
+ .search-trigger {
+ width: 30px;
+ height: 30px;
+ padding: 0;
+ }
+ .search-trigger { justify-content: center; }
+ .search-trigger kbd { display: none; }
+}
+
/* ---- Nav rail (desktop) -------------------------------------------------- */
.layout { display: grid; grid-template-columns: 1fr; gap: 2.5rem; }
@media (min-width: 960px) {
@@ -728,11 +818,13 @@ main, .site-header, .site-footer { position: relative; z-index: 2; }
/* ---- Payloads call-to-action band ---------------------------------------- */
.cta-band {
+ --cta-ground: var(--band-ledger);
display: block;
- background: var(--band-ledger);
+ background: var(--cta-ground);
border-block: 1px solid var(--fg);
color: #faf4ed;
}
+.cta-band--internal { --cta-ground: var(--band-internal); }
.cta-band__body {
display: flex; align-items: center; justify-content: space-between;
gap: 1.6rem; flex-wrap: wrap;
@@ -758,7 +850,7 @@ main, .site-header, .site-footer { position: relative; z-index: 2; }
border-color: rgba(250, 244, 237, 0.5);
flex: none;
}
-.cta-band:hover .btn { background: #faf4ed; color: var(--band-ledger); border-color: #faf4ed; }
+.cta-band:hover .btn { background: #faf4ed; color: var(--cta-ground); border-color: #faf4ed; }
/* ---- Sheet page ---------------------------------------------------------- */
/* Same measure as the body below it, so the title, the rule under the
diff --git a/src/styles/tokens.css b/src/styles/tokens.css
@@ -181,6 +181,10 @@
/* The ledger band, far enough down the page that the two never share a
sightline. Cream on it: 7.04:1. */
--band-ledger: #015a77;
+ /* InternalAllTheThings is the Payloads mirror's companion, not a second
+ copy of it. A pine ground keeps the pair related while giving each
+ reference a distinct address on the homepage. Cream on it: 7.33:1. */
+ --band-internal: #28594f;
/* The plate ground the section banners and code blocks are drawn on,
and its scrim channels β the canvas reads these to erase its own
edges under the title. */
diff --git a/test/homepage-mirrors.test.mjs b/test/homepage-mirrors.test.mjs
@@ -0,0 +1,20 @@
+import assert from 'node:assert/strict';
+import { readFile } from 'node:fs/promises';
+import test from 'node:test';
+import { Window } from 'happy-dom';
+
+test('the homepage features both mirrored references', async () => {
+ const html = await readFile(new URL('../dist/index.html', import.meta.url), 'utf8');
+ const window = new Window();
+ window.document.write(html);
+
+ const bands = [...window.document.querySelectorAll('a.cta-band')];
+ const internal = bands.find((band) => band.getAttribute('href')?.endsWith('/internal'));
+
+ assert.equal(bands.length, 2);
+ assert.ok(internal, 'InternalAllTheThings feature band is missing');
+ assert.match(internal.textContent, /03\s+\^:\s+Full mirror Β· credit upstream/i);
+ assert.match(internal.textContent, /InternalAllTheThings/i);
+ assert.match(internal.textContent, /9-section, 175-page/i);
+ assert.match(internal.textContent, /Browse internal/i);
+});
diff --git a/test/mobile-nav.test.mjs b/test/mobile-nav.test.mjs
@@ -0,0 +1,46 @@
+import assert from 'node:assert/strict';
+import test from 'node:test';
+import { Window } from 'happy-dom';
+
+test('mobile navigation follows accessible open and close state transitions', async () => {
+ const window = new Window({ url: 'https://example.test/internal' });
+ globalThis.window = window;
+ globalThis.document = window.document;
+ globalThis.localStorage = window.localStorage;
+
+ document.body.innerHTML = `
+ <header class="site-header">
+ <button
+ type="button"
+ data-mobile-nav-toggle
+ aria-controls="mobile-primary-nav"
+ aria-expanded="false"
+ >Menu</button>
+ <nav id="mobile-primary-nav" data-mobile-nav hidden>
+ <a href="/payloads">Payloads</a>
+ <a href="/internal" aria-current="page">Internal</a>
+ </nav>
+ </header>
+ `;
+
+ await import('../src/scripts/app.ts');
+
+ const trigger = document.querySelector('[data-mobile-nav-toggle]');
+ const menu = document.querySelector('[data-mobile-nav]');
+ trigger.click();
+
+ assert.equal(trigger.getAttribute('aria-expanded'), 'true');
+ assert.equal(menu.hidden, false);
+
+ menu.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
+
+ assert.equal(trigger.getAttribute('aria-expanded'), 'false');
+ assert.equal(menu.hidden, true);
+ assert.equal(document.activeElement, trigger);
+
+ trigger.click();
+ menu.querySelector('a[aria-current="page"]').click();
+
+ assert.equal(trigger.getAttribute('aria-expanded'), 'false');
+ assert.equal(menu.hidden, true);
+});