Implementation Phases¶
"You don't build a garden in one day. But every day, you follow the same principles."
The Zen Design System is implemented across the site in phases. Each phase is a self-contained unit of work that can be done in one or two Copilot CLI sessions.
Phase 1: Foundation 🏗️ ✅ COMPLETE (26 Apr 2026)¶
Goal: Install the CSS custom property system and theme toggle. This changes NOTHING visually — it's plumbing. Old pages keep working exactly as they are.
Deployed: Commit series culminating in Phase 1 + Homepage combined session.
What Gets Done¶
- Add all Zen CSS custom properties to
:rootand[data-theme="dark"]instyle.css(TOP of file) - Add theme toggle button to
nav.html(sun/moon icon) - Add theme toggle JS: reads localStorage → sets
data-theme→ saves preference - No visual changes yet — just the infrastructure. All existing pages stay dark-only.
- Hugo build passes with zero errors
Why This Is Safe¶
CSS custom properties are additive. Adding --bg-page: #FAFAFA does nothing until a rule actually uses var(--bg-page). So the foundation is zero-risk to existing pages.
Files Touched¶
static/css/style.css— add:roottokens at TOP (above all existing rules)layouts/partials/nav.html— add theme toggle buttonstatic/js/switcher.js— add theme toggle logichugo.toml— bumpcache_version
Definition of Done¶
- [ ] All Zen tokens exist in
:rootand[data-theme="dark"] - [ ] Theme toggle button visible in nav
- [ ] Toggle switches between light/dark, persists in localStorage
- [ ] ALL existing pages still look correct in dark mode (no regressions)
- [ ] Zero Hugo build errors
Continuation Prompt¶
# Zen Design System — Phase 1: Foundation
## Context
Read the Zen Design System docs at:
learn.aguidetocloud.com → Playground → 🌸 Zen Design System
Key docs: philosophy.md, colours.md, typography.md, spacing.md, components.md, guardrails.md
## What to Do
1. Add CSS custom properties (`:root` light, `[data-theme="dark"]` dark) to style.css
- Copy token values from colours.md, typography.md, spacing.md
2. Add theme toggle button to nav.html (sun/moon icon, far right)
3. Add theme toggle JS to switcher.js:
- On load: check localStorage('theme') → prefers-color-scheme → default 'light'
- Set data-theme on <html>
- Toggle button swaps and saves to localStorage
4. Refactor ALL homepage CSS to use var() tokens — zero hardcoded colours
5. Remove: backdrop-filter, neon vars, gradient backgrounds, glow effects, shimmer animations
6. Test in both modes + Playwright screenshots
7. Hugo build must pass
## Guardrails (ACTIVE)
⚠️ No hardcoded colours. One accent (indigo). No decorative elements.
No backdrop-filter. Transitions ≤200ms ease-out. Both modes must work.
See guardrails.md for full rules.
## Key Files
- style.css — the main CSS file
- layouts/index.html — homepage template
- layouts/partials/welcome-strip.html — hero section
- layouts/partials/nav.html — navigation (add toggle here)
- static/js/switcher.js — JS (add toggle logic here)
- hugo.toml — bump cache_version
## Rules
- Use `pwsh scripts/hugo-safe.ps1` for Hugo builds
- git pull --rebase before every push
- Bump cache_version for CSS/JS changes
Phase 2: Front Door (Homepage) 🚪 ✅ COMPLETE (26 Apr 2026)¶
Goal: Rewrite homepage CSS to use only Zen tokens. First page to go fully Zen. Both light and dark modes working.
Deployed: Combined with Phase 1 in a single session. Homepage supports light/dark toggle.
What Gets Done¶
- Replace ALL hardcoded colours in homepage CSS with
var()tokens - Remove glassmorphism, neon, gradient, glow from homepage rules
- Simplify homepage structure — less "card mania", more breathing room
- Remove decorative elements (watermark numbers, shimmer animations, cursor glow)
- Homepage renders correctly in both light and dark mode
- Playwright screenshots at 1440px: light + dark
Definition of Done¶
- [ ] Homepage looks clean in light mode
- [ ] Homepage looks clean in dark mode
- [ ] Zero hardcoded colours in homepage CSS
- [ ] No
backdrop-filterin homepage CSS - [ ] All other pages still work in dark mode (no regressions)
Phase 3: Walls (Nav + Footer) 🧱 ✅ COMPLETE (26 Apr 2026, b7a6f6b)¶
Goal: Shared partials go Zen. This makes the shell of EVERY page feel new.
Deployed: Nav, footer, mega-menus, mobile drawer all use Zen tokens. 38 per-page nav accent rules deleted. body:not(.is-home) scoping keeps legacy pages dark while homepage supports light/dark.
What Gets Done¶
nav.html— refactor to Zen tokens, clean minimal stylefooter.html— refactor to Zen tokens- Both work in light and dark modes
- Navigation active states use
--accent(indigo) - Mobile nav/hamburger updated
Impact¶
When this deploys, every single page gets a new shell. Even un-migrated tool pages start feeling Zen.
Definition of Done¶
- [ ] Nav + footer use only Zen tokens
- [ ] Both modes work on every page
- [ ] Mobile nav functions correctly
Phase 4: Biggest Rooms (53 Tool Pages) 🔧 ✅ COMPLETE (26 Apr 2026, 262e089)¶
Goal: Minimal, tools-first design. Nothing between the user and the tool.
Phase 4a: Structural Migration (COMPLETE — 26 Apr 2026)¶
- Created
static/css/zt-tools.css— universal tool page styles (underline tabs via ARIA selectors, 1200px width) - Created
layouts/partials/tool-header.html— compact title + counter + subtitle (replaces gradient hero bar) - Created
layouts/partials/tool-faq.html— reusable collapsed FAQ partial (available but not used — FAQ kept as tab) - Migrated all 53 tools via batch Python script + manual fixes
- Removed
tool-ecosystem.htmlcalls from all tools - Removed
back-navfrom all tools, replaced with "← All Tools" link tool_colours.tomlNOT deleted yet — still used by OG image generator. Per-tool accents no longer affect page styling.- Per-tool CSS files NOT deleted — internal tool styling preserved for Z4b polish pass.
free-tools/list.htmldirectory page NOT yet updated to Zen cards — deferred.
Phase 4b: Z4 Light/Dark CSS Migration (IN PROGRESS — 27 Apr 2026)¶
Goal: All 53 tool pages work in both light AND dark mode using Zen tokens. Replaces all glassmorphism CSS (dark-only rgba(255,255,255,...), backdrop-filter, per-tool accents) with Zen design tokens.
📖 Full playbook: Z4 Migration Playbook — the 5 traps, token mapping, detection commands, lessons learned.
What Was Done (5 passes, ~800+ CSS changes, LOCAL — NOT DEPLOYED)¶
- Pass 1 — Batch migration of 53 CSS files: removed 177 backdrop-filters, 39
--tool-accentdeclarations, updated 49 template FAQs, fixed 3 JS files. Addedzen-migratedclass to all 54 tool body classes. - Pass 2 — Targeted remaining hardcoded colours: neon cyan, near-white hex text, dark backgrounds. Darkened
--text-muted(#A3A3A3→#6B6B6B) and--text-tertiary(#737373→#525252) for light mode contrast. - Pass 3 — Fixed 12 CSS files with per-tool variable systems (
--cp-*,--lp-*,--dt-*, etc.) that had dark defaults. - Pass 4 — Found 11 MORE per-tool variable systems + old glassmorphism variable refs (
--bg-card,--glass-border). 249 changes across ~30 files. - Pass 5 — Fixed 4 remaining FAIL tools: instruct-builder (86 changes), licence-picker (198 changes — eliminated
:rootalias vars), prompt-guide (scoped override removed), qr-generator (24 changes — #EC4899→var(--accent)). - Structural fixes — Licence Picker template restructured (header was inside tablist), AI News breaking card restyled from red glassmorphism to Zen card style.
- Automated QA result: ✅ 45 GOOD | ⚠️ 7 WARN (acceptable) | ❌ 0 FAIL | 💥 1 ERROR (feedback timeout)
What Was Done (Phase 4c — 27 Apr 2026, LOCAL)¶
- Pass 6: Replaced 68 per-tool accent colours (demo-scripts #F97316 → var(--accent))
- Pass 7: Eliminated 602
:rootalias variable usages across 17 CSS files (Trap 3 — the #1 cause of invisible text) - Fixed
--text-tertiarydark mode gap inbody.zen-migrated— was missing, causing 100+ dark mode failures - Migrated
command-centre.css(cc) from scratch — was completely missed in Z4b - Fixed global floating elements —
.global-btt,.feedback-fab,.bookmark-cta-innernow use Zen tokens on zen-migrated pages - Fixed
<select>dropdown styling globally for zen-migrated pages - Cleaned glass pill tab code in 10 CSS files (dead code from old tab style)
- Fixed button text colour inheritance in 9 CSS files (buttons not inheriting color in dark mode)
- Fixed
feedback/list.html— replacedtool-hero.htmlwithtool-header.html, addedzt-pagewrapper - Fixed
.tool-eco-feedbackshared component — was still usingrgba(255,255,255,...) - Fixed
licensing.css— 9 instances of#f1f5f9(Tailwind slate-100 → var(--text-primary)) - Fixed
ainews.css— non-Zen magenta/gold tier badge colours → neutral Zen tokens - Fixed
instruct-builder.css— removed lastbackdrop-filter: blur(12px) - Fixed
site-analytics.css— white text label → var(--text-muted) - Deep WCAG contrast audit — Playwright script checks every visible text element's contrast ratio against effective background. Findings documented in guardrails.md.
- Automated QA result: ✅ 40 GOOD | ⚠️ 7 WARN | ❌ 5 FAIL | 💥 1 ERROR (basic QA)
Total changes this session: ~1,400+ CSS property replacements, 58 :root declarations removed, 10 glass pill cleanups, 7 template/structural fixes.
What Was Done (Phase 4d — 27 Apr 2026)¶
- roadmap.css full Zen migration — Replaced entire "Amber Command" palette (~60 hardcoded dark colours) with Zen tokens. Hero gradient → flat
var(--bg-surface). All inputs, cards, chips, skeleton, BTT button, footer migrated. - Badge text token system — Added
--badge-red/orange/amber/green/blue/purpletobody.zen-migratedin style.css. Dark text in light mode (#B91C1C, #C2410C, etc.), light text in dark mode (#FCA5A5, #FDBA74, etc.). Proper WCAG contrast on tinted backgrounds in both modes. - Badge migration across 6 tools — cert-tracker (3 groups), deptime (4 groups), incident-comms (severity + gallery), cert-compass (yellow badges), admin-badges (rarity), service-health (tab/rank badges).
- feedback.js timeout — Added AbortController with 15s timeout on submit, 10s on discussions fetch.
- QA: 53/53 GOOD — Playwright light+dark mode screenshots for all tools. Zero warnings, zero failures.
- Deployed commit
8c3b52d.
Triaged as non-issues¶
- copilot-matrix backdrop-filter — 0 instances found (already cleaned)
- button white text — False alarm: all have fixed saturated backgrounds, white text is fine
- ai-showdown search button — Not reproducible in CSS
- countdown dark mode — Fullscreen dark bg is intentional for timer display
<option>element styling — Browser limitation, won't fix
Key Decisions¶
- FAQ stays as a tab — desktop users won't scroll to find a collapsed FAQ at the bottom. Tabs are functional navigation.
- 1200px max-width — matches
--max-page. Gives tools breathing room. zt-pageclass on wrapper divs — marker class for tab styling + width override via cascade order.- Counter kept — social proof is information, not decoration. Dual class (
tool-counter) preserves JS animation. body.zen-migratedopt-in class — pages with this class opt OUT of force-dark and get full light/dark mode. Control point:baseof.htmlline ~78.- Eliminated
:rootalias variables — CSS custom properties inherit computed values, making:rootaliases unreliable when multiple:rootblocks exist. --text-muteddarkened to #6B6B6B — WCAG ~4.7:1 contrast ratio (was 2.31:1 at #A3A3A3).--text-tertiarymust be overridden in dark mode — added #A3A3A3 to[data-theme="dark"] body.zen-migrated.- Badge text tokens flip per mode — single
var(--badge-red)resolves to dark (#B91C1C) in light mode, light (#FCA5A5) in dark mode. Contrast-safe on both tinted backgrounds. - White text (#fff) on saturated semantic backgrounds — safe for status badges where JS sets opaque coloured backgrounds (roadmap status, service-health rank).
Definition of Done¶
- [x] All 53 tools render with clean header + underline tabs
- [x] Hero gradient bars removed from all tools
- [x] Ecosystem grids removed from all tools
- [x] 800+ CSS glassmorphism patterns replaced with Zen tokens
- [x]
body.zen-migratedon all 54 tool body classes (including cc) - [x] Automated QA: 0 FAIL tools (basic scanner)
- [x] 10 CSS files cleaned of dead glass pill code
- [x]
:rootalias variables eliminated from 17 CSS files (Trap 3) - [x] Global floating elements (btt, fab, bookmark) use Zen tokens
- [x] Deep WCAG contrast audit run, findings documented
- [x] Semantic badge contrast review — badge text tokens added
- [x] Per-tool button white text reviewed — no real issue (saturated bgs)
- [x] Playwright QA: 53/53 GOOD in light+dark
- [x] Deployed to production
- [ ]
tool_colours.tomldeleted or emptied (deferred — OG generator uses it) - [ ] Both light/dark modes visually verified by Sutheesh
Phase 5: Reading Rooms (Blog + Study Guides) 📖¶
Goal: Blog posts and study guides get the Stripe Docs treatment — 3-column edge-to-edge layout.
Architecture Decision (26 Apr 2026): Full-Width Philosophy¶
The viewport is your canvas. Content defines its own width.
All pages should be edge-to-edge with no outer max-width containers. Sidebars anchor to edges, content fills remaining space. Generous whitespace comes from grid proportions, not arbitrary caps. This applies site-wide going forward.
┌──────────────────────────────────────────────────────────────────┐
│ Nav (edge-to-edge) │
├──────────┬──────────────────────────────────┬────────────────────┤
│ Left │ Content (1fr — fills space) │ Right companion │
│ sidebar │ │ sidebar (280px) │
│ (250px) │ Tables, code, text all breathe │ Related articles │
│ TOC │ into whatever room the screen │ Video widget │
│ sticky │ gives them. │ CTAs │
│ --bg- │ │ sticky │
│ elevated │ 1920px → 1390px content │ │
│ │ 1440px → 910px content │ │
│ │ 1280px → 750px content │ │
├──────────┴──────────────────────────────────┴────────────────────┤
│ Footer │
└──────────────────────────────────────────────────────────────────┘
Phase 5a: Blog (COMPLETE — 26 Apr 2026, commit 67c5831)¶
What Was Done:
- Created
layouts/blog/single.html— 3-column reading layout - Created
static/css/zt-reading.css— full reading room styles (882 lines) - Created
static/js/zt-toc.js— IntersectionObserver TOC highlighting + progress bar - Right companion sidebar: video widget, 5 related articles, subscribe CTAs
- Mobile: sidebars collapse,
<details>TOC below title - Migrated
blog/list.htmlto Zen (tool-header + card list) - Fixed global token gap (
--text-primary/secondary/mutedonbody:not(.is-home)) - Configured Hugo TOC depth (h2–h4)
Key Decisions:
- Content fills all space — no
max-widthcap on content.1frgrid column. - 3-column, not 2 — right companion sidebar earns its place with related content.
- Separate
blog/single.html— cleaner than conditional_default/single.html. - Legacy CSS untouched — override in
zt-reading.css, don't delete fromstyle.css.
Definition of Done: - [x] Blog posts render with left sidebar TOC - [x] Content fills available space between sidebars - [x] Right companion sidebar with related articles - [x] Mobile: sidebars collapse gracefully - [x] Hugo build: zero errors - [x] Deployed
Phase 5b: Study Guides (TODO)¶
- Cert-tracker single template (31KB) needs sidebar treatment
- Reuse
zt-reading.cssinfrastructure - Left sidebar: section navigation (domains/modules), not just TOC
- Right sidebar: practice exam link, related certs, progress
Phase 5c: Nav Full-Width (TODO)¶
- Nav still has Phase 3 pill shape — jarring above full-width content
- Make edge-to-edge: logo left, dropdowns middle, toggle+CTA right
- Affects all 1876 pages — deserves its own commit
Future Enhancements (TODO)¶
- Reading mode toggle — hide both sidebars for focused reading
- Companion extras — "Popular this week", bookmark/save, reading time bar
- ~~Full-width tool pages — apply same edge-to-edge philosophy to 53 tools~~ → Done in Z5
Phase 5c: Tool Pages 3-Column Layout (COMPLETE — 27 Apr 2026, commit 1c32975)¶
What Was Done:
- Created
tool-nav.html— left sidebar with all 53 tools grouped by 9 categories - Created
tool-companion.html— right sidebar with popular tools, blog posts, CTAs baseof.htmldetects tools viatoolkit_nav.toml— wraps in CSS grid (zero template changes).zt-reading--toolCSS grid:250px | 1fr | 280pxwith mobile collapse at 1024px- Fixed Prompt Library extra
</div>breaking grid (companion was invisible) - Forced all inner containers full-width (
max-width: noneon-container,-page,-wrap)
Phase 5d: 1036 CSS Readability Fixes (COMPLETE — 27 Apr 2026, commit c839ecb)¶
What Was Done:
- Batch script (
z5-batch-fix.cjs) fixed 1036 issues across 55 CSS files - Removed: glow shadows, glow text-shadows, glass pill radii, glow CSS vars
- Fixed: near-white hex text → tokens, tiny font sizes → token scale, backdrop-filter → none
- Fixed: Ko-fi button contrast (white on red-transparent → badge-red token)
- Playwright QA: top 5 worst tools readable in both light + dark mode
- All learnings documented in
z4-migration-playbook.md(Traps 6-9)
Phase 6: Attic (Everything Else) 🧹¶
Goal: Every remaining page uses Zen tokens. No legacy styling survives.
What Gets Done¶
- 404 page: minimal Zen treatment
- AI Hub: Zen cards for video grid
- Cert Tracker: Zen treatment
- Search overlay: Zen colours + tokens
- Remove ALL dead CSS (old tool classes, old homepage classes, old neon vars)
- Remove cursor glow, shimmer animations, gradient definitions
- CSS file size audit — target 50% reduction
Definition of Done¶
- [ ] Zero hardcoded colours in entire
style.css - [ ] Zero references to old neon variables
- [ ] Zero
backdrop-filterin CSS - [ ] CSS file size reduced significantly
- [ ] Every page works in both modes
Phase 7: Guided Alignment 🎯¶
Goal: The Guided Astro platform matches the Zen system visually.
Architecture Decision (26 Apr 2026) — PERMANENT¶
Two platforms, clear boundary. Don't consolidate.
aguidetocloud.com (Hugo — Zen)
└── /cert-tracker/az-900/ ← Study guide, content, links (Hugo)
└── "Start Practice Test →" button
└── /guided/practice/az-900 ← Opens Astro quiz
- Hugo = content + tools. Zen design. Fast, SEO-friendly. 53 tools, blog, study guides.
- Astro = interactive apps ONLY. PracticeQuiz.tsx (133KB React) is too complex for vanilla JS rewrite.
- Hugo owns the entrance — everything the user sees before clicking "Start Test" is Hugo + Zen.
- Astro owns the interactive layer — practice tests, flashcards. Same domain via Cloudflare Pages Function proxy.
- Why not consolidate? PracticeQuiz has complex state management (multiple question types, scoring, timers, guided mode, domain breakdowns). React's declarative model handles this better than imperative DOM manipulation. Rewriting would take 5-10 sessions and produce something harder to maintain.
What Gets Done¶
- Port Zen CSS custom properties to Guided's Astro/Tailwind config
- Same Inter font, same type scale, same spacing
- Same accent colour (indigo replacing current green)
- Nav alignment between Hugo and Guided sites
- Consistent card/button/input styling
Definition of Done¶
- [ ] Navigating from aguidetocloud.com → /guided/ feels seamless
- [ ] Same font, colours, spacing across both
- [ ] Both light/dark modes work in Guided
Timeline Philosophy¶
No dates. No deadlines. Each phase is done when it's done right. Quality over speed. A Japanese garden is not built on a schedule — it's built with intention.
The only rule: no phase starts until the previous phase is complete and verified.
Phase 8: Video Tutorials Reading Rooms 📺 ✅ COMPLETE (27 Apr 2026)¶
Goal: Unify 6 video sections (78 videos) into the 3-column reading room pattern with a unified landing page at /videos/.
Deployed: Commits 4025777 and fdddcd6
What Got Done¶
- Created
/videos/unified landing page (78 videos, 6 categories, search, category pills) - 6 video section templates (ai-hub, cloud-labs, certifications, exam-qa, interview-prep, music) — each with list + single page
- DRY consolidation: 12 identical templates → 2 shared partials (
video-single-content.html+video-category-list.html) video-categories.htmlas single source of truth for category metadata (used by nav, landing, and all templates)video-nav.htmlleft sidebar: 6 collapsible categories with individual video linksvideo-companion.htmlright sidebar: practice exams, free tools, recent blog posts, CTAs- VideoObject JSON-LD on all single pages, CollectionPage JSON-LD on landing
- Zen-migrated body class for all 7 video sections in baseof.html
- Video-specific CSS classes (
zt-vid-*) — proper token usage, no inline styles - Upgraded thumbnails from mqdefault (320×180) to hqdefault (480×360)
- Search uses
hiddenattribute instead of brittlestylechecks - Nav updated: "Videos" link →
/videos/hub
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | DRY templates BEFORE polish — 6 identical single.html files meant every fix was 6× edits. Consolidate first, polish once. | High — saved ~500 lines of duplication |
| 2 | hidden attribute > style.display — searching by [style=""] selector is brittle. hidden is semantic, accessible, and CSS-proof. |
Medium — prevented future search bugs |
| 3 | Rubber-duck catches ~30% of issues — identified brittle search logic, unsorted related content, inline style violations, and DRY violations before deployment. | High |
| 4 | Shared category metadata partial — video-categories.html uses Hugo's return to provide data. One source for nav, landing, and templates. Pattern reusable for any grouped content. |
Medium |
| 5 | hqdefault.jpg is the sweet spot — mqdefault (320×180) looks soft on cards; maxresdefault can 404 for some videos. hqdefault (480×360) is always available and sharp enough. |
Low |
| 6 | Sort related content deliberately — first 3 (where ...) without sorting returns arbitrary order. Always sort ... "Date" "desc" for recency-based content. |
Medium |
Phase 9: Free Tools 3-Column Alignment 🧰 ✅ COMPLETE (27 Apr 2026)¶
Goal: Bring the /free-tools/ page into the unified 3-column reading room layout, matching blog, study guides, licensing, and videos.
Deployed: Commit fdddcd6
What Got Done¶
- Wrapped
/free-tools/inzt-readinggrid (left sidebar | center content | right companion) - Created
tools-nav.html: collapsible<details>categories pulled fromtoolkit_nav.tomlwith individual tool links inside each - Created
tools-companion.html: practice exams, study guides, recent blog posts, CTAs - Removed
/free-tools/from baseof.html$isToolPagedetection (page now owns its own grid) - CSS:
zt-reading--toolsoverrides for wider card content area - First category (Prompt Engineering) open by default, rest collapsed — matches all other nav patterns
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | baseof.html tool wrapping creates grid-ception — /free-tools/ was in the $isToolPage list, so baseof wrapped it in zt-reading--tool (3-col). Template then added its own zt-reading grid inside the center column = 5 visible columns. Always check baseof wrapping before adding template-level grids. |
Critical — caused visible layout breakage |
| 2 | Data-driven nav from TOML — toolkit_nav.toml already has categories. Nav pulls from the same source as the card grid — no hardcoded counts to maintain. |
Medium |
| 3 | Breathing space = zt-reading-content padding — the 48px horizontal padding on .zt-reading-content is what gives all 3-column pages their comfortable feel. Without it, hero/content feels squished to the edge. |
Medium |
Unified 3-Column Status¶
All major content sections now use the same reading room pattern:
| Section | Landing | Left Nav | Right Companion | Status |
|---|---|---|---|---|
| Blog | /blog/ |
Blog categories | Tools, guides | ✅ |
| Study Guides | /study-guides/ |
Vendor → cert hierarchy | Practice exams, tools | ✅ |
| Licensing Wiki | /licensing-docs/ |
13 categories, 50 plans | Tools, compare links | ✅ |
| Practice Exams | /guided/explore/ |
Vendor → cert hierarchy | CTAs, tools | ✅ |
| Video Tutorials | /videos/ |
6 categories, 78 videos | Practice exams, tools | ✅ |
| Free Tools | /free-tools/ |
9 categories from TOML | Exams, guides, blog | ✅ |
Pattern: zt-reading grid (250px | 1fr | 280px) → sidebar collapses on mobile to <details> → companion hidden on mobile.
Phase 10: About Page + Legacy CSS Cleanup 👤 ✅ COMPLETE (27 Apr 2026)¶
Goal: Migrate the About page from neon glassmorphism to Zen 3-column reading room, clean remaining legacy CSS.
Deployed: Commits 7f9170b (CSS cleanup) + ee16379 (about page)
What Got Done¶
About page redesign:
1. New layouts/about/single.html — 3-column reading room
2. Left sidebar: page TOC with 7 section jump links
3. Right companion: connect links (YouTube, LinkedIn, Ko-fi), site stats (tools/videos/guides/exams), recent blog posts, explore CTAs
4. Hero card: headshot with object-position: center 20%, name, role, Resume + Links buttons
5. Career timeline: Zen tokens, indigo accent dot for current role, semantic colors
6. Removed ALL neon-cyan/magenta colors, rgba glows, inline <style> blocks from about.md
7. Body class: is-about → page-about zen-migrated (light+dark)
8. About link added to desktop nav
Legacy CSS cleanup (style.css):
1. Blog trainer/tip/agent/living-doc/prompt cards: glass gradients + backdrop-filter → solid var(--bg-elevated) + semantic border colors
2. tool-eco-card: rgba(255,255,255,0.04) → var(--bg-elevated), text rgba(255,255,255,0.5) → var(--text-muted)
3. .ecosystem banner: glass bg → var(--bg-elevated), var(--glass-border) → var(--border)
4. Net: removed 10 backdrop-filter, 12 rgba(255,255,255), 5 var(--glass-*) references
QA:
- test-guided-qa.cjs: 14/14 checks passed ✅ (PracticeQuiz canvas changes verified safe)
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | Content pages benefit most from reading rooms — the About page went from a plain scrolling page to a navigable experience with TOC + companion. Biggest UX improvement per effort. | High |
| 2 | object-position for headshot crops — circular crops on portrait photos cut heads. object-position: center 20% shifts focus upward. |
Low |
| 3 | Playwright screenshots before/after — taking screenshots of current state before redesigning prevents "was it always like that?" confusion and validates improvements. | Medium |
| 4 | Blog card CSS was dark-only — trainer-script/tip/agent cards used rgba dark backgrounds + color: rgba(255,255,255,0.92). Invisible in light mode on zen-migrated blog pages. |
High |
🌸 Zen Migration Final Status (28 Apr 2026)¶
| Section | Landing | 3-Column | Zen Tokens | Light+Dark | Status |
|---|---|---|---|---|---|
| Homepage | / |
Custom grid | ✅ | ✅ | ✅ |
| Blog | /blog/ |
✅ | ✅ | ✅ | ✅ |
| Study Guides | /study-guides/ |
✅ | ✅ | ✅ | ✅ |
| Licensing Wiki | /licensing-docs/ |
✅ | ✅ | ✅ | ✅ |
| Practice Exams | /guided/explore/ |
✅ | ✅ | ✅ | ✅ |
| Video Tutorials | /videos/ |
✅ | ✅ | ✅ | ✅ |
| Free Tools | /free-tools/ |
✅ | ✅ | ✅ | ✅ |
| About | /about/ |
✅ | ✅ | ✅ | ✅ |
| 53 Tool Pages | Individual | ✅ | ✅ | ✅ | ✅ |
| 50 Licensing Pages | Individual | ✅ | ✅ | ✅ | ✅ |
| 78 Video Pages | Individual | ✅ | ✅ | ✅ | ✅ |
| 149 Cert Pages | Individual | ✅ | ✅ | ✅ | ✅ |
| Guided (Astro) | Platform | ✅ | ✅ | ✅ | ✅ |
| Nav | Global | — | ✅ | ✅ | ✅ Unified |
| Footer | Global | — | ✅ | ✅ | ✅ Unified |
| Sidebar titles | All reading rooms | — | ✅ | ✅ | ✅ Parity |
Remaining: ~24 var(--glass-*) refs in style.css (homepage cards — cosmetic only), old mega-menu CSS dead code.
Phase 11: Zen Homepage + Dead CSS Purge + Nav Simplification 🏠 ✅ COMPLETE (27 Apr 2026)¶
Goal: Radical homepage redesign reflecting the truth of the site. Strip away corporate noise. River-flow layout. Plus massive CSS cleanup and nav alignment.
Deployed: Commit 4d0a6d8 (Hugo) + 8cc7caf (Guided)
What Got Done¶
Homepage redesign — "The River": 1. Replaced entire old homepage (232 lines: bento cards, vendor logos, toolkit grid, tabbed content, testimonials carousel, newsletter) with radically simple river flow 2. 5 sections only: Welcome → 6 Pathways → Latest → Voices → Newsletter → Who 3. Line SVG icons replace emojis — monochrome (black in light, white in dark), subtle elevated background squares 4. Highlighted keywords in accent color inside cards: "$9", "No sign-up", "plain English", "Free forever" 5. Practice Exams card has indigo left border (only paid offering — subtle distinction) 6. Personal honest copy: "Everything I learn about cloud & AI at work — and in my own time — I share here. Sometimes as a study guide. Sometimes as a tool. Sometimes as a video or a blog post. Six ways to learn, one honest source." 7. "Built by a Microsoft Engineer" pill badge 8. "For IT pros, students, and anyone studying for cloud & AI certifications" — WHO line for SEO + clarity 9. Newsletter (Guided Weekly) preserved in clean Zen style 10. WebSite + Organization + Person JSON-LD schema added 11. SEO: Title includes "study guides", "practice exams", "certifications". Meta desc covers all 6 offerings.
Nav simplification: 1. Renamed: Cert Study Guides, Cert Practice Exams, Video Tutorials, Free Tools, M365 Licensing Wiki, Blog, About 2. Reordered: Learning first (study → practice → videos) → tools → reference → content → about 3. Logo text hidden on ALL pages — logo icon is sufficient, cleaner nav 4. CTA: "Start Free →" → "Downloads" (links to Ko-fi shop) 5. Mobile drawer: emojis removed, order matches desktop 6. Both Hugo + Astro navs aligned
CSS cleanup:
1. Purged 1185 lines of dead .hp-* homepage CSS from style.css
2. style.css: 143KB → 111KB (-22%)
3. Blog trainer/tip/agent/living-doc/prompt cards → Zen tokens (removed 10 backdrop-filter, 12 rgba hardcodes)
4. tool-eco-card + .ecosystem → Zen tokens
5. zen-migrated on homepage body class — light/dark modes work
Other:
1. /start/ → / redirect — homepage IS the start page now
2. test-guided-qa.cjs: 14/14 passed ✅
Design Decisions & Patterns (REUSE THESE)¶
| Decision | Rationale | Reuse where |
|---|---|---|
| Line SVG icons > emojis | Monochrome, scales with theme, professional. Uses currentColor so black in light, white in dark. |
ALL pages — replace emojis site-wide |
| River flow > grid cards | One thing per screen height. No competition for attention. User reads linearly. | Homepage only — inner pages keep 3-column |
| No search bars — 3-column grid is enough | Sidebar nav + category pills + collapsible groups give instant discovery. Search adds complexity for marginal benefit. Removed from all landing pages (27 Apr 2026). | All landing pages — study-guides, licensing-docs, blog, videos, homepage |
Highlighted keywords (zh-hl) |
Accent color on key phrases ("$9", "No sign-up") draws eye without shouting. | Pathway cards, CTAs, any promotional text |
| Logo text hidden | Logo icon is recognizable enough. Text wastes nav space. | Global — already applied |
| Personal copy > corporate copy | "I share here" > "We offer". First person, warm, honest. | All landing pages, hero text |
| Subtitle = story, not features | "Sometimes as a study guide. Sometimes as a tool." tells HOW the site works, not WHAT it has. | Homepage welcome section |
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | Homepage redesign unlocks CSS purge — 60% of style.css was dead .hp-* rules. Couldn't delete until homepage was rebuilt. Always redesign before purging. |
Critical — 32KB saved |
| 2 | baseof.html body class matters — homepage had is-home without zen-migrated, so footer/global elements stayed glassmorphism in light mode. Always add both. |
High |
| 3 | One paid offering needs distinction — Practice Exams is the only revenue source. A 3px left border is enough — not a different card style, just a whisper of "this one is special". | Medium |
| 4 | /start/ becomes redundant — when the homepage IS clear navigation, a separate "start here" page duplicates it. Redirect, don't maintain two. |
Low |
| 5 | Nav text labels matter — "Study Guides" vs "Cert Study Guides" vs "Licensing Wiki" vs "M365 Licensing Wiki" — specificity helps users and SEO. | Medium |
🌸 Polish Phase: What's Next¶
The Zen migration is structurally complete. Every section has the 3-column reading room. The homepage is redesigned. Now it's polish time — making every page as clean and airy as the homepage.
Priority Order for Polish Sessions¶
| # | Task | Scope | Key work |
|---|---|---|---|
| 1 | ~~Emoji → SVG icon migration~~ | ~~All 6 landing pages + nav sidebars~~ | ✅ COMPLETE (27 Apr 2026) — see below |
| 2 | ~~3-column breathing room~~ | ~~Study guides, licensing, blog landing~~ | ✅ COMPLETE (27 Apr 2026) — see below |
| 3 | ~~Copy simplification~~ | ~~All hero text, card descriptions~~ | ✅ COMPLETE (27 Apr 2026) — see below |
| 4 | ~~Dark mode contrast pass~~ | ~~All pages~~ | ✅ COMPLETE (28 Apr 2026) — see below |
| 5 | ~~Guided light mode polish~~ | ~~Astro platform (Phase F)~~ | ✅ COMPLETE (28 Apr 2026) — unified nav, sidebar parity, dark default |
| 6 | ~~Footer Zen migration~~ | ~~Global (both platforms)~~ | ✅ COMPLETE (28 Apr 2026) — Ko-fi button, icons, Zen tokens, Guardrail #12 parity |
| 6b | ~~Tools overhaul~~ | ~~Categories, sidebar, names~~ | ✅ COMPLETE (28 Apr 2026) — 9→4 categories, consistent sidebar, 42 names simplified, hero rewritten |
| 6c | ~~Theme sync~~ | ~~localStorage cross-platform~~ | ✅ COMPLETE (28 Apr 2026) — unified theme key, auto-migration |
| 7 | style.css final cleanup | Global CSS | Remaining var(--glass-*) refs, old mega-menu CSS, dead .zt-tool-nav-* selectors |
| 8 | CSS consolidation | zt-tools.css → zt-reading.css | Merge — they share 90% of the 3-column pattern |
How to Start a Polish Session¶
Future sessions should:
1. Read phases.md (this file) — full history, lessons, design decisions
2. Read z4-migration-playbook.md — CSS traps, token mapping, detection commands
3. Pick ONE task from the priority table above
4. Pilot on one page → screenshot → compare to homepage feel → scale
5. Update this file with findings and lessons
Polish Phase 1: Emoji → SVG Icon Migration ✅ COMPLETE (27 Apr 2026)¶
Scope: ~1,100 emoji→SVG replacements across 99 files (90 templates, 3 data files, 3 CSS files, 3 config)
What was built¶
| Component | Details |
|---|---|
layouts/partials/icon.html |
Reusable SVG icon partial — 70 monochrome icons using currentColor. Accepts name, size, stroke, fallback, label params. |
| Landing pages (7) | study-guides, free-tools, licensing-docs, blog, videos, about, 404 |
| Sidebar partials (14) | cert-nav, sg-companion, tool-nav, tool-companion, tools-nav, tools-companion, video-nav, video-companion, licence-nav, licence-companion, blog-list-companion, blog-list-nav, feedback-cta, bookmark-cta |
| Individual tool pages (70) | All 53 tool templates + cert-tracker, prompt sections, guided, etc. |
| Data files (3) | toolkit_nav.toml (53 icon fields), section_nav.toml (10), video-categories.html (6) |
| CSS (3 files) | zt-reading.css (SVG alignment for sidebars), free-tools.css (hero stats, tool icons, ::before bullets), style.css (footer links) |
Design Decisions & Patterns (REUSE THESE)¶
| Decision | Rationale |
|---|---|
icon.html partial (not inline SVGs) |
70+ icons reused across 90 templates. DRY. Homepage inlines 6 SVGs — that's fine for static content, but data-driven contexts need a partial. |
stroke-width: 1.5 for ≤16px |
Homepage uses stroke-width: 2 at 20px. Thinner strokes prevent small icons from looking muddy. |
aria-hidden on decorative, aria-label on semantic |
Status flags (retiring/beta/upcoming) have aria-label. All other icons are decorative (aria-hidden="true"). |
fallback param for data-driven icons |
Vendor icons fall back to logo_emoji if slug unknown. Prevents silent blank UI when data changes. Emits warnf in build logs. |
CSS ::before bullet for feature spans |
Free-tools page had ~200 emoji bullets. Replacing each with a partial call would be extremely verbose. A CSS content: "·" pseudo-element is cleaner and more Zen-aligned (consistent, not unique). |
iconName pattern for Hugo dict values |
You cannot nest {{ partial }} inside a Hugo dict string. Store icon names as strings, render at output: {{ partial "icon.html" (dict "name" .iconName ...) }} |
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | Two nav partial sets exist — tool-nav.html (individual tool pages) AND tools-nav.html (free-tools landing). Easy to miss one. Always grep for both patterns. |
High |
| 2 | Bulk Python scripts need f-string brace escaping — {{{{ → {{ in Python f-strings, not {{{{{{. Triple braces break Hugo templates. |
Critical |
| 3 | Hugo dict values are strings — {{ partial ... }} inside "emoji" "{{ partial ... }}" is a string literal, not a template call. Use "iconName" "rocket" + render in template. |
Critical |
| 4 | vendors.toml is auto-generated — don't add fields. Use slug-based lookup (vendor-microsoft) in the icon partial instead. But toolkit_nav.toml IS hand-maintained — safe to add icon field. |
Medium |
| 5 | Feature bullet emojis are decorative — replacing 200 emojis with 200 SVG partial calls is over-engineering. CSS ::before is more Zen. |
Medium |
Remaining emojis (intentionally kept)¶
| Emoji | Context | Reason |
|---|---|---|
☆ / ⭐ |
Prompts — favorite/best-platform stars | Functional UI, not decorative |
🐶 🐛 😂 |
Content/quirky labels | Content meaning, not chrome |
♿ |
Accessibility icon | Semantic |
🇳🇿 |
About page flag | Country flag |
Platform emojis in /prompts/ |
~1000 from data layer | Complex data-driven system — separate migration needed |
Polish Phase 2: 3-Column Breathing Room ✅ COMPLETE (27 Apr 2026)¶
Scope: Spacing, tree-view nav, reading room centering across all 3-column pages.
What was built¶
| Component | Details |
|---|---|
| Breathing room (13 CSS edits) | Hero top padding 24→32px, bottom margin 32→48px. Vendor/category section gaps 32→48px. Card grid gaps 8→12px (study guides), 12→16px (licensing). Blog landing top padding 16→24px, card gap 12→16px, card padding uniform 24px. |
| Tree-view nav (4 sidebars) | +/− toggle boxes on <details> summaries. Thin connector lines (border-left: 1px solid --border-emphasis) on vendor body, category links, and lic-nav-links. Study guides has 3-level tree (vendor→category→cert), others 2-level. |
| Blog TOC connector lines | Nested <ul> in TOC gets border-left — shows h2→h3→h4 hierarchy. No toggles (short TOC benefits from showing all). |
| Blog reading body centered | max-width: 720px; margin: 0 auto on .zt-reading-body — balances whitespace between sidebar and companion. Title/meta stay left-anchored. |
| Grid column dividers | Sidebar border-right + companion border-left bumped from --border to --border-emphasis for visibility in both modes. |
| Blog prev/next fix | Legacy rgba(255,255,255,0.55) color → --text-tertiary token. Removed backdrop-filter + box-shadow glow (Zen guardrail). |
| Blog companion | Shows 10 articles (was 5). |
| Brace typo fix | 3 stray } from */}}} comment typos in study-guides, blog, videos templates. |
Design Decisions¶
| Decision | Rationale |
|---|---|
| +/− text characters (not SVGs) | CSS content: property can't use Hugo partials. +/− are universally understood, match VS Code/Explorer tree pattern. |
--border-emphasis for tree lines |
--border was too faint. --border-emphasis adapts to both modes (#404040 dark, #D4D4D4 light). |
| No +/− on blog TOC | TOC has 5-10 items — collapsing hides useful navigation. Lines alone give tree feel. |
margin-left: 23px on vendor body |
Aligns connector line with center of the 16px toggle box. Not a design token, but a layout alignment value. |
Shared zt-lic-nav-* classes |
Licensing, Videos, Free Tools all use same nav CSS. One change = 3 pages updated. |
Blog body margin: 0 auto |
720px prose in ~900px column creates lopsided gap. Centering balances it. Title stays left to anchor with sidebar. |
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | justify-content: space-between breaks with ::before — 3 flex items get spread out. Use gap + margin-left: auto on the last item instead. |
Critical |
| 2 | Hugo comment triple braces */}}} render a literal } — only need */}}. Found on 3 landing pages from emoji migration batch. Always verify no stray output. |
High |
| 3 | Blog prev/next had hardcoded rgba colors — old glassmorphism style. The zt-reading-content override fixed borders but missed text color. Always check all properties. |
Medium |
| 4 | Tree view without horizontal branches is cleaner — VS Code pattern: vertical guide lines + toggle. No horizontal branch lines needed. Simpler CSS, no last-child edge cases. | Medium |
| 5 | 🔴 ALWAYS bump cache_version when CSS/JS changes — Phase 2 tree-view + blog centering were invisible for 3 deploys because cache_version wasn't bumped. CDN cached the old CSS at the same query string. pre-push-check.ps1 guardrail now catches this automatically. |
Critical |
Polish Phase 3: Copy Simplification ✅ COMPLETE (27 Apr 2026)¶
Scope: Rewrite hero text and category descriptions on all 5 landing pages to personal/honest voice matching the homepage.
What was changed¶
| Page | Before | After |
|---|---|---|
| Study Guides hero | "Free study guides for 53 certifications..." (corporate feature list) | "Some of these I wrote while studying myself. Others I built because people kept asking." + feedback link |
| Free Tools hero | "Professional-grade tools for IT pros — built by Susanth" | "Some I built for work, others just because they seemed useful" + feedback link |
| Free Tools 8 categories | Feature-list descriptions ("Write better prompts...") | Personal stories ("The prompt tools I reach for most", "My old sysadmin life, distilled") |
| Free Tools footer CTA | "Built with Passion, Shaped by You" / "Tell us" / "we build" | "These tools grow with your feedback" / "I build" |
| Free Tools feedback card | "your voice shapes our tools and content" | "your feedback shapes what I build next" |
| Licensing hero | "Deep-dive guides for 50 Microsoft plans..." | "Microsoft licensing is confusing — I know because I explain it to customers all the time" + feedback link |
| Blog hero | "Practical guides for IT pros... Written in plain English by Susanth" | "The questions customers ask me at work, answered in detail" + feedback link |
| Videos hero | "120 free videos across 6 categories. Certification courses..." | "Cert courses, Copilot demos, hands-on labs" — concise + "drop a comment" |
Design Decisions¶
| Decision | Rationale |
|---|---|
| "I" not "we" | One person builds this site. "We" feels dishonest. Matches homepage: "Everything I learn... I share here." |
| Honest about origins | Study guides: "Some I wrote while studying, others I built because people kept asking." NOT "I study every cert" — that's false. |
| Durable phrasing over specific claims | "I keep adding more" not "I add more every week". Avoids copy becoming stale/false. |
| Feedback link on every hero | Consistent "open to correction" tone. Each page links to /feedback/. Videos says "drop a comment" (YouTube comments). |
| Keep M365 in licensing title | "Licensing Guides" too generic. "M365 Licensing Guides" gives instant context while being shorter than the original. |
| Don't rewrite 53 tool card descriptions | Card-level copy is feature-focused — appropriate for that context. Personal voice belongs at hero/category level. |
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | 🔴 Rubber-duck your copy for honesty, not just tone — "I build a guide for every cert I study" was wrong. Sutheesh studied some, created others for the community. Rubber-duck caught tone issues but not factual accuracy. Always ask: "Is this literally true?" | Critical |
| 2 | Over-claiming erodes trust — "I use these daily", "I add more every week" sound great but become false fast. Use durable language: "I reach for most", "I keep adding". | High |
| 3 | Check ALL "we/our" instances — Found stray "Tell us" and "we build" in footer CTA that initial pass missed. Grep for \b(we |our ) across all modified files. |
Medium |
| 4 | cache_version must be bumped with CSS/JS changes — Phase 2's tree-view and blog centering were invisible for 3 deploys. Added pre-push-check.ps1 automated guardrail to catch this. |
Critical |
Guardrail added: pre-push-check.ps1¶
Automated pre-push script that blocks deployment if:
1. CSS/JS files changed but cache_version not bumped
2. Hugo build fails
3. Template markers (ZgotmplZ, unclosed {{) in output HTML
Run before every push: pwsh scripts/pre-push-check.ps1
Polish Phase 4: Dark Mode Contrast Pass ✅ COMPLETE (28 Apr 2026, commit a7eb4e4)¶
Scope: Audit all pages for dark mode contrast issues. Fix unreadable text in both light and dark modes.
Methodology¶
- Built Playwright contrast audit (
scripts/dark-mode-audit.cjs) — visits 30 representative pages in both light + dark mode - For each text element: computes foreground color, walks up DOM compositing rgba backgrounds, calculates WCAG contrast ratio
- Flags issues below AA threshold (4.5:1 normal text, 3:1 large text)
- Initial run found 126 "critical" issues — 87 were false positives (print styles + alpha blending bug)
- Fixed alpha blending in audit script → accurate 39 criticals → fixed down to 19
What was fixed¶
| File | Fix | Impact |
|---|---|---|
cert-compass.js |
30 hardcoded rgba(255,255,255,...) and #fff → Zen tokens |
14 criticals eliminated |
cert-compass/single.html |
3 inline white colors → var(--text-tertiary/primary) |
White-on-light text fixed |
cert-compass/list.html |
5 inline white colors → var(--text-tertiary/secondary) |
Same pattern |
security-toolkit/list.html |
"More Tools" section: rgba(255,255,255,...) backgrounds/text → var(--bg-elevated), var(--text-primary) |
Invisible section in light mode fixed |
admin-comms/list.html |
color:#fff → var(--text-primary) |
Editor title invisible in light mode |
ai-cost-calculator/list.html |
5 unit labels rgba(255,255,255,0.5) → var(--text-muted) |
"%" and "hrs/wk" invisible in light mode |
cert-tracker.css |
--cert-badge-beginner/intermediate/advanced → var(--badge-green/blue/amber) |
Badges used same color for text and bg tint |
copilot-matrix.css |
Consumer/Enterprise badges #C4B5FD/#93C5FD → var(--badge-purple/blue) |
Light purple on light purple tint |
licence-picker.css |
Dependency warning var(--warning) → var(--badge-amber) |
Yellow on white |
service-health.css |
Split status colors: light mode darker (#15803D/#A16207/#DC2626), dark mode brighter (#4ADE80/#FACC15/#F87171) |
Yellow "Degraded" on white was 1.92:1 |
prompt-lab.css |
Tier heading --tier-color → var(--text-primary) |
Teal on white was 1.78:1 |
style.css |
Added --success/--warning/--error overrides to body.zen-migrated for both modes |
Global semantic token gap |
Remaining 19 criticals (all acceptable)¶
| Count | Page | Reason skipped |
|---|---|---|
| 10 | countdown | Emoji buttons — emojis render as colored images, CSS color doesn't affect them |
| 2 | cert-compass | Decorative ● empty dots — intentionally invisible (design) |
| 2 | licence-picker | ✓ checkmark transparent when unselected (intentional state) |
| 3 | roadmap | Star ★ intentionally subtle until hover + one dark category inline color |
| 2 | deprecation-timeline | color-mix() measurement artifact in audit |
Lessons Learned¶
| # | Lesson |
|---|---|
| 1 | Print styles are not dark mode issues — @media print { background:#fff; color:#000 } is correct. Don't bulk-fix print blocks. |
| 2 | rgba alpha compositing matters — rgba(16,185,129,0.15) on dark bg ≈ rgb(3,28,19), NOT rgb(16,185,129). Audit tools must blend alpha layers against parent backgrounds. |
| 3 | Tinted badges ≠ filled badges — blanket color:#fff breaks on tinted (low-alpha) backgrounds. Split: filled badges get white text, tinted badges get dark token text. |
| 4 | JS-generated inline styles need token refs — color:${statusColor} in JS templates can't be overridden by CSS. Use var(--token) in inline styles so CSS custom properties handle mode switching. |
| 5 | Semantic tokens (--success/--warning/--error) must flip per mode — bright green/yellow/red work on dark backgrounds but fail on light. Added mode-aware values to body.zen-migrated. |
Polish Phase 4b: Sidebar First-Category Expanded ✅ COMPLETE (28 Apr 2026, commit 14096b7)¶
Scope: All 6 landing page sidebar navs — expand the first category by default so visitors see content immediately.
| Landing | Nav partial | First category | Status |
|---|---|---|---|
/study-guides/ |
cert-nav.html |
Microsoft → Azure | Already worked |
/free-tools/ |
tools-nav.html |
Prompts & AI (via $isFirst) |
Already worked |
/licensing-docs/ |
licence-nav.html |
Enterprise | Fixed — opens when $currentCat is empty |
/videos/ |
video-nav.html |
First video category | Fixed — opens when $currentPermalink = /videos/ |
/blog/ |
blog-list-nav.html |
N/A — flat list | No categories to expand |
/about/ |
— | N/A — no sidebar nav | N/A |
Polish Phase 5: Guided Zen + Unified Nav + Dark Default ✅ COMPLETE (28 Apr 2026)¶
Scope: Align the Guided Astro platform to Zen, unify the nav across both platforms, set dark mode as default.
What Got Done¶
- Guided light mode polish — removed all orb decorative divs, fixed font preloads (Satoshi→Inter), removed ALL
backdrop-filter/backdrop-blur(9 instances across 5 files), replaced translucent/hardcoded colors with Zen tokens (10 files) - Unified nav — rewrote Astro Header.astro pixel-for-pixel matching Hugo nav: 3-column CSS grid, circle logo, nav links with accent pill hover, mobile drawer slide-from-left
- Sidebar parity — removed unwanted cross-links, added indigo connector lines, synced tree-view CSS, removed grey sidebar background
- Dark mode default — Hugo now defaults dark on first visit (Guided already did)
- Guardrail #12 added: "One Body Two Organs" — any shared element change must update BOTH platforms in same session
Polish Phase 6: Footer Zen + Sidebar Title Parity ✅ COMPLETE (28 Apr 2026, commit 9f38103 + Guided acd3ad0)¶
Scope: Migrate footer to Zen tokens, unify across Hugo and Guided, add sidebar title parity.
What Got Done¶
- Hugo footer — Ko-fi
rgba→ official Ko-fi branded button (CDN), removed opacity hacks, all spacing → Zen tokens - Guided footer — full rebuild matching Hugo (same 6 links, same icons, same structure)
- Sidebar title parity —
.zt-lic-nav-header(Videos, Licensing, Free Tools) now matches.zt-cert-nav-headerwithborder-left: 3px solid var(--accent)+ bottom divider
Polish Phase 7: style.css Dead Code Cleanup ✅ COMPLETE (28 Apr 2026, commit a444801)¶
Scope: Remove dead CSS and JS from the codebase — mega-menus, old nav dropdowns, border-beam, orphaned homepage responsive rules.
Results¶
| File | Before | After | Saved |
|---|---|---|---|
style.css |
3,827 lines / 111.7 KB | 3,222 lines / 92.3 KB | 605 lines / 19.5 KB |
switcher.js |
447 lines / 18 KB | 88 lines / 3.2 KB | 359 lines / 14.8 KB |
| Total | 964 lines / 34.2 KB |
What Was Removed¶
| Category | Lines | Notes |
|---|---|---|
| Mega-menu CSS | 310 | .mega-menu, .mega-smart-*, .mega-learn-*, .mega-toolkit-* — nav simplified to 6 direct links |
| Nav dropdown CSS | 47 | .nav-dropdown, .dropdown-toggle, .dropdown-menu — no HTML uses them |
| Border-beam CSS | 50 | Decorative neon conic-gradient animation — zero template references |
| nav-cat-label + divider | 23 | Legacy dropdown artifacts |
| Dead drawer CSS | 42 | .drawer-tabs, .drawer-tab, .drawer-group, .drawer-features — drawer simplified |
| Dead mobile overrides | 86 | Dropdown + mega-menu mobile layouts inside @media (max-width: 1024px) |
| Dead hp-* responsive | 24 | hp-toolkit-grid, hp-blog-grid, hp-ray-* — old homepage |
| Smart Mega Menu JS | 117 | Search + recent tools IIFE — no HTML emits the target IDs |
| Dropdown handlers JS | 91 | Click, keyboard, close-outside — no .dropdown-toggle in HTML |
| HP-carousel/tab JS | 60 | hp-hscroll-*, hp-content-tab — dead homepage carousel |
| Drawer tab/group JS | 43 | Dead tabbed drawer switching |
What Was NOT Touched (Documented Tech Debt)¶
These require per-component Zen migration, not bulk removal:
--neon-*variables (~32 usages) — blog timeline, blockquotes, video card tags, pills, FAQ, focus-visible, back-nav--glass-*variables (~14 usages) — blog search, blog CTA, back-to-top button, feedback FAB, page hero. Also used byreadiness.css.backdrop-filter(~38 lines) — mix ofblur()on legacy pages andnoneoverrides for zen-migrated pages- Hardcoded
rgba(...)— content-body, 404 page, blog timeline, callouts
Rubber-Duck Catches¶
| # | Finding | Action |
|---|---|---|
| 1 | .welcome-inner still in welcome-strip.html — NOT dead |
Kept ✅ |
| 2 | readiness.css also uses --glass-* — can't remove vars |
Deferred removal ✅ |
| 3 | Dead nav dropdown + drawer groups not in original scope | Added to cleanup (+130 lines found) ✅ |
| 4 | Smart Mega Menu IIFE also dead | Removed additional 117 lines ✅ |
Lessons Learned¶
| # | Lesson |
|---|---|
| 1 | Grep ALL CSS files, not just the target — readiness.css consuming --glass-* was invisible when only auditing style.css. Always search the entire static/css/ directory. |
| 2 | Separate dead code removal from visual migration — removing dead selectors is zero-risk. Replacing token values (glass→Zen) changes appearance on legacy pages. Keep these as separate commits. |
| 3 | JS querySelectorAll on missing elements is safe — dead JS that searches for non-existent DOM elements returns empty lists. No runtime errors, but still dead weight to remove. |
Self-Reminders: Certification Watch¶
| Cert | Status (28 Apr 2026) | URL | Action |
|---|---|---|---|
| AI-200 | 🔴 404 — not published yet | learn.microsoft.com/.../study-guides/ai-200 |
Beta was expected April 2026. Check every session. Starter prompt ready at files/ai200-course-starter-prompt.md. |
| SC-500 | 🔴 404 — not published yet | learn.microsoft.com/.../study-guides/sc-500 |
Beta expected May 2026. Check every session. Starter prompt ready at files/sc500-course-starter-prompt.md. |
Tool Zenification Progress (Phase 13)¶
| # | Tool | Status | Commit | Date |
|---|---|---|---|---|
| 1 | AI News | ✅ | — | 28 Apr |
| 2 | M365 Roadmap | ✅ | — | 28 Apr |
| 3 | Service Health | ✅ | — | 28 Apr |
| 4 | Deprecation Timeline | ✅ | — | 28 Apr |
| 5 | AI Service Mapper | ✅ | — | 28 Apr |
| 6 | AI SaaS Showdown | ✅ | — | 28 Apr |
| 7 | Cert Compass | ✅ | — | 28 Apr |
| 8 | Licensing Simplifier | ✅ | — | 28 Apr |
| 9 | Licence Picker | ✅ | — | 28 Apr |
| 10 | ROI Calculator | ✅ | — | 28 Apr |
| 11 | CA Policy Builder | ✅ | — | 29 Apr |
| 12 | Purview Starter Kit | ✅ | — | 29 Apr |
| 13 | PowerShell Builder | ✅ | — | 29 Apr |
| 14 | AI Cost Calculator | ✅ | 44caf3a |
29 Apr |
| 15 | Prompt Polisher | ✅ | a43a8c7 |
29 Apr |
| 16 | Prompt Guide | ✅ | e76beda |
29 Apr |
| — | Token Calculator (NEW #54) | ✅ | fe33b8e |
29 Apr |
| 17 | Advanced Prompt Lab | ✅ | 67ca542 + dafaac4 |
29 Apr |
| 18 | Prompt Tester | ✅ | 09713fe + dafaac4 |
29 Apr |
| 19 | Copilot Readiness | ✅ | 0f43dcd |
30 Apr |
| 20 | Meeting Planner | ✅ | 1082bde |
30 Apr |
| 21 | QR Generator | ✅ | b990348 |
30 Apr |
| 22 | WiFi Cards | ✅ | f805155 |
30 Apr |
| 23 | Password Generator | ✅ | 5357be8 |
30 Apr |
| 24 | Image Compressor | ✅ | da516eb |
30 Apr |
| 25 | Typing Test | ✅ | 0705f6f |
30 Apr |
| 26 | Countdown Timer | ✅ | 3dbeb3e |
1 May |
| 27 | Color Palette | ✅ | feca3cd |
1 May |
| 28 | Security Toolkit | ✅ | 57031e1 |
1 May |
Phase 12: Content Canvas — Page Resourcefulness 🎯 (Starting 28 Apr 2026)¶
"A page should be a river — the user flows through it, never getting stuck on decoration."
Goal: Go page by page through the site's most important pages and apply the Zen "content is king" philosophy to the middle content canvas only. Remove dead weight, simplify layouts, improve information density, make every pixel earn its place.
⚠️ Scope Rule — MIDDLE CANVAS ONLY¶
Phase 12 does NOT touch: - Left sidebar navigation (already settled in Phase 7-8) - Right companion sidebar (already settled in Phase 7-8) - Nav/footer (owned by Phase 6) - 3-column grid structure (owned by Phase 5)
Everything in this phase targets the center column — the content the user came for. The frame is done; now we polish what's inside it. Each element in the middle canvas must earn its place: colour choice, card structure, text hierarchy, spacing, and information density.
Why This Phase Exists¶
Phases 1-11 built the frame: unified 3-column grid, consistent nav/footer, Zen tokens, light/dark mode. Polish Phase 8 eliminated all legacy CSS (zero neon/glass/backdrop-filter across 50+ files).
The structure is solid. But the content INSIDE the frame — the middle canvas — is still cluttered. Many pages have: - Decorative sections that don't help the user - Redundant information repeated from nav/sidebar - Complex layouts where simple lists would do - "How It Works" sections no one reads - Excessive spacing, nested containers, visual noise
The homepage redesign ("The River") proved the approach: strip to essentials, let content breathe, highlight what matters. Phase 12 applies this thinking to individual pages.
The Approach¶
7-page project — all pages using the 3-grid system (left sidebar + middle canvas + right sidebar):
| # | Page | Platform | Current Pain |
|---|---|---|---|
| 1 | /blog/ |
Hugo | ✅ DONE — river rows, compact header, inline filters |
| 2 | /videos/ |
Hugo | Heavy hero, dates on cards make content look stale, stat pills are filler |
| 3 | /study-guides/ |
Hugo | Guide cards could surface key info better, vendor grouping could be cleaner |
| 4 | /free-tools/ |
Hugo | Cards have too much info, category sections could breathe more |
| 5 | /guided/explore/ |
Astro | Practice exam listing — apply same Zen lens |
| 6 | /licensing-docs/ |
Hugo | Content density, comparison tables need clarity |
| 7 | /about/ |
Hugo | Personal page — evaluate what earns its place |
The Process (Per Page)¶
- Screenshot — Playwright captures of current state (both modes, desktop + mobile)
- Audit — list every element in the content canvas, classify: essential / nice-to-have / dead weight
- Rubber-duck — critique the simplification plan before touching code
- Implement — remove dead weight, simplify layouts, improve hierarchy
- QA — Playwright both modes + mobile, verify nothing broke
- Before/after comparison — side-by-side screenshots to validate improvement
Zen Content Canvas Principles¶
"Attract people to the substance, not the outside flashiness. Give quality inside — not just bright packaging with nothing in it."
The anti-mantra: Modern web design shouts — bold headings, flashy heroes, gradients, visual calories that taste sweet but nourish nothing. Zen does the opposite. Quiet, confident design that trusts the content to speak for itself. People come for substance and stay because it's genuinely good.
The weight test: Before adding any visual emphasis (bold, colour, size, border, shadow), ask: "Is this shouting?" Hierarchy should come from colour contrast and position, not from weight and size. font-weight: 500 not 700. text-primary vs text-muted — not big vs small. The river is calm.
| Principle | Rule | Test |
|---|---|---|
| Substance over packaging | The content IS the design. Visual chrome exists only to serve it. | Would removing this element make the content harder to consume? If no → remove it. |
| Content first | The main content visible without scrolling past chrome | Can the user see real content within the first 600px of the canvas? |
| One purpose per section | Each section does one thing | If you removed it, would the page lose a specific capability? |
| Progressive disclosure | Details hide behind clicks, not scroll | Are FAQ/details using <details> elements? |
| Scannable hierarchy | User can skim headings and understand the page | Do h2/h3 tell a story on their own? |
| Breathing room | Content doesn't touch the edges | Is there consistent spacing between sections? |
| Whisper, don't shout | Use font-weight: 500 max for body content. Hierarchy via colour, not boldness. |
Is anything on the page louder than the content it serves? |
| No "How It Works" | Users figure it out by using it | Is there an instructional section that could be a tooltip instead? |
Definition of Done (Per Page)¶
- [ ] Screenshot comparison shows measurable reduction in visual noise
- [ ] Content visible within first 600px without scrolling past decorative chrome
- [ ] Zero "How It Works" or instructional preamble sections
- [ ] Both modes + mobile verified
- [ ] No broken functionality
- [ ] Hugo build passes
Definition of Done (Phase 12 Complete)¶
- [ ] All 6 pages simplified
- [ ] Playbook updated with patterns and lessons
- [ ] Before/after screenshots archived
Page 1: /blog/ — Content Canvas Brainstorm (28 Apr 2026)¶
Current state audit¶
14 articles. Tags: Copilot (8), What's New (3), Guide (1), AI Agents (1).
| Element | Earns its place? | Verdict |
|---|---|---|
| h1 "Blog" + 3-line subtitle + 3 stat pills | ❌ Heavy hero, 2 pills are filler | Simplified → compact "Blog · N articles" + 1-line desc |
| Category tag pill on each card | ✅ | Quick visual scan for content type |
| Date "Jan 2026 · 15 min" | ✅ | Freshness + depth signal |
| h2 Title | ✅ Essential | The #1 thing users scan |
| Description (truncated 150 chars) | ❌ Dead weight | Titles are already 50-85 chars and self-documenting. Every description just rephrases the title |
Card background (bg-surface) |
🟡 | Visual separation, but adds weight |
| Card border + border-radius | 🟡 | Click affordance, but adds "boxy" feel |
| 24px card padding | 🟡 Excessive | Could be tighter |
| 16px gap between cards | ✅ | Breathing room without waste |
| Inline category filters (new) | ✅ Essential | Mobile users can't see sidebar — need inline filters |
Key finding: Descriptions are dead weight. Example: - Title: "Microsoft 365 Copilot Deployment Best Practices — The Ultimate Checklist for IT Admins" - Desc: "Complete deployment checklist for Microsoft 365 Copilot. Covers licensing, security, governance..." - The title says everything. The description adds zero information.
This is true for ALL 14 posts. The titles are verbose and descriptive by design.
Four design concepts¶
Concept A: River Rows (Recommended ⭐)¶
Inspired by Vercel blog, Hacker News, Dan Abramov's blog.
No cards. No backgrounds. Just clean rows separated by a subtle 1px bottom border. Title is the star — everything else is metadata.
[Copilot] Jan 2026 · 15 min
Microsoft 365 Copilot Chat — The Complete Train-the-Trainer Guide
──────────────────────────────────────────────────────────────────
[What's New] Mar 2026 · 8 min
What's New in Microsoft 365 Copilot – March 2026
──────────────────────────────────────────────────────────────────
- Pros: Lightest visual weight. Maximum content density. Most "Zen". Title is the only thing fighting for attention. Scales well as blog grows. No description = no dead weight.
- Cons: Less visual affordance that items are clickable (mitigated by hover state). Less visual "polish" than cards.
- Hover: Entire row gets subtle
bg-elevatedbackground + title turns accent colour.
Concept B: Compact Cards (No Description)¶
Current design minus the description. Tighter padding.
┌──────────────────────────────────────────────────────────────┐
│ Copilot Jan 2026 · 15m │
│ Microsoft 365 Copilot Chat — Complete Train-the-Trainer Guide │
└──────────────────────────────────────────────────────────────┘
- Pros: Familiar card pattern. Clear click targets. Minimal change from current.
- Cons: Cards still feel "boxy". Background colour + border + radius = visual weight. Each card is still its own island, not a river.
Concept C: Title-First List¶
Title is the headline. Metadata is muted below it. No card boundaries.
Microsoft 365 Copilot Chat — The Complete Train-the-Trainer Guide
Copilot · January 2026 · 15 min read
Microsoft 365 Copilot Chat Changes April 15, 2026
Copilot · April 2026 · 8 min read
- Pros: Title dominance. Clean. Blog-native feel.
- Cons: Tag pill loses its visual punch (becomes inline text). Harder to scan categories at a glance.
Concept D: Featured Latest + Compact List¶
Latest post gets a bigger treatment. Older posts become a compact list.
┌──────────────────────────────────────────────────────────────┐
│ LATEST · Copilot · April 2026 │
│ Microsoft Copilot Cowork — The Complete Guide │
│ Everything you need to know about Copilot Cowork... │
└──────────────────────────────────────────────────────────────┘
Copilot Chat Changes April 15, 2026 Copilot · Apr 2026
Copilot Control System — Complete Guide Copilot · Mar 2026
February 2026 Updates | 36 New Features What's New · Feb 26
- Pros: Highlights fresh content. Compact for older posts. Good for returning visitors.
- Cons: Arbitrary distinction (why is one post "special"?). Two different visual patterns = more cognitive load.
Recommendation¶
Concept A (River Rows) is the strongest Zen approach: 1. Eliminates all visual noise — no bg-surface, no border-radius, no card padding 2. Title is the only thing that matters — which matches how users actually scan 3. Combined with inline filter pills, users can narrow by category instantly 4. 14 posts would fit in ~1.5 scrolls instead of ~3-4 currently 5. Hover state provides sufficient click affordance 6. Most aligned with the "river" metaphor — content flows, nothing dams it
Combined with the already-implemented compact header ("Blog · 14 articles") and inline filter pills, the full middle canvas becomes:
Blog 14 articles
Copilot, Azure, licensing, and AI — explained.
[All] [Copilot] [What's New] [Guide] [AI Agents]
[Copilot] Apr 2026 · 45 min
Microsoft Copilot Cowork — The Complete Guide to AI That Does Work
──────────────────────────────────────────────────────────────────
[Copilot] Apr 2026 · 12 min
Copilot Chat Changes April 15, 2026 — What Every Admin Needs to Know
──────────────────────────────────────────────────────────────────
[Copilot] Mar 2026 · 30 min
The Copilot Control System — Your Complete Guide to Governing AI
──────────────────────────────────────────────────────────────────
That's a river. 🏞️
Decision log (28 Apr 2026)¶
| Decision | Chosen | Why |
|---|---|---|
| Card structure | Option A: River Rows | Lightest, most Zen. No bg-surface, no border-radius. Title is the only content. |
| Descriptions | Removed | Every description rephrases the title. Dead weight on all 14 posts. |
| Title weight | 500 (medium) | 600 felt too loud. Hierarchy via colour contrast, not boldness. "Whisper, don't shout." |
| Category tag position | Merged into right-side metadata | Tag · Date · Reading time as one quiet line. Frees the left side for the title. |
| Inline filters | Kept in header area | Essential for mobile (sidebar hidden). Also adds navigation above the river. |
| Filter deep-linking | ?tag= URL param |
Survives refresh/share. Syncs sidebar + inline pills. |
| Hero | Compact: "Blog · N articles" + 1-line desc | Old hero was 3 lines + 3 pills. Two pills were filler. |
| "New" badge | Posts < 14 days | Helps returning visitors spot fresh content. Uses --success green. |
| Hover state | bg-elevated + accent left border + title accent colour | Triple affordance: background, border, colour. Clear "you're here". |
| Sidebars | Untouched | Phase 12 scope = middle canvas only. |
Files changed¶
layouts/blog/list.html— new template (river rows + compact header + inline filters + updated JS)static/css/zt-reading.css— river row styles, compact header styles, inline filter styleshugo.toml— cache_version bump
✅ Page 1 complete. Deployed 28 Apr 2026.
Page 2: /videos/ — Content Canvas (28 Apr 2026)¶
Changes applied¶
Shared template (video-category-list.html) — affects all 6 video sub-sections:
- Heavy hero → compact header ("Certification Courses · 14 videos")
- Removed dates from card taglines (2022 dates made current content look stale)
- Shortened view counts: "523,083 views" → "523K views" (same signal, less noise)
- Removed decorative icons from section headers + category jump pills
- Removed card hover box-shadow (Zen stays flat — just border-color change)
- Video grid: minmax(240px) → minmax(180px) = 4 columns instead of 3
/videos/ landing page:
- Same compact header pattern as blog: "Video Tutorials · 78 videos"
- 1-line description: "Cert courses, Copilot demos, hands-on labs — all free on YouTube."
Blog mobile refinement (bonus): - Title moved above meta on mobile (≤768px) - Category tag hidden on mobile - Meta left-aligned below title - Fixed CSS cascade bug: mobile media query was before base styles (overridden by cascade)
Decision log¶
| Decision | Chosen | Why |
|---|---|---|
| Remove dates from video cards | Yes | All videos are 2022. Dates signal "old" even though content is current. View counts are the better freshness/quality signal. |
| Shorten view counts | 523K format | Same signal, easier to scan. Substance without noise. |
| Remove icons | Yes | Section name IS the label. Icons are decoration that doesn't add information. |
| Remove hover shadow | Yes | Blog rows don't lift, video cards shouldn't either. Zen stays flat. |
| 4 columns | minmax(180px) | Higher density for 78 videos. Thumbnails still readable at 180px. |
| Shared template change | Yes | High leverage — all 6 sections get the treatment at once. |
Cumulative learnings (apply to all remaining pages)¶
- Hero pattern is solved — compact header:
h1 + count + 1-line desc. No stat pills, no icons, no marketing language. - Dates can be harmful — if all content is from the same era, dates signal "old". Remove or replace with a better signal (views, "New" badge).
- CSS cascade matters — mobile media queries MUST come AFTER base styles. Never define mobile overrides before the base class exists.
- Icons are usually decoration — if the text label is clear, the icon adds no information. Remove it.
- Hover effects should be flat —
border-colorchange, notbox-shadowlift. Zen stays grounded. - "Whisper, don't shout" —
font-weight: 500max, hierarchy via colour contrast not size/weight. - "Substance over packaging" — if removing an element doesn't lose information, remove it. Every element must earn its place.
Files changed¶
layouts/videos/list.html— compact header, no dates, short view counts, no iconslayouts/partials/video-category-list.html— shared template: same treatmentlayouts/blog/list.html— tag-wrap span for mobile hidestatic/css/zt-reading.css— 4-col grid, no shadow, blog mobile layout fixhugo.toml— cache_version bump
✅ Page 2 complete. Deployed 28 Apr 2026.
Page 3: /study-guides/ — Content Canvas (28 Apr 2026)¶
Changes applied¶
- Heavy hero → compact header ("Study Guides · 149 guides" + 1-line desc)
- Search bar added — filters by exam code + title, auto-hides empty categories/vendors
- Vendor header icons removed, vendor count badge → plain text (no pill)
- Vendor header weight: 600 → 500
- Card hover lift (
translateY(-1px)) removed — flat hover - Exam code weight: 700 → 600
- Card padding: 16px → 12px, grid: 3 → 4 columns
- Prominence flip: level badges (Fund/Assoc/Expert) → muted grey; status flags (Retiring/Beta/Upcoming) → coloured pills. Actionable info gets colour, static metadata whispers.
- Status flag icons removed (text is enough)
- Mobile padding: 48px → 16px (was squishing content)
- Blog: category tag hidden on desktop too (filter pills handle it)
Key decision: Prominence flip¶
Level is static metadata — it never changes and doesn't require action. Status (Retiring/Beta) is urgent and actionable. The urgent thing earns the colour. This principle applies to ALL future card designs: colour = action, grey = reference.
✅ Page 3 complete. Deployed 28 Apr 2026.
Page 4: /free-tools/ — Content Canvas (28 Apr 2026)¶
Changes applied¶
- Heavy hero → compact header ("Free Tools · 53 tools" + 1-line desc)
- Complete template rebuild: 400-line hardcoded cards → data-driven from
toolkit_nav.toml - Hybrid responsive: Mini Cards on desktop (icon + name + tagline) → App Launcher on mobile (icon + name, 3-col grid, desc hidden)
- Removed: CTA text, feature chips, card head pill wrapper, hover lift, category icons
- Category title weight: 600 → 500
- Card padding: 24px → 12px
- Search bar added (filters by name + description)
- Mobile padding fixed
Key decisions¶
- Data-driven > hardcoded — 53 tools should come from the TOML registry, not be manually duplicated in HTML
- Hybrid responsive — different information density for different viewports. Desktop has room for taglines; mobile needs density.
- Feature chips removed — description already tells the story. Chips were marketing in disguise.
- CTA text removed — the card IS the link. "Explore Prompts →" adds zero information.
User saw 3 concepts live:¶
- App Launcher (icon + name only) — maximum density
- Mini Cards (icon + name + tagline) — balanced ⭐
- River List (like blog) — medium density Chose: Concept 2 desktop + Concept 1 mobile
✅ Page 4 complete. Deployed 28 Apr 2026.
Page 5: /guided/explore/ — Content Canvas (28 Apr 2026)¶
Platform: Astro (C:\ssClawy\guided)
Changes applied¶
- Heavy hero → compact header ("Practice Exams · N exams · N vendors")
- Stat pills removed (redundant)
- Card restructure — split-line layout: code left, value right on same scan line
- Colour coding: questions in accent (indigo), price in green (success) — two colours with meaning
- Tagline removed (name is self-documenting)
- "Free Guide" → muted grey pill (reference), "Coming Soon" → amber pill (actionable)
- Card hover lift removed, weights reduced (500/600)
- Mobile padding: 48px → 16px
Key decisions¶
- Split-line (Concept A) chosen over Big Number (B) and River (C) — user saw A and B live
- Two-colour value system: accent = what you GET (questions), green = what you PAY (price)
- "Free Guide" muted — reference info doesn't need colour. Only actionable status (Coming Soon) earns colour.
✅ Page 5 complete. Deployed 28 Apr 2026.
Page 6: /licensing-docs/ — Content Canvas (28 Apr 2026)¶
Changes applied¶
- Heavy hero → compact header ("M365 Licensing Guides · N plans")
- Search bar added (filters by plan name + category)
- Icons removed from jump pills + section headers
- Split-line cards: plan name left, price right
- Price in green (
--success), "Free" in accent (--accent) - Coloured semantic badges: Most Popular/SMB Favourite → indigo, Best Value → green, Coming → amber
- Card hover lift removed, weights reduced to 500
- Category count badge: pill → plain text
- Category title weight: 500
- Mobile padding fixed
Key decision: Semantic badge colours¶
Badges matched to meaning using existing Zen tokens:
- --accent (indigo) = social proof (Popular, Favourite)
- --success (green) = value signal (Best Value)
- Amber = time-sensitive (Coming Soon)
This completes the badge colour system across all pages: colour = actionable/important, grey = reference.
✅ Page 6 complete. Deployed 28 Apr 2026.
Page 7: /about/ — Content Canvas (28 Apr 2026)¶
Changes applied¶
- Awards & Certifications: comma-separated paragraphs → muted pill chips (scannable)
- Disclaimer: collapsed behind
<details>(click to expand — legally there, not in the way) - "Join the Journey": icons removed from links (text is enough)
- Timeline role weight: 600 → 500
- Mobile TOC: inline styles → proper CSS classes
✅ Page 7 complete. Deployed 28 Apr 2026.
🏁 Phase 12 Complete — Summary¶
7 pages Zenified. 7 deploys. One session.
Cumulative Learnings (carry forward to Phase 13)¶
| # | Principle | First Discovered | Applied To |
|---|---|---|---|
| 1 | Hero → compact header | Blog | All 7 pages |
| 2 | "Whisper, don't shout" — font-weight: 500 max, hierarchy via colour |
Blog | All weights across all pages |
| 3 | "Substance over packaging" — if removing it doesn't lose info, remove it | Blog | Descriptions, CTAs, chips, icons |
| 4 | Dates can be harmful — old dates signal stale content | Videos | Video cards |
| 5 | Icons are usually decoration — text labels are enough | Videos | Section headers, jump pills, links |
| 6 | Hover stays flat — border-color change, no translateY or box-shadow |
Study Guides | All card hovers |
| 7 | Colour = action, grey = reference (prominence flip) | Study Guides | Level badges, status flags, licensing badges |
| 8 | Data-driven > hardcoded — use TOML registry, not 400 lines of HTML | Free Tools | Tool cards from toolkit_nav.toml |
| 9 | Hybrid responsive — different density per viewport | Free Tools | Mini cards (desktop) → app launcher (mobile) |
| 10 | Two-colour value system — accent = what you get, green = what you pay | Guided Explore | Practice exam cards |
| 11 | Semantic badge colours — indigo (social proof), green (value), amber (time-sensitive) | Licensing | Licensing badges |
| 12 | Mobile padding — always add @media (max-width: 1024px) override for center column padding |
Study Guides | All pages |
| 13 | CSS cascade — mobile media queries MUST come after base styles | Blog | Blog mobile layout |
| 14 | Progressive disclosure — legal/meta content behind <details> |
About | Disclaimer |
| 15 | Search earns its place at 50+ items — study guides (149), free tools (53), licensing (50+) | Study Guides | 3 pages |
Phase 13: Content Canvas Layer 2 — Going Deeper 🎯¶
"The house is clean. Now polish each room."
Goal: Phase 12 cleaned the listing pages (layer 1). Phase 13 goes one layer deeper — into the individual content pages that users land on after clicking a card. Pick one item per section, Zenify it thoroughly, then batch-apply the patterns to the rest.
⚠️ Scope Rule — LAYER 2 (Individual Content Pages)¶
Phase 13 targets the single/detail pages — what you see AFTER clicking a card on the listing page:
- A single study guide page (e.g. /cert-tracker/az-900/)
- A single practice exam page (e.g. /guided/az-900/)
- A single video page (e.g. /certifications/az-104-full-course/)
- A single licensing wiki page (e.g. /licensing/microsoft-365-e5/)
- A single blog post (e.g. /blog/copilot-cowork-complete-guide/)
NOT the listing pages (those are done in Phase 12). NOT individual tools (those are unique — saved for a dedicated session).
The Process¶
- Pick one representative page per section (the most-viewed or most complex)
- Audit the middle canvas — same Zen lens as Phase 12
- Rubber-duck the simplification plan
- Implement on the single page
- Batch-apply the pattern to all siblings (shared templates make this efficient)
- QA both modes + mobile
5 Sections to Cover¶
| # | Section | Representative Page | Shared Template |
|---|---|---|---|
| 1 | Study Guides | Pick the most complex cert (e.g. AZ-104) | cert-tracker/single.html |
| 2 | Practice Exams | Pick a live exam with modules | Astro [cert]/practice.astro + [slug]/index.astro |
| 3 | Video Tutorials | Pick a high-view cert video | video-single-content.html partial |
| 4 | Licensing Wiki | Pick E5 or E3 (most complex) | licensing/single.html |
| 5 | Blog Posts | Pick the longest post | blog/single.html |
Tools — Saved for Dedicated Session¶
Individual tools (53 of them) each have unique layouts. These need per-tool attention and will be handled in a separate session after Phase 13.
Phase 13a: Study Guide Single — Interactive Embed + Zen ✅ COMPLETE (28 Apr 2026)¶
Goal: Transform the study guide single page from a link list to an in-place learning experience. Bring the interactive study guide (Astro) directly into the Hugo page.
Deployed: Commits 35aba77 (Guided) + d27464d (Hugo)
What Got Done¶
Interactive Study Guide Embed (the big feature):
1. New EmbedLayout.astro — minimal wrapper for iframe embedding (no nav/sidebar/footer)
2. New embed/[...slug].astro — generates embed pages for all 945 modules at /guided/embed/{slug}/
3. Hugo curriculum section rebuilt as expandable <details> accordions
4. Lazy-load iframe on click — only loads what the user opens
5. Hover prefetch — pre-loads on mouseenter for near-instant expand
6. postMessage height sync — iframe auto-resizes to fit content
7. Live progress sync: "Mark as done" in iframe → parent updates domain counters
8. "Continue where you left off" button — auto-detects next unfinished module
9. Domain completion counters: "3/6" → "✓ Complete" on each domain header
10. Study hero bar: module count (27), total study time (~5h 41m), completed count
11. All-complete state: celebration message + practice exam CTA
12. Dev mode: hugo.IsDevelopment → iframes point to localhost:4322 Astro dev server
Two-Section Layout:
1. Section 1: Interactive Study Guide — hero bar, feature pills, embedded curriculum
2. Section 2: Exam Resources — official links, skills measured, videos, FAQ
3. Indigo left-border section headers that break out of content padding (visual anchors)
4. 48px separator between sections
5. Feature pills: 📖 ELI5 · 🔄 Flashcards · ✅ Knowledge checks · 📊 Compare tables · 💡 Exam tips · 📍 Progress tracking
Zen Polish:
1. Category badge: accent → grey (static metadata, not actionable)
2. All h2 icons removed (6 total — text labels are enough)
3. Status badges: emoji → text only (Retiring, Retired, Beta, Upcoming)
4. Status banners: icons removed
5. Cert Compass CTA → quiet inline link (was a loud button block)
6. Mobile floating bar: "Try Free" → "20 Free Questions", "Buy Now" → "Practice Exam $19"
7. Floating bar bg: rgba(3,3,8,0.95) → var(--bg-surface)
8. Card hover: translateY(-2px) + box-shadow glow → flat border-color only
9. Tab active glow removed
10. Sidebar icons removed (study planner, prep time)
11. Free/Premium labels removed from curriculum modules (unnecessary noise)
12. Domain heading: indigo colour + weight 600 (clickable = coloured)
13. Spacing increased everywhere: title→badges→hero→sections all breathing
Architecture Decisions (REUSE THESE)¶
| Decision | Rationale |
|---|---|
Dedicated /embed/ route > query param |
Astro is SSG — query params aren't available at build time. Separate route generates static embed pages. |
| Same-origin iframe via Cloudflare proxy | /guided/* is proxied through Pages Function. Iframe loads from same origin → no CORS issues, shared localStorage, shared cookies. |
hugo.IsDevelopment for dev URLs |
Dev mode points iframes to localhost:4322 Astro dev server. Production uses same-origin /guided/embed/. |
| postMessage for height sync | ResizeObserver on document.body + periodic fallback (10s) catches late-hydrating React components. |
Progress via localStorage guided_progress |
Same key used by both Guided app and Hugo parent. embed-progress postMessage triggers parent re-read. |
| Two sections > one long page | Interactive study guide is the USP — it earns top billing. Reference material (official links, skills) is valuable but secondary. Visual separator makes this hierarchy clear. |
| Feature pills > paragraphs | Students scan, they don't read. Pills communicate "what's inside" in 2 seconds. |
| Hover prefetch | <link rel="prefetch"> injected on mouseenter. Reduces perceived load time from ~2s to near-instant. |
| Continue button | #1 returning-learner improvement. Reads guided_progress from localStorage, finds first unfinished module, opens its domain + scrolls into view. |
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | SSG can't use query params — Astro's static mode pre-renders pages. ?embed=1 doesn't work because the page is the same HTML file regardless of query string. Dedicated route is the only option. |
Critical — avoided a broken deploy |
| 2 | Same-origin proxy is a superpower — the Cloudflare Pages Function that proxies /guided/* means iframes share localStorage with the parent. Progress, theme, license keys — all work seamlessly. |
High |
| 3 | Deploy Guided BEFORE Hugo — Hugo pages reference /guided/embed/* URLs. If Guided hasn't deployed yet, iframes 404 on first load. |
High — deployment order matters |
| 4 | ResizeObserver + periodic fallback — React island hydration happens after initial page load. A single height report misses it. ResizeObserver catches DOM changes; periodic checks catch edge cases. | Medium |
| 5 | Feature pills > feature paragraphs — students deciding whether to engage scan in 2 seconds. Six pills tell the story faster than a sentence. | Medium |
| 6 | "Continue" needs domain auto-open — the next unfinished module might be in a collapsed domain. The continue handler must open the parent <details> before scrolling. |
Medium |
Scope: 35 Microsoft Certs with Study Modules¶
All 35 certs automatically get the interactive embed. The template is shared — certs without study modules gracefully show only Section 2 (Exam Resources).
ab-100 ab-620 ab-730 ab-731 ab-900
ai-103 ai-300 ai-901
az-104 az-120 az-140 az-305 az-400 az-700 az-900
dp-300 dp-420 dp-600 dp-700 dp-750 dp-800 dp-900
mb-500 mb-800 md-102 ms-102 ms-700
pl-300 pl-400 pl-900
sc-100 sc-200 sc-300 sc-401 sc-900
Phase 13b: Video + Licensing + Blog + Cert Landing ✅ COMPLETE (28 Apr 2026)¶
Goal: Zenify the remaining 4 content page types after study guides.
Deployed: Commits d128768 (Hugo video+licensing), 5dd135e (Hugo blog), 2f206d1 (Guided cert landing), 5805d31 (Guided practice embed)
Video Single (video-single-content.html, 78 pages)¶
- Date removed from meta line (all 2022 — signals stale)
- Tags section removed (low value, rarely clicked)
- Related video dates removed
- Views/likes kept (substance — users judge quality)
Licensing Single (licensing/single.html, 50 pages)¶
- All icons removed: meta "Verified", TOC summary, quick link buttons, related h2, attribution
- Disclaimer → progressive disclosure behind
<details>(legally there, not in the way) - Disclaimer copy: reduced bold, cleaner language
- Attribution: coffee icon removed
Blog Single (blog/single.html, all posts) — Major Overhaul¶
Reading typography:
1. H2 section breaks: top border + 3.5em margin + 24px padding = chapter feel
2. First h2 skips border (clean open)
3. Section intro: h2 + p styled as lede (1.05em, --text-primary)
4. List markers: indigo bullets and numbers
5. List items: 0.25em left padding for breathing room
Tables:
6. Cell padding: 16px → 24px horizontal (no more squishing)
7. First column: --text-primary + weight 500 (label scanning)
8. Zebra striping: even rows --bg-elevated
9. Mobile (≤640px): tables → stacked cards (header hidden, each row becomes a card with indigo label)
Prompt cards:
10. "Prompt" label in uppercase indigo above the card
11. Accent-tinted background (--accent-subtle)
12. Copy button: top-right, async clipboard API with success/failure states
Code blocks: 13. Copy button: appears on hover, top-right corner
Heading anchors:
14. # link appears on h2/h3/h4 hover (for sharing specific sections)
TOC active highlight: 15. Left sidebar TOC highlights current section on scroll (indigo + bold)
Cleanup: 16. Fake reads counter removed (formula-based, not real analytics) 17. Ko-fi badge removed from header area 18. Warm toggle: emoji → text 19. Focus button: icon → text 20. Resources h2: icon removed 21. Related articles: 10 → 5
Cert Landing Page ([slug]/index.astro, Guided)¶
- Hero gradient removed (Zen bans gradients)
- LEVEL_INFO emojis removed (🟢🔵🟣⭐ → text only)
- All inline styles → CSS classes (study modules, exam table, CTAs, mobile nav)
- Empty companion
<span>tags removed - Disclaimer →
<details>progressive disclosure - Practice exam embedded directly (native PracticeQuiz component, not iframe)
- Fullscreen expand/shrink with ESC support
- Practice section positioned at top (primary action first)
Lessons Learned¶
| # | Lesson | Impact |
|---|---|---|
| 1 | Section-open rhythm is the #1 blog readability win — H2 top border + padding + lede paragraph creates "chapter" boundaries. More impactful than any single component improvement. | Critical |
| 2 | Mobile tables → stacked cards — The Stripe/Linear pattern. Header hidden, each row becomes a card. Eliminates all squishing. | High |
| 3 | Copy buttons need async clipboard — navigator.clipboard.writeText() is async. Must use .then/.catch, not try/catch. Every copy button needs success + failure states. |
High |
| 4 | TOC active highlight is high-leverage — One scroll listener makes 50KB posts navigable. Users always know where they are. | High |
| 5 | h2 + p selector is the simplest "lede paragraph" — no content changes, pure CSS. Every section opens with a stronger intro. |
Medium |
| 6 | Heading anchors need h[n][id] selector — Hugo auto-generates IDs on headings. The JS just appends an <a> with href="#id". |
Low |
| 7 | Native component > iframe for same-project embedding — PracticeQuiz on the Guided cert page renders directly as React, not in an iframe. Faster, shares state, no postMessage needed. | High |
| 8 | PracticeQuiz is 2,587 lines — redesigning it needs a dedicated session with the test guardrail. Quality over speed for paid products. | Process |
CSP Fix (critical infrastructure)¶
X-Frame-Options: DENY→SAMEORIGINinstaticwebapp.config.json- CSP
frame-src: added'self'for same-origin iframes - Fixed iframe embedding for study modules (was showing "blocked content")
Next Up: PracticeQuiz UX Redesign 🎯¶
Starter prompt: C:\ssClawy\aguidetocloud-revamp\files\practice-quiz-redesign-starter-prompt.md
Scope: Redesign the PracticeQuiz setup screen, active quiz navigation, results page, and mobile experience based on Whizlabs/MeasureUp competitor research + Zen principles.
Key files: PracticeQuiz.tsx (2,587 lines), test-guided-qa.cjs (14+ automated checks)
Rule: node test-guided-qa.cjs MUST pass before every deploy.
Phase 14: Tool Page Zenification 🔧 (Starting 29 Apr 2026)¶
"Zenification is not polishing. It's questioning everything."
Goal: Go tool by tool through all 53 tools and apply fundamental redesign — not just CSS token swaps, but challenging the entire structure, layout, tabs, and data presentation of each tool.
Starter prompt: C:\ssClawy\aguidetocloud-revamp\files\tool-zenification-starter-prompt.md (v2)
Progress Tracker¶
| # | Tool | Status | Commit | Key Changes |
|---|---|---|---|---|
| 1 | Copilot Feature Matrix | ✅ Done | 3ed0cab |
Radical redesign — single-app view, SVG icons, underline tabs |
| 2 | ROI Calculator | ✅ Done | c507d0d |
All 6 tabs kept, emojis→text, CSS tokens, density tightened |
| 3 | Licence Picker | ✅ Done | afde166 + 2 |
Persona killed, tabs swapped, features → name+checkbox, scenarios collapsed |
| 4 | CA Policy Builder | ✅ Done | 5702f26 |
Templates first, 60+ emojis→text, Add/Remove toggle, tier tokens |
| 5 | Prompt Library | ✅ Done | 4615a12 |
Role-first landing, 40→8 super-groups, killed search/filters/POTD/badges |
| 6 | AI Service Mapper | ✅ Done | 2e03ac6 |
Deep: 2-col cards, pricing default, cost estimator collapsed, quiz emojis, all tabs tight |
| 7 | Migration Planner | ✅ Done | ffa4cf1 |
121 emojis killed, underline tabs, density tightened, fixed missing div |
| 8 | AI SaaS Showdown | ✅ Done | 6a45837 |
Pricing first, emoji→letter badges, all tables 4px 8px, cards tight |
| 9 | Cert Compass | ✅ Done | 755b8ec |
Career Paths first, compact provider stats, cards tightened, emojis killed |
| 10 | Licensing Simplifier | ✅ Done | c0d0f2f |
Cards tight, features collapsed, calculator pre-populated, colored headers |
| 11 | Agent 365 Planner | ✅ Done | 31d2fb0 |
Underline tabs, emojis killed, density tightened, FAQ fixed |
| 12 | Purview Starter Kit | ✅ Done | 560981e |
Cards 10px, emojis killed, DLP/labels tightened, FAQ fixed |
| 13 | PowerShell Builder | ✅ Done | 3046b3f |
Build first, service picker, emojis→text only, module cards title-only |
| 14 | Copilot Model Map | ✅ Done | b311bd1c |
Killed gradient legend (→ solid dim line), font-weights 700→600, killed 💡⚡🟢🟡🔴👆 emojis (kept structure), GLOBAL: dark --text-muted #737373→#9CA3AF (4.17→7.1 contrast), audit-script overflow false-positive fix |
| 15 | Cert Tracker | ✅ Done | 5bdb9548 |
Emoji-purge surgical pass: kill 📖✅⚠️🧪🚫🔜 from JS-rendered stat boxes/status labels/notes/CTAs. Score 93→68. Kept category icons (functional). |
| 16 | Service Health | ✅ Done | 5bdb9548 |
Kill ✅🌍💬🕐🔴⚠️📈📉➡️ from JS, replace inline rgba styles with CSS classes. Score 90→67. Kept service product icons. |
| 17 | AI News | ✅ Done | 5bdb9548 |
Kill ⚠️🔴🏷️ JS-level emojis. Score 97→78. Kept provider emoji map (separate session for SVG migration). |
| 18 | M365 Roadmap | ✅ Done | 5bdb9548 |
Kill ⚠️✕ JS-level emojis. Score 70→69 (most of its score is from data emojis preserved as functional). |
| 15 | Prompt Polisher | ⬜ Queued | — | — |
| 16 | Prompt Guide | ⬜ Queued | — | — |
| 17 | Advanced Prompt Lab | ⬜ Queued | — | — |
| 18 | Prompt Tester | ⬜ Queued | — | — |
| 19 | Copilot Readiness | ⬜ Queued | — | — |
| 20 | Meeting Planner | ⬜ Queued | — | — |
| 21 | Cert Study Guides | ⬜ Queued | — | — |
| 22 | QR Generator | ⬜ Queued | — | — |
| 23 | WiFi QR | ⬜ Queued | — | — |
| 24 | Password Generator | ⬜ Queued | — | — |
| 25 | Image Compressor | ⬜ Queued | — | — |
| 26 | Typing Test | ⬜ Queued | — | — |
| 27 | Countdown Timer | ⬜ Queued | — | — |
| 28 | Colour Palette | ⬜ Queued | — | — |
| 29 | Security Toolkit | ⬜ Queued | — | — |
| 30 | Pomodoro Timer | ⬜ Queued | — | — |
| 31 | Admin Bingo | ✅ | aa90dbf9 |
10 May (night) — score 20→0 |
| 32 | Acronym Battle | ✅ | aa90dbf9 |
10 May (night) — score 87→0 |
| 33 | Excuse Roulette | ⬜ Queued | — | — |
| 34 | Rename Generator | ⬜ Queued | — | — |
| 35 | Admin Comms | ⬜ Queued | — | — |
| 36 | Compliance Checker | ⬜ Queued | — | — |
| 37 | Phishing Simulator | ⬜ Queued | — | — |
| 38 | SLA Calculator | ⬜ Queued | — | — |
| 39 | Admin Badges | ⬜ Queued | — | — |
| 40 | Policy Tester | ⬜ Queued | — | — |
| 41 | Incident Response | ⬜ Queued | — | — |
| 42 | CLI Quiz | ✅ | aa90dbf9 |
10 May (night) — score 18→2 |
| 43 | IT Day Planner | ⬜ Queued | — | — |
| 44 | Agent Builder Guide | ⬜ Queued | — | — |
| 45 | CS Companion | ⬜ Queued | — | — |
| 46 | Instruct Builder | ⬜ Queued | — | — |
| 47 | Demo Scripts | ⬜ Queued | — | — |
| 48 | Deprecation Timeline | ✅ | aa90dbf9 |
10 May (night) — score 19→8 (still polish, leakage floor) |
| 49 | M365 Roadmap | ⬜ Queued | — | — |
| 50 | Service Health | ⬜ Queued | — | — |
| 51 | AI News | ⬜ Queued | — | — |
| 52 | Site Analytics | ⬜ Queued | — | — |
| 53 | Community Feedback | ⬜ Queued | — | — |
Done: 31/53 · Next: per audit-output/triage.md (not the original sequence)
Phase 14 batch 9 (commits
687a70ad+14415147, 10 May 2026 night, 6 tools shipped 🟢 clean): Pomodoro 20→4, SLA Calc 17→0 (PERFECT), Image Compressor 16→1, Prompt Guide 14→1, Phishing Sim 13→2, Instruction Builder 9→4. Total 89→12 (-77 points). Reusablescripts/rgba-sweep.mjs(Node) wrote-and-removed for bulk rgba(R,G,B,A) → color-mix(token X%) sweep across known RGB triples (indigo→accent, red→error, green→success, yellow→warning, plus blue/orange variants). PowerShell regex sweep on CSS files for fw 700/800 → 600 (32 instances across batch). Per-tool surgical: Pomodoro 6 ambient pill buttonsstyle="--pill-color:#X"→data-ambientattribute consumed by CSS palette modifiers (theme-aware tokens). SLA Calc layout intro paragraphs + JS-rendered status text → utility classes +data-status="breach/warn/safe"semantic attribute. Image Compressor 17#818CF8(dark-mode-only accent literal) →var(--accent). Prompt Guide 4 gradients (incl hardcoded#84CC16hero +#1a2a1a/#050510cert card + 2 same-color fakes) → solid color-mix orvar(--accent-subtle). Phishing Sim radial-gradient withrgba(231,76,60,0.12)→ color-mix onvar(--error). Instruction Builder hover shadow + 7 status-color rgbas → color-mix.Note (10 May 2026, late evening): AI Cost Calculator (score 19→14→7 🟢) — re-zenified across two sessions: commit
aa90dbf9(inline-style → utility classes, purple literals → tokens) and commit697df5db(mobile table overflow fix at ≤480px: font 0.82→0.72rem, padding 4×8→3×5px,.aicost-summary-section { overflow-x: auto }safety net). The "Chart.js canvas wrapper false-positive" hypothesis from the prior session was wrong — the 7 mobile overflows were a real.aicost-tablebug in the JS-generated exec-summary tables (372px content on 390px viewport). Now 🟢 clean.Copilot Frontier Map (commit
697df5db, 10 May 2026 night, score 26→1 🟢): Was never in the original numbered tracker (oversight — added to the queued worklist viaaudit-output/triage.md). 8 fw 700/800 → 600 (zen weight ceiling). 1.cfm-pipe-previewshadowrgba(0,0,0,0.25)→color-mix(in srgb, black 12%, transparent)(resolved 16 of 21 runtime rgba box-shadows; the other 5 are global chrome — feedback-fab, search-modal, btt, bb-palette-modal, anchor — which the audit's>5threshold absorbs). Remaining 1 point = palette=43 from inline-style spans in shared partials (zt-companion-link-tag+ Ko-fi link), out of scope.Site Analytics (commits
0fd232ed+50c9c808, 10 May 2026 night, score 102→23 🟡, -79 points biggest single Phase-14 drop): Two-pass surgery. Pass 1: static/css/site-analytics.css gradient sweep (11 linear-gradient → solid color-mix or var(--accent-subtle) for same-color-stop fakes), 2 rgba shadows → color-mix on black, 32 fw 700/800 → 600, 4 hardcoded rgba color fills → color-mix on tokens, hardcoded green progress bar →var(--success). static/js/site-analytics.js inline-style cleanup (today/yesterday/YT bar utility classes, link-soft/-muted classes, country reach table →.siteana-co-*class set, heatmap cellsstyle="background:rgba(...)"→--hm-alphacustom property consumed by CSS rule). Pass 2 — DISCOVERY:layouts/site-analytics/list.htmlhas 1400 lines of inline JS that DUPLICATES rendering logic from static/js/site-analytics.js. The audit was seeing the layout's output, not static JS. Fixed at the source: heatmap legendis-l1/2/3/4, content-numis-blue/green/etcpalette modifiers, big info-card linear-gradients →.siteana-deep-ctavariants, FAQ details inline → class, hardcoded heatmap render →--hm-alphapattern, certs reach table inline rebuild →.siteana-co-*classes, event/page lists →.siteana-list-stackpatterns. Audit script:serviceWorkers: 'block'on browser context (SW was caching old JS even after Cloudflare deploy). Floor 23 = 36 legitimate content inline-styles (info.color leaderboard rows, b.color category bars, per-tag dot colors, freshness dots — all Lesson 48 data-driven) + 70 palette from same content + 4/30 dark contrast fails. Polish-tier won't go 🟢 without rewriting data-color contracts.Audit script refinements (commits
697df5db+50c9c808): Three defensive improvements: (1) CSS scan strips@media printblocks before pattern matching — print stylesheets legitimately use font-weight 700 and hardcoded hex (#000,#ccc) for paper legibility, no theming on paper, shouldn't penalise the screen-zen score (lesson 44 generalisation). (2) Mobile overflow check exempts<canvas>ancestors — Chart.js / similar resize asynchronously and may briefly report >viewport widths before settling. Defensive only; was NOT the actual cause of AI Cost's 7 overflows (that was a real table bug, now fixed). (3)serviceWorkers: 'block'on browser context — Cloudflare-deployed JS was being intercepted by the active service worker scopehttps://www.aguidetocloud.com/, causing audits to show stale results post-deploy. Investigation script (debug-jsload.mjs probingpage.on('response')) confirmed no JS network request was firing because SW was serving cached version. Block flag forces fresh-network for accurate post-deploy verification.Audit-first reset (10 May 2026, evening session): A Playwright triage sweep replaced the 14→53 sequence with a worst-first worklist. See
scripts/zen-tool-audit.mjs+audit-output/triage.md. Initial scores: 22 broken, 21 polish, 1 clean (QR Generator). Top 5 priorities by score: Copilot Model Map (199, 180 mobile overflows) · Colour Palette (149) · Site Analytics (123) · M365 Service Health (101) · Cert Tracker (98). Universal "1 backdrop-filter" was the brain-bar palette overlay → fixed globally in commit22f29382.
Tool 1: Copilot Feature Matrix ✅ COMPLETE (29 Apr 2026, commit 3ed0cab)¶
What changed: - Compare Tiers: Consumer/Enterprise split with compact tier headers, tier overview cards at top (open by default), text status badges - By App: Emojis → monochrome SVG icons via Hugo partial bridge pattern, per-app colours removed - All Features: RADICAL REDESIGN — 60-column spreadsheet → single-app-at-a-time view (default Teams) - What Changed: Emojis removed, old alias vars fixed - FAQ: Inline styles removed, copy we→I - Cross-links: Glassmorphism killed → Zen cards - CSS: ~60 token fixes, underline tabs, dead code removed
What was tried and rejected: - Unified 4-column table (all tiers in one view) — too many "—" dashes, lost audience segmentation, worse than the split
Tool 2: ROI Calculator ✅ COMPLETE (29 Apr 2026, commit c507d0d)¶
See session journal for details.
Tool 3: Licence Picker ✅ COMPLETE (29 Apr 2026, 3 commits)¶
See session journal for details.
Tool 4: CA Policy Builder ✅ COMPLETE (29 Apr 2026, commit 5702f26)¶
What changed:
- Tab reorder: Templates first (instant value), Build second
- Floating sections relocated: "How many policies?" → Templates tab; "CA Quick Reference" → Build tab
- Content CTA killed: blog/YouTube promo removed
- Quickstart redesign: gradient removed → flat Zen surface, compact scenario row
- Template cards: risk text collapsed into details (shorter cards); Add/Remove toggle (no dead-end disabled state); Remove All per tier
- 60+ emojis → text: scenarios, tier headers, wizard steps (1–7), detail row labels, toasts, linter, export headings
- FAQ: hardcoded purple removed, collapsed by default (first item open)
- CSS full cleanup: all rgba→color-mix, gradient→flat, 16px→tokens, Zen font scale, weights≤600, 150ms transitions, underline tabs, tier-specific tokens (--cab-tier-sp/ent/spec), SVG score ring via CSS classes
- Density tightened: cards 10px, gaps 6px, grids 280px min, wizard steps compact
Cumulative Learnings 16–42 (from tool zenification)¶
| # | Principle | First Discovered |
|---|---|---|
| 16 | Zenification ≠ polishing — challenge entire structure before styling | Feature Matrix |
| 17 | Read the tool's learning docs first — understand WHY before changing | Feature Matrix |
| 18 | Audience segmentation earns its place — Consumer/Enterprise split helps | Feature Matrix |
| 19 | Tier/plan cards → column headers — context moves inline, not above | Feature Matrix |
| 20 | Card order must match table order — misalignment confuses | Feature Matrix |
| 21 | Detail cards above, not below — bottom = nobody finds them | Feature Matrix |
| 22 | Status emojis → text badges — Full/Partial/— more accessible | Feature Matrix |
| 23 | Remove per-tool/per-tier colours — one accent only | Feature Matrix |
| 24 | Unified table can backfire — more columns ≠ more useful | Feature Matrix |
| 25 | Use Playwright to verify — screenshot after every structural change | Feature Matrix |
| 26 | Emojis → SVG icons everywhere — including JS-rendered content | Feature Matrix |
| 27 | Hugo partial → JS icon bridge — jsonify | safeJS, window.__cpIcons lookup |
Feature Matrix |
| 28 | Show one thing at a time — default to one dimension, let user switch | Feature Matrix |
| 29 | Zenify = structural redesign, CSS is LAST — screenshot the gold standard (Feature Matrix) side-by-side with the tool. For every visible element ask "remove it — did the user lose value?" Write the proposed CUTS first, get approval, THEN implement. CSS token cleanup is the final step, not the first. | ROI + Licence Picker |
| 30 | Pre-flight gate (MANDATORY) — Before touching any code: (1) Screenshot tool + Feature Matrix side-by-side, (2) List every element and verdict (remove/shrink/keep), (3) Propose structural cuts and get approval, (4) Implement structure, (5) CSS tokens last. Skipping steps 2-3 is how "polish" happens instead of "zenify". | Licence Picker |
| 31 | Tighten tables globally — comparison/data tables default to padding: 4px 8px, font-size: var(--text-caption). Goal: 2× more rows visible per viewport than the first instinct. |
Licence Picker |
| 32 | Mobile = full width for all tools — .zt-page mobile padding is 12px (not 32px). Fix globally, not per-tool. |
All tools |
| 33 | Tighten EVERYTHING by default — cards: padding: 8-10px. Gaps: 6px. Buttons: 5px 14px. Grid mins: 130-140px. Headings: --text-sm not 1rem. If the first instinct is 12px padding, use 8px. Density = more value per viewport. |
Licence Picker |
| 34 | Default tab = instant value — the tab that gives value with zero interaction goes first. Comparison tables beat interactive pickers as landing tab because users see everything immediately. | Licence Picker |
| 35 | Mobile: results/sidebar below content — on mobile, put results/recommendation panels BELOW the interactive area (order: 1), not above (order: -1). Users need to interact first, see results second. |
Licence Picker |
| 36 | Kill duplicate text — if title says "Cheapest way to get Copilot" and question says "What's the cheapest way to get Copilot?", kill the question. One expression per idea. | Licence Picker |
| 37 | Collapse long answers — scenario answers, bonus features, "why not" explanations → behind <details>. Show the actionable line (cost + recommendation), hide the essay. |
Licence Picker |
| 38 | Add/Remove toggle on cards — never leave the user with a disabled "Added" button and no way back. When an item is added, flip the button to "Remove" so they can undo without switching tabs. Same for "Add All" → "Remove All" on section headers. | CA Policy Builder |
| 39 | Move floating helpers INTO their tab — reference content that floats outside all tabs gets ignored. "How many policies?" belongs in the Templates tab (context). "Quick Reference" belongs in the Build tab (where users need it). | CA Policy Builder |
| 40 | Tier-specific CSS tokens — don't use --success/--warning/--error for non-state semantics like trust tiers. Create component-level aliases (--cab-tier-sp, --cab-tier-ent, --cab-tier-spec) that map to Zen palette tokens. Reads better, avoids "enterprise = warning" confusion. |
CA Policy Builder |
| 41 | Scenario data shape matters — if JS parses label.split(' ')[0] to extract an emoji icon, removing the emoji breaks the parser. Restructure the data object (title field instead of parsing from label) before removing emojis. |
CA Policy Builder |
| 42 | Two-pass zenification works — Pass 1: structural cuts + emoji removal + core CSS tokens. Pass 2: grep for remaining legacy patterns (rgba, 16px, 0.Xrem, font-weight: 700, var(--cab-accent)) and batch-fix everything missed. Second pass caught ~40 remaining issues. |
CA Policy Builder |
| 43 | Run an automated audit before zenifying anything — when resuming a paused tracker, build a Playwright-based static + runtime audit of every queued tool first. The original 14→53 sequence was arbitrary; the audit revealed 22 actual broken tools, 21 polish, 1 already clean. Worst-first attack > tracker-order attack. | Phase 14 resume (Copilot Model Map) |
| 44 | Audit script must respect intentional design — naive "is this element wider than viewport" flags every horizontally-scrollable matrix table or filter pill row as broken. Always check if the parent has overflow-x: auto/scroll before counting overflow. The "180 mobile overflows" on Copilot Model Map was 100% false positive from the matrix table's correct horizontal-scroll pattern. |
Audit fix |
| 45 | Global token contrast bugs hide in plain sight — dark mode --text-muted: #737373 was below WCAG AA contrast (4.17:1) on the darkest backgrounds across ~50 pages. Discovered only when the audit sampled 30 random text-bg pairs and flagged 12 as low-contrast. Fix var(--*) token definitions, not per-tool overrides. |
Copilot Model Map dark-mode fix |
| 46 | Mobile-strip helpers go global — Lessons #32, #33, #35 (mobile padding 12px, density tightening, results-below-content) belong in style.css as .zt-mobile-hide / .zt-mobile-only / .zt-mobile-stack / .zt-mobile-sidebar-below opt-in classes, not re-implemented per tool. New tools just add the class. |
Phase B globals |
| 47 | Hidden DOM elements still get audited — the brain-bar palette modal (hidden by default with [hidden] and rendered via baseof.html) was contributing backdrop-filter to every page's audit. The audit doesn't know "hidden". Fix the source, not the audit. Solid darker bg (rgba 0.85) replaces blur; modal still reads as a focused overlay. |
Phase A brain-bar fix |
| 48 | Distinguish content emojis from chrome emojis — data tools (cert tracker, roadmap, service health, AI news) load JSON from runtime endpoints with emoji status/category markers baked in. These are CONTENT, not chrome — Microsoft Learn does the same with their service icons. Killing them invasively rewrites data generators. Scope kills to JS-rendered decorative noise (error-msg ⚠️, stat-box prefixes, CTAs) and leave functional product/category emojis alone. Note in commit message what's kept and why. | Tools 15-18 emoji-purge |
| 49 | Verify the false-positive theory before refactoring tooling — when an audit/linter flags something as a probable false-positive, prove it via direct inspection (a 30-line Playwright evaluate() listing flagged elements with their tag/class/parent metadata) BEFORE adding an exemption. AI Cost Calculator's "7 mobile overflows from Chart.js canvas wrappers" turned out to be a real .aicost-table bug — adding a Chart.js exemption would have masked a genuine mobile UX regression. Defensive exemptions can still be valuable (canvas exemption was added anyway as future-proofing) but must be justified for the right reason, not as a workaround for unverified hypotheses. Cost of inspection: 90 seconds. Cost of misdiagnosis: a real bug shipped + a permanent audit blind spot. |
Phase 14 batch 7 AI Cost residual |
| 50 | Service workers cache aggressively — block them in audits — Cloudflare deployed site-analytics.js was being intercepted by the active service worker (scope https://www.aguidetocloud.com/), which served stale cached JS to Playwright even though cache_version HTML had been bumped and CSS reloaded fresh. Audit was reading old DOM rendered by old JS, showing zero score improvement after a real deploy. Diagnosis: a page.on('response') listener showed NO network request fired for site-analytics.js (only the CSS hit network). Fix: browserContext({ serviceWorkers: 'block' }) forces fresh-network for every navigation. Real users still see SW-cached old JS until next visit, but that's a different problem (SW invalidation strategy). For audits, you want ground truth, not cached truth. |
Phase 14 batch 8 Site Analytics |
| 51 | Inline JS in Hugo layouts duplicates static JS files (often invisibly) — layouts/site-analytics/list.html has 1400 lines of inline <script> rendering the dashboard. static/js/site-analytics.js ALSO exists with similar rendering functions. Both load on the page. The audit's runtime DOM inspection sees whichever wins the render race — usually the layout (because inline scripts execute on parse, before the external script's defer/load). Editing only the static JS file = changes don't ship to the visible UI. Always grep BOTH the static JS AND the layout for the rendering function name before zenifying. Pattern: grep -rn "function renderHeatmap" layouts/ static/. If hits in both, the layout wins — fix the layout first. |
Phase 14 batch 8 Site Analytics layout discovery |
| 52 | Bulk RGBA→color-mix sweeps need a reusable Node script (PowerShell delegate-replace hangs) — when many CSS files share the same hardcoded RGB triples (e.g., #818CF8 indigo, #EF4444 red, #22C55E green) the ergonomic move is a Node.js regex tool that maps known RGB→token and converts alpha→percentage. PowerShell [regex]::Replace($input, $pattern, [scriptblock]) hangs in some shell configurations (PSv5 issue). Node ESM string.replace(regex, fn) works reliably. Pattern: scripts/rgba-sweep.mjs accepts a CSS file path, sweeps a Map of RGB-triple → token-name, converts alpha→Math.round(parseFloat(a)*100)%, writes back. Used + removed in batch 9 (one-shot tool). Recreate when needed. |
Phase 14 batch 9 6-tool sweep |
| 53 | data-status / data-ambient attributes are theme-aware semantic alternatives to inline style="color:#X" — when JS produces dynamic styling that needs to map to brand/state colours (success/warning/error/breach/safe), prefer data-status="breach" HTML attribute consumed by [data-status="breach"] { color: var(--error); } CSS rule. Two wins: (1) audit doesn't flag (no style= attribute with colour keyword), (2) theme-aware (token resolves per light/dark). Same pattern works for content categories: data-ambient="s-focus" → CSS rule with --pill-color: var(--error). Lifts arbitrarily many tool inline styles to zero with one CSS block. |
Phase 14 batch 9 SLA Calc + Pomodoro |