- Scroll-progress bar: drive scaleX from scroll progress via callback form;
the animation form snapped the bar to 0 at the bottom (progress=1 boundary)
- Nav active-underline: recompute active section from scroll position each
frame so it tracks upward scroll too (inView-enter died on the way back up)
- Add a Writing section to the homepage with recent posts + a blog CTA
- New projects tagline + open-minded lead
- Split the combined infra project: keep the estate/cloud modernisation,
add a dedicated Network Automation at Fleet Scale case (Unimus + NetBox,
config backup, bulk push, vaulted+rotated credentials) from the Linde role
- Add the secret-zero bootstrap-chain diagram (was a broken image ref)
- Remove the corner sparkle artifact from all six blog hero images
- Bump hero/diagram cache-bust params so the updated assets serve
outbound-only-exposure (corrected sealed-vault image) + secret-zero (the seed-
key circuit-tree, _R revision). Both verified against their prompts, optimized
to webp (17KB / ~120KB). Completes hero coverage for all 6 posts.
Add an optional hero field to the blog schema; render it on the post page and
as the index card thumbnail. Ship 4 verified Nano Banana hero images (shipping/
init-gating/authentik/workload) as optimized webp (64-134KB). Publish the
secret-zero post. (outbound hero pending — its file was a dup of shipping;
secret-zero hero pending generation.)
Themed thin scrollbar (cyan→magenta thumb, Firefox + WebKit), an on-brand glow
halo on the keyboard focus ring (solid outline keeps WCAG visibility), and a 1px
inner top highlight so cards read raised at rest. CSS-only, token-pure.
Unify scroll reveals, hero entrance, nav active-underline, button springs,
the scroll-progress bar and backdrop parallax under one Motion system
(src/scripts/anim.ts), bundled into a self-hosted /_astro module so CSP
script-src 'self' holds. Progress bar + parallax now scroll()-driven and
cross-browser (was Chromium-only animation-timeline). Fail-open, reduced-motion
aware, content fully visible with JS off.
The tab logo and social preview were still on the old teal palette. Retone both
to the electric cyan→magenta theme matching the hero nameplate:
- favicon.svg: jw monogram + prompt-line + cursor on a cyan→magenta gradient.
- og.png (gen-og.mjs): name in the cyan→violet→magenta hero gradient, cyan
eyebrow/separators, magenta URL, cyan→magenta top bar + dual corner glows.
- bump ?v=2 on both refs (public/ assets are CF-edge-cached + social platforms
cache OG hard) so the new art shows immediately.
The hero name was a mostly---text gradient with a thin accent sweep; in light
mode it rested on low-contrast tones and the body text-halo washed it to a ghost.
Replace with a full cyan→violet→magenta fill driven by the theme-aware accent
tokens (deep on light, bright on dark) so it's unmissable in either mode, plus a
tight dark edge-shadow for legibility, the electric glow, and a one-shot light
sheen that parks off-screen. Opt the title out of the light text-halo.
Light mode: revert the heavy white-out scrim back to a moderate wash so the
board stays visible, and earn legibility with a soft light text-halo behind
running text instead (invisible on the solid cards, only works over the image).
Pairs with the darker light-mode text tokens.
Also append ?v=2 to every /diagrams/*.svg reference so the recoloured diagrams
bypass Cloudflare's 4h edge cache and show immediately (the SVG URLs aren't
content-hashed like the CSS bundle).
Body text washed out in light mode — the secondary/tertiary text tokens were
too light against the bright sandstone board image. Darken light --text-dim and
--text-faint, and heavily strengthen the light-theme scrim so the board drops
to a faint texture behind content. Dark mode unchanged.
CSS animation-timeline: scroll() is Chromium-only, so the backdrop didn't move
for non-Chromium browsers. Replace it with a tiny rAF-throttled scroll handler
in site.js (the existing same-origin script — CSP stays strict, no inline JS)
that drives a --bg-shift CSS var off scroll position. The board now pans
vertically in lock-step with scroll and sits still at rest, in all browsers.
The backdrop's only motion was the scroll-driven pan (animation-timeline:
scroll()), which is Chromium-only — so in Firefox/Safari the board sat dead
still. Add a continuous timed top↔bottom drift (48s, alternates) as the
universal baseline; keep the scroll-coupled pan as a Chromium enhancement that
overrides it. Motion-safe: both gated behind prefers-reduced-motion.
The S→E→SE→NE loop wandered back near its start, so on a long page the
per-screen movement was imperceptible (worse once the image was zoomed to
215%). Replace it with a single continuous vertical pan (~40% travel) so the
board obviously drifts downward as the page scrolls.
- Backdrop image scaled 168% → 215% so the Bat-Computer board reads bigger
and more immersive, with more room for the scroll-pan.
- Retitle the least-privilege post "The most secure credential is the one
you never mount" → "Every pod holds a key to a door it never opens" so it
no longer mirrors the "...inbound port is the one you never open" post.
Least-privilege for Kubernetes workloads — own ServiceAccount + no auto-mounted
API token, then non-root + dropped caps, then Pod Security as the enforced floor.
Adds a matching house-style SVG diagram (workload-least-privilege).
All JS moved to external /site.js → script-src 'self' with no inline JS,
hashes or eval. Full header set via nginx (CSP, nosniff, frame-deny,
referrer, permissions, COOP/CORP); HSTS stays at the CF edge. Shared
headers include avoids the location add_header reset footgun. Build-time
secret/inline-script/third-party scan gate. SECURITY.md documents posture.
Hand-authored inline-SVG Diagram component (no runtime JS, CSP-clean,
themeable) rendering edge-AI, IaC-fleet and homelab architectures on the
case studies. Staggered CSS hero entrance, motion-aware.
Projects + blog as schema-validated content collections; structured case
studies (problem/design/outcome), blog with tag pages, reading time, RSS
feed (drafts excluded), sitemap, and Shiki dual-theme code highlighting.
Real career history (Woolworths, Virtus Health, Linde, ELGAS, Darktime),
cloud-heavy skills matrix, education, LinkedIn, Sydney location, and
projects mapped to actual work. OG subtitle now smaller italic serif.