This changelog covers changes to the site theme and design. It does not track changes to individual blog posts or article content. Note: the site theme is not licensed for copying or modification.
2026-08-11
Reading experience
- Reading progress bar — posts with a 6+ minute reading time now show a topbar progress indicator that fills as the article is scrolled; position is recalculated on scroll and resize, the topbar is made
stickyso the bar stays visible, and the effect is skipped underprefers-reduced-motion - Collapsible tablet TOC — post pages gain a collapsible table of contents for tablet-width viewports; the TOC script now populates and keeps both the tablet and desktop navigation states in sync
- Copy-action toast feedback — copying a post link or a code block now shows a toast notification, including a clearer failure message when clipboard access is unavailable
Navigation & accessibility
- Mobile nav toggle state — the mobile sidebar toggle now supports distinct menu/close icons and truly toggles open/closed on each click;
aria-expandedandaria-labelare kept in sync with the current state - Breadcrumbs on tag/category pages — the category and tag listing layouts gain a breadcrumb trail styled for dark, light, and accessible themes, including hover states and a readable current-page label
- Accent swatch tooltips — sidebar accent-theme swatches gain
data-theme-labelattributes and::afterhover/focus-visible tooltips showing the theme name, with light-mode styling and reduced-motion-safe behaviour - Decorative icons hidden from screen readers —
aria-hidden="true"added to non-informative SVG icons in the shortcuts modal, sidebar fallback icon, back-to-top button, and the home “View all posts” link
Code blocks
- Line numbers —
code-blocks.jsnow wraps each<pre>in a two-column shell and generates line numbers based on the block’s actual line count; corresponding styles added for dark, light, and accessible themes; header insertion updated so language labels and copy controls still render correctly with the new wrapper
Search
- Loading state — the search modal now shows a spinner while the Lunr index is fetched and built, hidden on success, failure, or modal close
Site structure
- Community page URL — the Community nav link now points to
/community/; the page file was renamed fromcommunity_review.mdtocommunity.mdso the URL and source filename match
2026-05-12
Community page
- Award logo sizing fixed — award images gain a no-zoom class and
.award-entry__logonow applies a fixed width (w-[84px]), left alignment, and resets border/radius, preventing inconsistent zoom/rounding across logos
2026-05-11
View transitions
- MPA page transitions —
@view-transition { navigation: auto }added to the CSS so the browser plays a cross-fade animation when navigating between pages; old and new root snapshots each animate for 250ms withease-outtiming; the entire effect is suppressed underprefers-reduced-motion: reduce - Shared hero image transition — the post-card thumbnail and the full-post hero image share a
view-transition-namekeyed to the post slug (post-img-{slug}), so the thumbnail morphs smoothly into the full hero image when opening a post - Scroll anchor offset —
scroll-padding-top: 4remadded tohtmlso anchor-linked headings clear the fixed topbar after a transition
Container queries
- Post card container —
.post-cardnow carriescontainer-type: inline-size; container-name: post-card; the list-view layout rules (thumbnail width, body padding, excerpt clamp) are applied inside a@container post-card (min-width: 480px)query rather than a viewport media query, so cards adapt to their actual rendered width regardless of how the grid is configured
Focus ring refinement
- Consistent 3px outline — the standard
:focus-visiblering increased from 2px to 3px; the accessible-mode ring reduced from 4px to 3px, giving both a uniform thickness with a slightly larger offset
About & Community Review page — timeline components
- Presentations timeline — the flat presentation list in
_data/presentations.ymlis now grouped by year via Liquidgroup_byand rendered as a visual vertical timeline with circular year markers and per-entry month badges; data fields changed from a singledatestring to structuredyear,month, andmonth_namefields - Awards timeline — the MVP award list in
_data/awards.ymlchanged from a singleyearsstring tostart/endinteger fields (supporting"Present"as end value); rendered as a.award-timelinewith logo, category, and date-range display - Publications timeline — the publications list on the Community Review page is now grouped by year (extracted from the existing
datestring) and rendered in the same vertical timeline style as presentations
Tailwind CSS
- Upgraded to v4.3.0 —
tailwindcss,@tailwindcss/cli,@tailwindcss/node, and@tailwindcss/oxideupdated to v4.3.0
Post card image sizing
- Responsive
sizesrefinement — post-card<source>sizes attribute gains a 1280px breakpoint (50vw) and a33vwfallback for larger grids - List-view layout scoped to selectors — the previous container-query-based list view rules were replaced with scoped
#posts-container.posts-listselectors (fixed thumbnail width, no max-height, adjusted body padding, single-line excerpt truncation), keeping grid thumbnails consistent while avoiding container-query side effects in list view
2026-05-09
Post hero image
- Height capped across all display sizes — the post hero image container previously used
aspect-[21/9]with no maximum height, producing a 703px-tall hero at 1080p, 977px at 1440p, and 1526px at 4K; the aspect ratio has been replaced withheight: clamp(220px, 35vw, 480px), which scales smoothly from 220px on mobile (up from 161px — better visual impact) through ~350px at 720p, and caps at 480px at 1080p and above regardless of viewport width - LCP performance attributes — the hero
<img>element now carriesfetchpriority="high",loading="eager", anddecoding="auto", signalling to the browser that this is the Largest Contentful Paint element and should be loaded as a high-priority resource - Title overlay on hero — the post title, category label, and metadata bar are now rendered inside the hero image over a gradient overlay (
transparent → rgba(0,0,0,0.85)), removing the visual gap between image and content; hero height increased toclamp(360px, 48vw, 580px)to accommodate the text comfortably; the image is inset with content-matching padding (px-6 pt-6 lg:px-10) and given rounded corners (rounded-xl) and a shadow; the attribution pin moves to the top-right corner to avoid overlap with the title text; posts without a hero image fall back to the original full header layout below the fold; thesizesattribute on the responsive<source>element updated to account for padding (calc(100vw - 48px)on mobile,calc(100vw - 360px)on desktop)
2026-05-07
Accessibility & visual improvements
- Title hierarchy — post page title bumped to
text-3xl sm:text-4xl lg:text-5xlwithtracking-tight;.post-content h1reduced from 36px to 30px so in-body H1s never exceed the page title;aboutandblogpage titles gainsm:text-4xlfor visual parity - Accent contrast token — a new
--color-accent-deepestCSS token (one shade darker than--color-accent-dark) is defined for all eight themes, the rainbow theme, and the accessible theme; it is used for any background surface that pairs with white text or icons, bringing those surfaces to WCAG 2.1 AA contrast; affected components: view-toggle active state, skip link, back-to-top button, project card link, project card tags, category filter active button, copy-URL button, and code block language header - Reading column width — post main content area narrowed from
max-w-3xl(~768px) tomax-w-[68ch]for a more comfortable ~65–70 character line length;text-wrap: balanceapplied to all post and card headings;text-wrap: prettyapplied to post body paragraphs and list items - Sidebar navigation — deduplicated the sidebar: the “Navigate” section (which duplicated main nav links) is replaced by a “More” section containing Archive and RSS Feed only; primary navigation (About, Blog, Projects) is now driven by
site.menuin the sidebar header; RSS Feed link moved from the Connect section into More - Theme-aware hero dots — the homepage radial dot pattern used a hardcoded indigo colour regardless of the active accent theme; it now uses
color-mix(in srgb, var(--color-accent) 20%, transparent)in dark mode andvar(--color-accent-dark) 12%in light mode, so the dots shift colour when the accent theme is changed - Code comment contrast — dark-mode syntax comment colour raised from
#64748b(slate-500, ~3.5:1) to#94a3b8(slate-400, ~5.4:1) against the#1e293bcode background, clearing WCAG AA for body text - Touch targets —
.dark-togglegainsmin-width: 44px; min-height: 44px;.accent-swatchgains an invisible::beforeexpanded hit area (~36px total);.post-tag-pillpadding increased frompy-0.5topy-1.5withmin-height: 32px
2026-04-03
Bug fixes
- Share buttons — full URL —
url: https://stealthpuppy.comis now set in_config.ymlso Jekyll’sabsolute_urlfilter produces a full URL in LinkedIn and Bluesky share buttons; previously only the relative path (e.g./evergreen-workbench/) was passed - Utterances comments label — the utterances
labelattribute was incorrectly set topage.url(a URL path) instead ofsite.utterance.label(comment); GitHub issues created by comments were not tagged with the correct label and did not appear in the repository issues list - Dark mode flash on navigation — an inline
<style>html.dark{background:#0f172a}</style>is now injected in<head>immediately after the theme-init script, so the dark background colour is applied beforestyle.cssloads, eliminating the white flash visible when navigating between pages in dark mode
Accent themes
- Rainbow theme — a new rainbow accent option replaces the gray swatch; when selected, all accent-coloured elements (links, active nav, focus rings, code highlights) smoothly cycle through the full colour spectrum via a CSS
@keyframesanimation on a registered@property --accent-hue; the swatch displays a conic gradient preview
2026-03-26
Post metadata
- Updated date — a “Updated” date now appears in the post header metadata strip, sourced from
page.last_modified_at(viajekyll-last-modified-at), showing when the post file was last committed to git; it only renders when the updated date differs from the published date - Category icon — the category icon in post metadata changed from a price-tag shape to a folder icon, better representing the concept of a category
- Tag pills — tag pills in the post header now include a small tag SVG icon before the tag name, and each pill links to its tag landing page
Outdated / content warning
- A new front-matter flag
outdated: trueon a post renders a warning callout below the post header, alerting readers that the content may no longer be accurate - The warning text is configurable via
outdated_noticein front matter; a default message is shown if the field is omitted
Series navigation
- Posts that belong to a series can set
seriesandseries_partin front matter; a series navigation block listing all parts (with the current part highlighted) is rendered between the post summary and the article body - The duplicate series/part label that previously appeared in the post-meta strip has been removed — series information is now only shown in the dedicated series navigation block
Post layout order
- The post summary (description callout) is now rendered above the series navigation block, so the description always appears immediately after the post header
Projects page
- A page-level “Updated” date now appears in the Projects page header, showing when
projects.mdwas last committed to git
Share buttons
- Share buttons now use solid filled brand colours (LinkedIn
#0A66C2, Bluesky#1185FE) instead of the previous ghost/outline style - The “Copy link” button uses the current accent colour; it briefly turns green on successful copy
- Brand colours are consistent across light and dark modes
2026-03-23
Accessible theme
A new high-contrast accessible theme designed for low vision and colour-blind users:
- Yellow-on-black palette — foreground
#fde047on#000background; contrast ratio ~15:1 (exceeds WCAG AAA 7:1 requirement) - Dedicated toggle button — eye icon button in the topbar and sidebar, separate from the light/dark toggle; button shows a filled/pressed state when active
- Always-underlined links — all links show underlines regardless of hover, removing colour as the sole link indicator
- Yellow borders — all card, callout, sidebar, and code block borders switched to yellow for visibility
- Visible focus rings — focus outlines use yellow and are always shown, not suppressed by
:focus-visible - Desaturated hero images — post hero images rendered in greyscale to reduce visual noise
- Accent swatches hidden — the colour accent picker is hidden in accessible mode (accent colour is fixed to yellow)
- Accessible state persists across reloads — stored in
localStorageunder keyaccessible, independent of the dark/lightthemekey - New icon —
_includes/icons/eye.svg(Lucide eye) added for the accessible toggle button
Theme toggle
- Separated into two independent controls: a binary light/dark toggle (moon/sun icons) and a dedicated accessible theme button (eye icon)
- Previously the single toggle cycled through three states; it is now a simple light ↔ dark binary, with accessible mode enabled and disabled via its own button
- Exiting accessible mode via the dark toggle enters dark mode; exiting via the accessible button restores the previously saved light/dark preference
Topbar icon consistency
- Fixed a CSS specificity issue where the
<span>wrappers around moon/sun icons inherited a different colour than the unwrapped search icon in light mode; all three topbar icons now render at the same muted colour
Accessibility
Improvements for screen readers, keyboard users, and users with visual preferences:
- Focus management — focus traps and focus restoration added to search modal, keyboard shortcuts modal, and mobile sidebar; image zoom overlay now uses
role="dialog"with focus trapped inside and restored on close - ARIA fixes — search results corrected from
role="listbox"/role="option"torole="list"(appropriate for link-based results); removed incorrectrole="tooltip"from hero image credit span - ARIA additions —
aria-labeladded to search input (placeholder alone is insufficient for screen readers);aria-pressedadded to dark mode toggle, grid/list view toggle, and accent swatch buttons;aria-expandedadded to mobile sidebar toggle;aria-labeladded to TOC aside (role="navigation"); descriptivearia-labeladded to blog pagination links - Decorative SVGs —
aria-hidden="true"added to decorative icons in post metadata (calendar, clock, tag) so screen readers skip them - Back-to-top button — removed from tab order when visually hidden (
aria-hidden+tabindextoggled in JS) - Non-colour active state — TOC active heading link bumped to
font-semiboldso the active state is distinguishable without relying on colour alone - High-contrast mode — added
@media (prefers-contrast: more)block with stronger borders and text for OS high-contrast mode
Code blocks
- Language label in the header bar is now white in light mode (previously inherited body text colour)
- Moved the copy-to-clipboard button from the header bar into the code listing itself, floating in the top-right corner below the header
- Reduced header bar height with tighter padding
- Fixed corner radii: header top corners are rounded, the join between header and code listing is flush (no gap or double radius), code listing bottom corners are rounded
Post summary
- Changed from right-side-only rounded corners to fully rounded on all four corners, matching the callout style
Callouts
- Note, tip, warning, and danger callouts changed from right-side-only rounded corners to fully rounded on all four corners
Author bio
- Removed social links (GitHub, LinkedIn, Bluesky) from the author bio card at the bottom of posts — social links remain in the sidebar
Images in posts
- Removed the link hover highlight colour on images wrapped in anchor tags
- Added a magnifying glass icon overlay that appears on hover to indicate the image can be zoomed/enlarged
Sidebar navigation
- Split the single combined navigation list into two labelled sections: Navigate (internal site pages) and Connect (external social links)
Sidebar responsive layout
- Restructured the sidebar into three explicit zones:
- Header (avatar, name, tagline, main nav) — fixed, shrinks at short viewport heights
- Navigation (Navigate + Connect sections) — scrollable when content overflows
- Footer (accent swatches) — fixed, always visible at full size regardless of viewport height
- Accent colour swatches no longer resize at short viewport heights (≤780px) — they remain 20px and centred at the bottom of the sidebar
- Sidebar tagline continues to hide at very short viewports (≤719px)
- Swatches centred horizontally in the footer
2026-03-22
Accent colour swatches
- Removed the indigo swatch and replaced it with a blue swatch as the first option
- Updated all swatch colours to more vivid, saturated values matching standard Tailwind 500-level palette
- Added a gray swatch as the eighth option
- Updated
accent-theme.jsto reflect the new swatch set — blue is now the default fallback theme when no preference is stored
Topbar glass effect
- Upgraded the top navigation bar from a near-opaque frosted background to a proper glassmorphism effect:
- Background opacity reduced from 90% to 60% (dark) / 65% (light) so page content bleeds through the blur
- Blur increased from
backdrop-blur(~8px) tobackdrop-blur-lg(16px) - Added
backdrop-saturate-150to boost the colour richness of blurred content behind the bar - Softened border opacity to 50–60%
- Added a hairline inset top-edge highlight (
box-shadow: inset 0 1px 0 rgba(255,255,255,0.06)) characteristic of glass surfaces
UI effects and micro-interactions
Added four new interaction effects, all disabled for users with prefers-reduced-motion: reduce:
- Post cards — cards lift 3px (
translateY(-3px)) and gain a shadow on hover; hero image zoom increased from 1.02 to 1.05 - Search modal — the ⌘K modal now animates open (scale + fade in, 180ms) and closed (scale + fade out, 150ms) instead of appearing instantly
- TOC active indicator — the active heading link in the table of contents shows a 2px accent-coloured left border that transitions in, with a subtle
padding-leftnudge to the link text - Icon micro-interactions — the dark mode toggle SVG rotates 15° on hover; sidebar social link icons lift 2px on hover
2026-03-21
Colour highlights
Added targeted colour highlights across the theme to improve visual clarity without introducing a second accent colour.
- Social icon brand colours — sidebar and author bio social icons (GitHub, LinkedIn, Bluesky, Ko-fi, Spotify, RSS) now show their platform brand colour on hover
- Share button brand colours — LinkedIn and Bluesky share buttons show platform brand colours on hover
- Post metadata icons — calendar, clock, and tag icons in the post header now use the accent colour
- Tag pill background tint — tag pills gain a subtle accent-tinted background using
color-mix() - View toggle active state — the active grid/list view button on the blog page now uses the accent colour instead of flat dark grey
- Callout type differentiation — three new callout variants alongside the existing
.noteclass:.warning— amber border and background.tip— green border and background.danger— red border and background
Hero image photo attribution
- Added an attribution icon overlay on hero images linking to the original photographer
- Removed the separate attribution page in favour of per-post attribution data in front matter
Image zoom
- Replaced medium-zoom with a lightweight custom implementation — removes the vendor script dependency
- Zoomed image is capped at 95 vw × 95 vh and centred in the viewport
- Backdrop uses
backdrop-blur-smandbg-black/60— matching the search modal blur effect - Fixed navigation hijack caused by images wrapped in
<a>links (common in Markdown): click is intercepted andpreventDefault()called so the browser no longer navigates to the raw image URL
Mermaid diagrams
- Fixed arrow and edge colours in dark mode —
lineColoroverridden toslate-400(#94a3b8) so connecting lines are visible against the dark background
Table of contents
- Active heading link now renders in the current accent colour in light mode — previously the light-mode override rule had higher specificity and suppressed the accent colour
Sharing
- Fixed LinkedIn share button — updated from the deprecated
/shareArticleendpoint to/sharing/share-offsite/, which correctly pre-populates the LinkedIn post composer with the page URL and Open Graph metadata
Footer
- Removed the separate attribution page link from the footer
- Added a link to the site changelog
2026-03-20
Keyboard shortcuts
- Added a keyboard shortcuts modal (press
?to open) listing all available keyboard shortcuts - Shortcuts include:
⌘K/Ctrl+Kfor search,Dfor dark mode toggle,Gfor grid/list view,Tfor back to top
Mermaid diagram support
- Added client-side rendering of Mermaid diagrams in posts
- Diagrams are defined in fenced code blocks with the
mermaidlanguage identifier - Theme-aware: diagram colours adapt to light and dark mode
UI refinements
- Compact sidebar layout for short viewport heights (≤780px) such as 720p screens
- Sidebar tagline hidden on very short viewports (≤719px)
- Minor link hover and spacing improvements throughout
2026-03-19
New theme — complete rewrite
Replaced the Hydejack 9.x theme with a fully custom Jekyll layout built on Tailwind CSS v4 and @tailwindcss/typography.
Layout and structure
- Sidebar layout — fixed sidebar with avatar, navigation links, social links, search, dark mode toggle, and accent colour swatches
- New layouts —
base,default,post,blog,list,page,about,plain - Post layout — hero image, metadata bar (date, reading time, category), description summary callout, article body, table of contents sidebar, related posts, and Utterances comments
- Blog layout — paginated post grid with grid/list view toggle, persisted to
localStorage - Post cards — image thumbnail, excerpt, category badge, and estimated reading time
Styling
- Palette — slate/indigo base with
slate-900background andindigo-400accent - Dark mode — class-based (
.darkon<html>) withlocalStoragepersistence;slate-950sidebar contrasts againstslate-900content area - Light mode — white content area,
gray-50sidebar - Accent colour themes — 8 swappable accent colours (indigo, blue, purple, pink, red, orange, amber, green)
- Syntax highlighting — full light and dark token colour overrides for Rouge (Monokai-inspired dark, high-contrast light)
- Inline code — accent-coloured pill style with monospace font
- Article links — block highlight on hover (accent background, white text)
- Image spacing — ~8px above and below inline images via negative margin technique
JavaScript
| Script | Purpose |
|---|---|
dark-mode.js |
Class-based dark mode toggle with localStorage persistence |
search.js |
⌘K / Ctrl+K modal with live fuzzy search via Lunr.js |
toc.js |
Dynamic table of contents from article headings with IntersectionObserver active-link tracking |
zoom.js |
Custom image zoom lightbox (originally medium-zoom; replaced 2026-03-21) |
code-blocks.js |
Language badge injection and one-click copy button on code blocks |
sidebar.js |
Mobile sidebar open/close with overlay |
Build pipeline
npm run build— full build (fonts + icons + CSS)npm run build:css— Tailwind CSS compilation onlynpm run build:icons— copies SVG icons from npm packages (simple-icons,lucide)- Self-hosted Geist variable fonts (sans and mono)
Removed
- Hydejack 9.x theme files (SASS partials, legacy JS bundles)
- IcoMoon icon font
- PWA web manifest and app icons
- Category filter bar from blog page (simplified to post grid)