Skip to content

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

  1. Add all Zen CSS custom properties to :root and [data-theme="dark"] in style.css (TOP of file)
  2. Add theme toggle button to nav.html (sun/moon icon)
  3. Add theme toggle JS: reads localStorage → sets data-theme → saves preference
  4. No visual changes yet — just the infrastructure. All existing pages stay dark-only.
  5. 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 :root tokens at TOP (above all existing rules)
  • layouts/partials/nav.html — add theme toggle button
  • static/js/switcher.js — add theme toggle logic
  • hugo.toml — bump cache_version

Definition of Done

  • [ ] All Zen tokens exist in :root and [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

  1. Replace ALL hardcoded colours in homepage CSS with var() tokens
  2. Remove glassmorphism, neon, gradient, glow from homepage rules
  3. Simplify homepage structure — less "card mania", more breathing room
  4. Remove decorative elements (watermark numbers, shimmer animations, cursor glow)
  5. Homepage renders correctly in both light and dark mode
  6. 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-filter in homepage CSS
  • [ ] All other pages still work in dark mode (no regressions)

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

  1. nav.html — refactor to Zen tokens, clean minimal style
  2. footer.html — refactor to Zen tokens
  3. Both work in light and dark modes
  4. Navigation active states use --accent (indigo)
  5. 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)

  1. Created static/css/zt-tools.css — universal tool page styles (underline tabs via ARIA selectors, 1200px width)
  2. Created layouts/partials/tool-header.html — compact title + counter + subtitle (replaces gradient hero bar)
  3. Created layouts/partials/tool-faq.html — reusable collapsed FAQ partial (available but not used — FAQ kept as tab)
  4. Migrated all 53 tools via batch Python script + manual fixes
  5. Removed tool-ecosystem.html calls from all tools
  6. Removed back-nav from all tools, replaced with "← All Tools" link
  7. tool_colours.toml NOT deleted yet — still used by OG image generator. Per-tool accents no longer affect page styling.
  8. Per-tool CSS files NOT deleted — internal tool styling preserved for Z4b polish pass.
  9. free-tools/list.html directory 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)

  1. Pass 1 — Batch migration of 53 CSS files: removed 177 backdrop-filters, 39 --tool-accent declarations, updated 49 template FAQs, fixed 3 JS files. Added zen-migrated class to all 54 tool body classes.
  2. 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.
  3. Pass 3 — Fixed 12 CSS files with per-tool variable systems (--cp-*, --lp-*, --dt-*, etc.) that had dark defaults.
  4. Pass 4 — Found 11 MORE per-tool variable systems + old glassmorphism variable refs (--bg-card, --glass-border). 249 changes across ~30 files.
  5. Pass 5 — Fixed 4 remaining FAIL tools: instruct-builder (86 changes), licence-picker (198 changes — eliminated :root alias vars), prompt-guide (scoped override removed), qr-generator (24 changes — #EC4899→var(--accent)).
  6. Structural fixes — Licence Picker template restructured (header was inside tablist), AI News breaking card restyled from red glassmorphism to Zen card style.
  7. Automated QA result: ✅ 45 GOOD | ⚠️ 7 WARN (acceptable) | ❌ 0 FAIL | 💥 1 ERROR (feedback timeout)

What Was Done (Phase 4c — 27 Apr 2026, LOCAL)

  1. Pass 6: Replaced 68 per-tool accent colours (demo-scripts #F97316 → var(--accent))
  2. Pass 7: Eliminated 602 :root alias variable usages across 17 CSS files (Trap 3 — the #1 cause of invisible text)
  3. Fixed --text-tertiary dark mode gap in body.zen-migrated — was missing, causing 100+ dark mode failures
  4. Migrated command-centre.css (cc) from scratch — was completely missed in Z4b
  5. Fixed global floating elements.global-btt, .feedback-fab, .bookmark-cta-inner now use Zen tokens on zen-migrated pages
  6. Fixed <select> dropdown styling globally for zen-migrated pages
  7. Cleaned glass pill tab code in 10 CSS files (dead code from old tab style)
  8. Fixed button text colour inheritance in 9 CSS files (buttons not inheriting color in dark mode)
  9. Fixed feedback/list.html — replaced tool-hero.html with tool-header.html, added zt-page wrapper
  10. Fixed .tool-eco-feedback shared component — was still using rgba(255,255,255,...)
  11. Fixed licensing.css — 9 instances of #f1f5f9 (Tailwind slate-100 → var(--text-primary))
  12. Fixed ainews.css — non-Zen magenta/gold tier badge colours → neutral Zen tokens
  13. Fixed instruct-builder.css — removed last backdrop-filter: blur(12px)
  14. Fixed site-analytics.css — white text label → var(--text-muted)
  15. Deep WCAG contrast audit — Playwright script checks every visible text element's contrast ratio against effective background. Findings documented in guardrails.md.
  16. 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)

  1. 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.
  2. Badge text token system — Added --badge-red/orange/amber/green/blue/purple to body.zen-migrated in 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.
  3. 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).
  4. feedback.js timeout — Added AbortController with 15s timeout on submit, 10s on discussions fetch.
  5. QA: 53/53 GOOD — Playwright light+dark mode screenshots for all tools. Zero warnings, zero failures.
  6. 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-page class 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-migrated opt-in class — pages with this class opt OUT of force-dark and get full light/dark mode. Control point: baseof.html line ~78.
  • Eliminated :root alias variables — CSS custom properties inherit computed values, making :root aliases unreliable when multiple :root blocks exist.
  • --text-muted darkened to #6B6B6B — WCAG ~4.7:1 contrast ratio (was 2.31:1 at #A3A3A3).
  • --text-tertiary must 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-migrated on 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] :root alias 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.toml deleted 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:

  1. Created layouts/blog/single.html — 3-column reading layout
  2. Created static/css/zt-reading.css — full reading room styles (882 lines)
  3. Created static/js/zt-toc.js — IntersectionObserver TOC highlighting + progress bar
  4. Right companion sidebar: video widget, 5 related articles, subscribe CTAs
  5. Mobile: sidebars collapse, <details> TOC below title
  6. Migrated blog/list.html to Zen (tool-header + card list)
  7. Fixed global token gap (--text-primary/secondary/muted on body:not(.is-home))
  8. Configured Hugo TOC depth (h2–h4)

Key Decisions:

  • Content fills all space — no max-width cap on content. 1fr grid 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 from style.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.css infrastructure
  • 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:

  1. Created tool-nav.html — left sidebar with all 53 tools grouped by 9 categories
  2. Created tool-companion.html — right sidebar with popular tools, blog posts, CTAs
  3. baseof.html detects tools via toolkit_nav.toml — wraps in CSS grid (zero template changes)
  4. .zt-reading--tool CSS grid: 250px | 1fr | 280px with mobile collapse at 1024px
  5. Fixed Prompt Library extra </div> breaking grid (companion was invisible)
  6. Forced all inner containers full-width (max-width: none on -container, -page, -wrap)

Phase 5d: 1036 CSS Readability Fixes (COMPLETE — 27 Apr 2026, commit c839ecb)

What Was Done:

  1. Batch script (z5-batch-fix.cjs) fixed 1036 issues across 55 CSS files
  2. Removed: glow shadows, glow text-shadows, glass pill radii, glow CSS vars
  3. Fixed: near-white hex text → tokens, tiny font sizes → token scale, backdrop-filter → none
  4. Fixed: Ko-fi button contrast (white on red-transparent → badge-red token)
  5. Playwright QA: top 5 worst tools readable in both light + dark mode
  6. 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

  1. 404 page: minimal Zen treatment
  2. AI Hub: Zen cards for video grid
  3. Cert Tracker: Zen treatment
  4. Search overlay: Zen colours + tokens
  5. Remove ALL dead CSS (old tool classes, old homepage classes, old neon vars)
  6. Remove cursor glow, shimmer animations, gradient definitions
  7. 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-filter in 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

  1. Port Zen CSS custom properties to Guided's Astro/Tailwind config
  2. Same Inter font, same type scale, same spacing
  3. Same accent colour (indigo replacing current green)
  4. Nav alignment between Hugo and Guided sites
  5. 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

  1. Created /videos/ unified landing page (78 videos, 6 categories, search, category pills)
  2. 6 video section templates (ai-hub, cloud-labs, certifications, exam-qa, interview-prep, music) — each with list + single page
  3. DRY consolidation: 12 identical templates → 2 shared partials (video-single-content.html + video-category-list.html)
  4. video-categories.html as single source of truth for category metadata (used by nav, landing, and all templates)
  5. video-nav.html left sidebar: 6 collapsible categories with individual video links
  6. video-companion.html right sidebar: practice exams, free tools, recent blog posts, CTAs
  7. VideoObject JSON-LD on all single pages, CollectionPage JSON-LD on landing
  8. Zen-migrated body class for all 7 video sections in baseof.html
  9. Video-specific CSS classes (zt-vid-*) — proper token usage, no inline styles
  10. Upgraded thumbnails from mqdefault (320×180) to hqdefault (480×360)
  11. Search uses hidden attribute instead of brittle style checks
  12. 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 partialvideo-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 spotmqdefault (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 deliberatelyfirst 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

  1. Wrapped /free-tools/ in zt-reading grid (left sidebar | center content | right companion)
  2. Created tools-nav.html: collapsible <details> categories pulled from toolkit_nav.toml with individual tool links inside each
  3. Created tools-companion.html: practice exams, study guides, recent blog posts, CTAs
  4. Removed /free-tools/ from baseof.html $isToolPage detection (page now owns its own grid)
  5. CSS: zt-reading--tools overrides for wider card content area
  6. 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 TOMLtoolkit_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-aboutpage-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 existtool-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

  1. Built Playwright contrast audit (scripts/dark-mode-audit.cjs) — visits 30 representative pages in both light + dark mode
  2. For each text element: computes foreground color, walks up DOM compositing rgba backgrounds, calculates WCAG contrast ratio
  3. Flags issues below AA threshold (4.5:1 normal text, 3:1 large text)
  4. Initial run found 126 "critical" issues — 87 were false positives (print styles + alpha blending bug)
  5. 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:#fffvar(--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/advancedvar(--badge-green/blue/amber) Badges used same color for text and bg tint
copilot-matrix.css Consumer/Enterprise badges #C4B5FD/#93C5FDvar(--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-colorvar(--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 mattersrgba(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 refscolor:${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

  1. 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)
  2. 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
  3. Sidebar parity — removed unwanted cross-links, added indigo connector lines, synced tree-view CSS, removed grey sidebar background
  4. Dark mode default — Hugo now defaults dark on first visit (Guided already did)
  5. Guardrail #12 added: "One Body Two Organs" — any shared element change must update BOTH platforms in same session

Scope: Migrate footer to Zen tokens, unify across Hugo and Guided, add sidebar title parity.

What Got Done

  1. Hugo footer — Ko-fi rgba → official Ko-fi branded button (CDN), removed opacity hacks, all spacing → Zen tokens
  2. Guided footer — full rebuild matching Hugo (same 6 links, same icons, same structure)
  3. Sidebar title parity.zt-lic-nav-header (Videos, Licensing, Free Tools) now matches .zt-cert-nav-header with border-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 by readiness.css.
  • backdrop-filter (~38 lines) — mix of blur() on legacy pages and none overrides 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 targetreadiness.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)

  1. Screenshot — Playwright captures of current state (both modes, desktop + mobile)
  2. Audit — list every element in the content canvas, classify: essential / nice-to-have / dead weight
  3. Rubber-duck — critique the simplification plan before touching code
  4. Implement — remove dead weight, simplify layouts, improve hierarchy
  5. QA — Playwright both modes + mobile, verify nothing broke
  6. 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

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-elevated background + 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.

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 styles
  • hugo.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)

  1. Hero pattern is solved — compact header: h1 + count + 1-line desc. No stat pills, no icons, no marketing language.
  2. 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).
  3. CSS cascade matters — mobile media queries MUST come AFTER base styles. Never define mobile overrides before the base class exists.
  4. Icons are usually decoration — if the text label is clear, the icon adds no information. Remove it.
  5. Hover effects should be flatborder-color change, not box-shadow lift. Zen stays grounded.
  6. "Whisper, don't shout"font-weight: 500 max, hierarchy via colour contrast not size/weight.
  7. "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 icons
  • layouts/partials/video-category-list.html — shared template: same treatment
  • layouts/blog/list.html — tag-wrap span for mobile hide
  • static/css/zt-reading.css — 4-col grid, no shadow, blog mobile layout fix
  • hugo.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:

  1. App Launcher (icon + name only) — maximum density
  2. Mini Cards (icon + name + tagline) — balanced ⭐
  3. 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 flatborder-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

  1. Pick one representative page per section (the most-viewed or most complex)
  2. Audit the middle canvas — same Zen lens as Phase 12
  3. Rubber-duck the simplification plan
  4. Implement on the single page
  5. Batch-apply the pattern to all siblings (shared templates make this efficient)
  6. 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)

  1. Date removed from meta line (all 2022 — signals stale)
  2. Tags section removed (low value, rarely clicked)
  3. Related video dates removed
  4. Views/likes kept (substance — users judge quality)

Licensing Single (licensing/single.html, 50 pages)

  1. All icons removed: meta "Verified", TOC summary, quick link buttons, related h2, attribution
  2. Disclaimer → progressive disclosure behind <details> (legally there, not in the way)
  3. Disclaimer copy: reduced bold, cleaner language
  4. 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)

  1. Hero gradient removed (Zen bans gradients)
  2. LEVEL_INFO emojis removed (🟢🔵🟣⭐ → text only)
  3. All inline styles → CSS classes (study modules, exam table, CTAs, mobile nav)
  4. Empty companion <span> tags removed
  5. Disclaimer → <details> progressive disclosure
  6. Practice exam embedded directly (native PracticeQuiz component, not iframe)
  7. Fullscreen expand/shrink with ESC support
  8. 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 clipboardnavigator.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: DENYSAMEORIGIN in staticwebapp.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). Reusable scripts/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 buttons style="--pill-color:#X"data-ambient attribute 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 #84CC16 hero + #1a2a1a/#050510 cert card + 2 same-color fakes) → solid color-mix or var(--accent-subtle). Phishing Sim radial-gradient with rgba(231,76,60,0.12) → color-mix on var(--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 commit 697df5db (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-table bug 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 via audit-output/triage.md). 8 fw 700/800 → 600 (zen weight ceiling). 1 .cfm-pipe-preview shadow rgba(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 >5 threshold 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 cells style="background:rgba(...)"--hm-alpha custom property consumed by CSS rule). Pass 2 — DISCOVERY: layouts/site-analytics/list.html has 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 legend is-l1/2/3/4, content-num is-blue/green/etc palette modifiers, big info-card linear-gradients → .siteana-deep-cta variants, FAQ details inline → class, hardcoded heatmap render → --hm-alpha pattern, certs reach table inline rebuild → .siteana-co-* classes, event/page lists → .siteana-list-stack patterns. 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 print blocks 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 scope https://www.aguidetocloud.com/, causing audits to show stale results post-deploy. Investigation script (debug-jsload.mjs probing page.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 commit 22f29382.


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 bridgejsonify | 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