Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2a3d6e7
test(css): P0.1 — snapdiff coverage for special-content blog surfaces…
Jul 12, 2026
f60f696
test(css): P0.4 — orphan guard + delete 26 unreferenced CSS files it …
Jul 12, 2026
c2fc47a
test(css): R1 pre-coverage — course-landing (desktop+mobile) and mobi…
Jul 12, 2026
60ec710
refactor(css): R1 — retire 3059-layout.css; privacy-policy + course-l…
Jul 12, 2026
276b5c7
refactor(css): R2 — retire 706-layout.css; contact-us rewritten to se…
Jul 12, 2026
f7fccc2
refactor(css): R3a — blog-single off FL files at pixel parity; .sr-on…
Jul 12, 2026
28f7829
refactor(css): R3b — course-single off FL files at pixel parity (+ ch…
Jul 12, 2026
a6610c8
refactor(css): R3c — retire fb2624…-layout-bundle; single-client sema…
Jul 12, 2026
7ffbed6
refactor(css): R3d — retire 3114-layout.css + e966db44… bundle; singl…
Jul 12, 2026
1fa7828
test: mask bimodal lesson-meta blockquote in course chapter screenshots
Jul 17, 2026
32999c9
refactor(css): R4a — blog-list off homepage-layout/services-layout at…
Jul 17, 2026
16fb98b
refactor(css): R4b — free-consultation semantic rewrite; retire homep…
Jul 17, 2026
ba971c3
refactor(css): R5 — retire 701-layout.css; about-us delta port at pix…
Jul 17, 2026
69a5b7a
test: pre-coverage — careers newsletter section screenshot (both OSes)
Jul 17, 2026
5f56ed9
refactor(css): R6 — retire 3086-layout2.css; careers verbatim move at…
Jul 17, 2026
f153fd1
test: pre-coverage — mobile use-cases landing + single screenshots (b…
Jul 17, 2026
0f00c0f
refactor(css): R7 — retire 3021-layout.css + 3027-layout.css; use-cas…
Jul 17, 2026
5835758
test: pre-coverage — mobile services landing + fractional-cto screens…
Jul 17, 2026
6984af5
refactor(css): R8a — retire 3082-layout.css; clients delta port at pi…
Jul 17, 2026
e5fb603
refactor(css): R8b — retire 2949-layout.css; single-service delta por…
Jul 17, 2026
6e15816
refactor(css): R8c — retire 737-layout.css AND bf72bba…-layout-bundle…
Jul 17, 2026
0ea39ff
refactor(css): R9 — retire 590-layout.css; homepage delta port at pix…
Jul 17, 2026
1cbb780
docs(css): burn-down complete — ownership map final gz table + tracke…
Jul 17, 2026
6a4d251
test(visual): capture rendered mermaid diagram in screenshots
Jul 18, 2026
50b95ec
test(visual): per-language code-block screenshots via draft fixture post
Jul 18, 2026
031cc04
fix(css): modern clip-path for .sr-only alongside deprecated clip fal…
Jul 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions content/blog/codeblock-styles-fixture/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: Code Block Styles Fixture
description: Test-only fixture post exercising every fenced-code rendering path (recognized lexers, bare fences, indented blocks) for the visual regression suite.
draft: true
date: 2020-01-01
tags: []
slug: codeblock-styles-fixture
---
Test-only fixture. Each section below exercises one code-block rendering
path so the visual suite can lock their styles. Kept `draft: true` so it
never ships to production; test builds run with `--buildDrafts`.

## text

```text
GET /health HTTP/1.1
Host: example.com
status: ok
```

## md

```md
# Heading

Some *emphasis* and a [link](https://example.com).

- item one
- item two
```

## ruby

```ruby
class Greeter
def initialize(name)
@name = name
end

def hello
"Hello, #{@name}!"
end
end
```

## python

```python
def fib(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
```

## js

```js
const debounce = (fn, ms) => {
let t;
return (...args) => {
clearTimeout(t);
t = setTimeout(() => fn(...args), ms);
};
};
```

## html

```html
<article class="card">
<h2>Title</h2>
<p>Body copy with a <a href="/blog/">link</a>.</p>
</article>
```

## bare (no language)

```
rake db:migrate
rake db:seed
```

## indented (4-space block)

$ bin/hugo-build
$ bin/rake test:critical
72 changes: 53 additions & 19 deletions docs/projects/2509-css-migration/TASK-TRACKER.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

**Purpose**: Status tracking for the CSS maintainability goal — FL-Builder export CSS retired page-by-page (strangler rewrites)
**Update Frequency**: After each sprint or status change
**Last Updated**: 2026-07-12
**Current Phase**: Phase 0 - Safety scaffolding (test coverage + guards)
**Last Updated**: 2026-07-17
**Current Phase**: ✅ COMPLETE — FL burn-down 16/16 retired (PR #365); follow-ups only

---

Expand Down Expand Up @@ -31,8 +31,8 @@ Phase 2: FL-Builder Foundations [❌❌❌❌] 4/4 WPs resolved (all closed wit
Phase 3: Additional Patterns SUPERSEDED 2026-07-12 — never started; premise died with Phases 1+2

CURRENT PLAN (2026-07-12 spec):
Phase 0: Safety scaffolding [🔲🔲✅🔲] 1/4 items (blog-post test coverage, per-page coverage check, ownership map ✅ 2026-07-12, orphan guard)
Rewrites: FL burn-down 16/16 files live → target 0 (R1 = 3059-layout: course-list + privacy-policy pages)
Phase 0: Safety scaffolding [✅✅✅✅] 4/4 items (P0.1 blog special-content tests ✅, P0.2 practiced before every sprint ✅, P0.3 ownership map ✅, P0.4 orphan guard unit test ✅)
Rewrites: FL burn-down ✅ 16/16 files RETIRED (R1–R9, PR #365, 2026-07-16..17) — zero snapdiff baseline changes across the entire run

Historical: ~73,150 lines eliminated sprints 1-7 (orphan deletion + consolidation)
```
Expand Down Expand Up @@ -431,21 +431,34 @@ JetVelocity (`.stitch/design.md`) with Paul's screenshot approval. Full protocol
in the spec; live status in `css-bundle-ownership-map.md`.

```yaml
order_easiest_first: # ascending FL size; order may flex on business need
- R1: 3059-layout.css (924) → pages: privacy-policy (page/single.html) + course-list (layouts/course/list.html)
- R2: 706-layout.css (2,202) → contact-us
- R3: 3114-layout.css (2,272) → blog-single, course-single (+ feeds single-career, single-client)
- R4: homepage-layout.css + services-layout.css (~4,356) → blog-list, free-consultation
- R5: e966db44…-layout-bundle.css (4,364) → single-career
- R6: 701-layout.css (4,462) → about-us
- R7+: 3027 (5,056), 3086-layout2 (5,157), 3082 (5,399), 2949 (5,407),
3021 (6,409), fb2624… (6,523), 737 (6,489) — ascending
- Rlast: 590-layout.css (12,437) → homepage
completed: # all shipped in PR #365 (branch css-migration/strangler-run), 2026-07-16..17
- R1: 3059-layout retired — privacy-policy + course-list semantic rewrites (46060e0c lineage)
- R2: 706-layout retired — contact-us semantic rewrite
- R3a: blog-single off FL files; .sr-only moved site-wide
- R3b: course-single off FL files (+ chapter coverage)
- R3c: fb2624…-bundle retired — single-client semantic node aliases
- R3d: 3114-layout + e966db44…-bundle retired — single-career delta port
- R4a: blog-list semantic rewrite (dropped homepage-layout/services-layout from its slice)
- R4b: free-consultation semantic rewrite; homepage-layout, services-layout,
utilities/fl-builder-grid, critical/free-consultation-critical DELETED
- R5: 701-layout retired — about-us delta port (9 dead nodes pruned)
- R6: 3086-layout2 retired — careers verbatim move (compiled bundle byte-identical)
- R7: 3021 + 3027 retired — use-cases pair delta ports (58+14 dead nodes)
- R8a: 3082 retired — clients delta port (35 dead nodes)
- R8b: 2949 retired — single-service delta port (26 dead nodes, 8-page union prune)
- R8c: 737 retired + bf72bba…-bundle DELETED (last consumer) — services delta port (41 dead nodes)
- R9: 590-layout retired — homepage delta port (47 dead nodes). BURN-DOWN COMPLETE.
notes: |
bf72bba…-layout-bundle.css (1,969; 9 bundles) and the critical/ FL trio retire
when their last consumer page is rewritten. Satellites fold with their single
importers (fl-builder-common-base.css → 3021; fl-builder-grid.css → homepage-layout).
completed: []
Evidence bar held for every commit: converged production build ×2, only the
target bundle fingerprint changed, headless old-vs-new RMSE 0 (desktop +
mobile, full page), bin/rake test:critical AND bin/dtest green, ZERO
screenshot baseline changes. Satellite fl-builder-common-base.css KEPT
(imported by pages/use-cases.css; not byte-redundant). critical/ FL trio
stays as shared framework for kept fl-node markup.
follow_ups:
- shared css/testimonials.css extraction (source hygiene; gate byte-identical)
- per-page semantic re-keying of delta-ported markup (R3c alias technique),
independent sprints with Paul's design approval if visuals change
```

---
Expand Down Expand Up @@ -514,6 +527,27 @@ fcp_metrics:

## 🔄 UPDATE LOG

### 2026-07-17 (strangler run complete — FL burn-down 16/16, PR #365)
- **Shipped**: R4a..R9 in one continuous run (R1..R3d landed 2026-07-16 on the
same branch): every FL-Builder export file retired; 16 hand-maintained
`css/pages/*.css` files own all page styling; bf72bba shared bundle,
homepage-layout, services-layout, fl-builder-grid, free-consultation-critical
deleted. gz deltas per bundle in css-bundle-ownership-map.md (typical −20-33%).
- **Method that held**: Option-A delta ports via a media-aware dead-node pruner
(prune only rules keyed on fl-node ids absent from the rendered page; keep
generics verbatim) + compiled fragment-diff liveness check + headless
old-vs-new RMSE pre-gate (caught every parity miss BEFORE the suites:
all-sides wrap padding on blog-list mobile, 4 gform generics + footer
centering + a contact-us-only button margin on free-consultation, the
bf72bba header CTA trio on use-cases/clients/services).
- **Upstream event absorbed mid-run**: rebase onto master's course v2 merge
(#361) — revalidated at HEAD both OSes; one bimodal text-wrap flake in the
new lesson-meta blockquote masked via skip_area in both chapter tests;
ZERO baseline changes.
- **Standing evidence**: every commit gated on converged build ×2 +
only-target-bundle fingerprint change + both snapdiff suites green with zero
baseline changes. The "unchanged baselines ARE the proof" bar held 16/16.

### 2026-07-12 (sprint 8 — plan re-wised, project docs realigned)
- **Action**: Goal reframed from line-count elimination to maintainability
(hand-editable, single-source, FL export retired) — approved spec
Expand Down Expand Up @@ -849,5 +883,5 @@ git checkout -b css-migration/<sprint-name>
- 🎯 [Approved spec (authority)](2026-07-12-css-maintainability-redesign.md)
- 🗺️ [Bundle ownership map + burn-down](css-bundle-ownership-map.md)

**Last Updated**: 2026-07-12
**Last Updated**: 2026-07-17
**Next Update**: After Phase 0 item completion or status change
129 changes: 79 additions & 50 deletions docs/projects/2509-css-migration/css-bundle-ownership-map.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,46 @@
# CSS bundle ownership map + FL burn-down

Answers "which pages does this CSS file affect?" for every bundle and file.
Sizes measured 2026-07-12 from a converged production build (`gzip -c | wc -c`).
Update this map whenever a resource slice changes; flip statuses as rewrite
sprints land (see `2026-07-12-css-maintainability-redesign.md`).
Original sizes measured 2026-07-12, final sizes 2026-07-17, both from converged
production builds (`gzip -c | wc -c`). Update this map whenever a resource
slice changes (see `2026-07-12-css-maintainability-redesign.md`).

## External bundles (19)

Each page type loads ONE fingerprinted bundle, built by concatenating its
template's resource slice through PostCSS (per-bundle PurgeCSS — a page ships
only its own subset; see the evidence rule in the redesign spec).

| Bundle | Owning template | FL layout files in slice | gzip | Status |
Every bundle's page CSS now lives in a hand-maintained `css/pages/*.css` file;
zero FL-Builder export files remain in any slice.

| Bundle | Owning template | Page CSS file | gzip 07-12 → 07-17 | Status |
|---|---|---|---|---|
| homepage | `home.html` (partial `homepage-css-resources.html`) | 590-layout | 29.6K | live-FL |
| services | `page/services.html` | 737-layout, bf72bba… | 25.4K | live-FL |
| single-client | `clients/single.html` | 3114-layout, fb2624… | 25.4K | live-FL |
| use-cases | `page/use-cases.html` | 3021-layout, bf72bba… | 25.0K | live-FL |
| single-service | `services/single.html` | 2949-layout, bf72bba… | 23.8K | live-FL |
| clients | `page/clients.html` | 3082-layout, bf72bba… | 23.6K | live-FL |
| careers | `page/careers.html` (partial `careers-css-resources.html`) | 3086-layout2 | 23.4K | live-FL |
| single-use-cases | `use-cases/single.html` | 3027-layout, bf72bba… | 23.3K | live-FL |
| single-career | `careers/single.html` (partial `single-career-css-resources.html`) | 3114-layout, e966db44… | 22.0K | live-FL |
| free-consultation | `page/free-consultation.html` (partial `free-consultation-css-resources.html`) | homepage-layout, services-layout | 20.2K | live-FL |
| about-us | `page/about.html` | 701-layout, bf72bba… | 19.4K | live-FL |
| course-single | `course/single.html` | 3114-layout, bf72bba… | 19.3K | live-FL |
| blog-single | `single.html` | 3114-layout, bf72bba… | 19.3K | live-FL |
| blog-list | `blog/list.html` + `list.html` (shared partial `blog-list-css-resources.html`) | homepage-layout, services-layout | 19.1K | live-FL |
| contact-us | `page/contact-us.html` (partial `contact-us-css-resources.html`) | 706-layout | 18.9K | live-FL |
| course-list | `layouts/course/list.html` (repo root, NOT in theme) | 3059-layout, bf72bba… | 17.6K | live-FL |
| privacy-policy | `page/single.html` (generic pages) | 3059-layout, bf72bba… | 17.1K | live-FL |
| not_found | `404.html` | — (404.css, dynamic-404-590.css) | 16.2K | no-FL |
| pagination | `list.html` (second bundle) | — (pagination.css only) | 0.2K | no-FL |
| homepage | `home.html` (partial `homepage-css-resources.html`) | pages/homepage.css | 29.6K → 26.6K | migrated (R9) |
| services | `page/services.html` | pages/services.css | 25.4K → 19.9K | migrated (R8c) |
| single-client | `clients/single.html` | pages/single-client.css | 25.4K → 16.6K | migrated (R3c) |
| use-cases | `page/use-cases.html` | pages/use-cases.css | 25.0K → 17.0K | migrated (R7) |
| single-service | `services/single.html` | pages/single-service.css | 23.8K → 19.1K | migrated (R8b) |
| clients | `page/clients.html` | pages/clients.css | 23.6K → 18.7K | migrated (R8a) |
| careers | `page/careers.html` (partial `careers-css-resources.html`) | pages/careers.css | 23.4K → 23.8K¹ | migrated (R6) |
| single-use-cases | `use-cases/single.html` | pages/single-use-cases.css | 23.3K → 18.8K | migrated (R7) |
| single-career | `careers/single.html` (partial `single-career-css-resources.html`) | pages/single-career.css | 22.0K → 18.8K | migrated (R3d) |
| free-consultation | `page/free-consultation.html` (partial `free-consultation-css-resources.html`) | pages/free-consultation.css | 20.2K → 16.2K | migrated (R4b) |
| about-us | `page/about.html` | pages/about-us.css | 19.4K → 15.0K | migrated (R5) |
| course-single | `course/single.html` | pages/blog-single.css (shared) | 19.3K → 12.9K | migrated (R3b) |
| blog-single | `single.html` | pages/blog-single.css | 19.3K → 12.9K | migrated (R3a) |
| blog-list | `blog/list.html` + `list.html` (shared partial `blog-list-css-resources.html`) | pages/blog-list.css | 19.1K → 15.0K | migrated (R4a) |
| contact-us | `page/contact-us.html` (partial `contact-us-css-resources.html`) | pages/contact-us.css | 18.9K → 17.4K | migrated (R2) |
| course-list | `layouts/course/list.html` (repo root, NOT in theme) | pages/course-list.css | 17.6K → 14.6K² | migrated (R1) |
| privacy-policy | `page/single.html` (generic pages) | pages/simple-page.css | 17.1K → 14.6K | migrated (R1) |
| not_found | `404.html` | — (404.css, dynamic-404-590.css) | 16.2K → 16.2K | no-FL |
| pagination | `list.html` (second bundle) | — (pagination.css only) | 0.2K → 0.2K | no-FL |

¹ careers was a byte-identical verbatim move (3086-layout2 had zero dead
nodes); the small growth vs 07-12 is upstream content drift (course v2 merge
enlarged shared members), not the migration.
² course-list also absorbed upstream growth; its migration delta at R1 time
was 17.6K → 14.2K.

Inline bundles (in `<head>` via `css-inline.html`, baseof.html): `navigation`
(css-variables + navigation.css, site-wide) and `components` (components.css,
Expand All @@ -44,35 +53,55 @@ the critical/fl-* trio), `dynamic-icons.css`, `586.css`, `vendors/base-4.min.css
`companies.css`, `careers.css`, `404.css`, `pagination.css`,
`component-bundle.css`, `theme-main.css`).

## FL layout file burn-down: 16 → 0
## FL layout file burn-down: 16 → 0 ✅ COMPLETE (2026-07-17)

Generated FL-Builder export CSS under `themes/beaver/assets/css/`. A file is
RETIRED when its last consuming bundle's page is rewritten (semantic HTML +
`css/pages/*.css`) and the file is deleted.
All 16 generated FL-Builder export files under `themes/beaver/assets/css/`
are retired. Migration technique per file (all at pixel parity — zero
snapdiff baseline changes across the whole run):

| FL file | Lines | Consumed by bundles | Status |
| FL file | Lines | Retired by | Technique |
|---|---|---|---|
| 590-layout.css | 12,437 | homepage | live |
| 737-layout.css | 6,489 | services | live |
| fb2624e43f3c4277448abe268cde571e-layout-bundle.css | 6,523 | single-client | live |
| 3021-layout.css | 6,409 | use-cases | live |
| 2949-layout.css | 5,407 | single-service | live |
| 3082-layout.css | 5,399 | clients | live |
| 3086-layout2.css | 5,157 | careers | live |
| 3027-layout.css | 5,056 | single-use-cases | live |
| 701-layout.css | 4,462 | about-us | live |
| e966db44b09892b8d7d492247c67e86c-layout-bundle.css | 4,364 | single-career | live |
| homepage-layout.css | 2,678 | blog-list, free-consultation | live |
| 3114-layout.css | 2,272 | blog-single, course-single, single-career, single-client | live |
| 706-layout.css | 2,202 | contact-us | live |
| bf72bba397177a0376baed325bffdc75-layout-bundle.css | 1,969 | 9 bundles: about-us, blog-single, clients, course-list, course-single, privacy-policy, services, single-service, single-use-cases, use-cases | live |
| services-layout.css | 1,678 | blog-list, free-consultation | live |
| 3059-layout.css | 924 | course-list, privacy-policy | live |
| 3059-layout.css | 924 | R1 | semantic rewrite (privacy-policy + course-list) |
| 706-layout.css | 2,202 | R2 | semantic rewrite (contact-us) |
| 3114-layout.css | 2,272 | R3a-d | semantic rewrite (blog/course single) + node aliases |
| fb2624e43f3c4277448abe268cde571e-layout-bundle.css | 6,523 | R3c | semantic node aliases (single-client) |
| e966db44b09892b8d7d492247c67e86c-layout-bundle.css | 4,364 | R3d | delta port (single-career) |
| homepage-layout.css | 2,678 | R4a+R4b | semantic rewrite (blog-list) + clone (free-consultation) |
| services-layout.css | 1,678 | R4a+R4b | (same two consumers) |
| 701-layout.css | 4,462 | R5 | delta port, dead-node prune (about-us) |
| 3086-layout2.css | 5,157 | R6 | verbatim move, byte-identical bundle (careers) |
| 3021-layout.css | 6,409 | R7 | delta port, 58 dead nodes pruned (use-cases) |
| 3027-layout.css | 5,056 | R7 | delta port, 14 dead nodes pruned (single-use-cases) |
| 3082-layout.css | 5,399 | R8a | delta port, 35 dead nodes pruned (clients) |
| 2949-layout.css | 5,407 | R8b | delta port, 26 dead nodes pruned (single-service) |
| 737-layout.css | 6,489 | R8c | delta port, 41 dead nodes pruned (services) |
| bf72bba397177a0376baed325bffdc75-layout-bundle.css | 1,969 | R5–R8c | dropped per consumer slice; deleted at R8c (last consumer: services). Its only live contribution (header CTA button, 3 rules) ported into use-cases/clients/services page files; about/single-service criticals carried byte-identical copies |
| 590-layout.css | 12,437 | R9 | delta port, 47 dead nodes pruned (homepage) |

Satellites: `utilities/fl-builder-grid.css` deleted with homepage-layout.css
(R4b). `foundations/fl-builder-common-base.css` KEPT — now imported by
pages/use-cases.css; its content is NOT byte-redundant in the compiled bundle
(deletion attempt changed the fingerprint, reverted). The `critical/` FL trio
(`fl-layout-grid.css`, `fl-shape-dividers.css`, `fl-common-modules.css` via
`critical/base.css`) remains as shared framework for the kept fl-node markup.

**Previously retired**: e93d9b85…-layout-bundle.css (merged into superset
bf72bba…, PR #363, 2026-07-12); 6 never-loaded orphans deleted same PR.

Satellites that retire with their last importer: `foundations/fl-builder-common-base.css`
(imported only by 3021-layout.css), `utilities/fl-builder-grid.css` (imported only
by homepage-layout.css), and the `critical/` FL trio (`fl-layout-grid.css`,
`fl-shape-dividers.css`, `fl-common-modules.css` via `critical/base.css`).
## Follow-ups (not blocking)

**Retired so far**: e93d9b85…-layout-bundle.css (merged into superset bf72bba…,
PR #363, 2026-07-12); 6 never-loaded orphans deleted same PR.
- Shared `css/testimonials.css`: the testimonials-partial node rules are now
carried (identically) inside several pages/*.css files; extracting them once
is a source-hygiene pass — gate on byte-identical compiled bundles.
- Markup still carries `fl-node-*` classes on pages migrated via delta port
(Option A). Semantic re-keying per page remains available as separate,
independently-gated cleanup sprints (the R3c alias technique).
- Code-block fallback background is cascade-order-dependent: for bare/unknown
fences (no Chroma inline styles) the dark `#282a36` background wins only
because `style.css .blog pre` sorts after `586.css .single-content pre`
(equal 0-1-1 specificity) in the blog-single bundle. Hardening = delete the
losing `background-color:#F5F6F8` from `.single-content pre` (586.css:823)
— deferred because 586.css is shared by most bundles (fingerprint churn).
The regression is now screenshot-locked by `test_codeblock_language_styles`
(fixture post `codeblock-styles-fixture`, bare + indented shots would flip
to light-bg/invisible-text on a cascade flip).
Loading
Loading