Skip to content

C3 complete: course CSS extraction + mid-body lesson visuals - #486

Merged
pftg merged 12 commits into
masterfrom
close-c3-2026-08-20
Aug 20, 2026
Merged

pftg merged 12 commits into
masterfrom
close-c3-2026-08-20

Conversation

@pftg

@pftg pftg commented Aug 20, 2026 •

Copy link
Copy Markdown
Member

Paul: "let's finish them… FINISH ALL." This PR started as a closure, got overruled, and now ships the whole thing. The C-queue is complete.

C3.2 — course CSS out of the global sheet

I audited the spec before executing it, and most of W4 was already built: the TL;DR accent exists (bq-tldr render hook + styling, PR #356), and the walkthrough heroes and artifact trails exist too — I redrew the latter this morning in C2.2.

The one genuinely unbuilt item was the first the spec named. The course reading scale (8 rules) was living in the site-wide style.css, so every blog and marketing visitor downloaded selectors that can only ever match a course page. Now in css/pages/course-single.css, loaded only by the course template, after single-post.css because it overrides that file's body type.

Two judgment calls:

  • Did not move the bq-tldr/bq-good/bq-bad callout accents. Zero blog pages use them today, so by usage they look course-only — but they're driven by a render hook any page can trigger. Extract on what the selector guarantees, not on what currently uses it, or a future blog post silently loses its callout colours.
  • Kept the .section-course prefix despite the file being course-only. Dropping it lowers specificity (0,4,2) → (0,3,2) and hands the cascade back to single-post.css — the exact trap course-typography.md documents.

Verified behaviour-preserving in-browser (body 20px/33px, blockquote 19px/30.4px, li 20px) and zero screenshot diffs, which is the bar for a refactor rather than a redesign.

C3.3 — mid-body visuals, 3 of 4 pages

Lesson Exhibit Scores
1.2 draft-vs-rewrite.svg 4/4
1.5 clicks-vs-payments.svg 4/4
5.7 batch-funnel mermaid (TD) 4/4

1.3 was declined, and the reasoning is right: every candidate either re-drew the mechanism its existing tracking-snippets.svg already owns, or illustrated a one-sentence checklist. A page whose rhythm has no hole doesn't get an exhibit.

The 1.5 exhibit's author flagged their own weakest call — the prose above it already states all four numbers. I checked it rendered and kept it: the paragraph is a dense ~90-word bullet asserting that identical payment counts mean opposite things, while the dot field shows it, and the 20 dashed empty slots make "too small a sample" visceral in a way the sentence can't.

Found while there: a live contradiction in 5.7

The page promised "3-5 demo calls booked" in its header and "2-3" in its success check — not merely inconsistent but impossible at the top end, since the same page caps replies at 1-4 and you can't book 5 demos from 4 replies. Corrected to 2-3.

The agent had deliberately left the exhibit's demo stage unnumbered because of that contradiction, which was the right instinct — an exhibit is the wrong instrument for picking a side in a body inconsistency. With it resolved, the stage now carries its number and the SVG was regenerated (hash changed, orphan deleted).

Test plan

  • bin/hugo-build green throughout
  • bin/check-svg-floor lists none of the new exhibits
  • Rendered at 1280×800 and mobile; img.complete awaited; no horizontal overflow; pre-rendered mermaid confirmed shipping no mermaid.js
  • bin/test (macOS leg) — 34 runs, 87 assertions, 53 screenshots, 0 failures
  • Linux leg via CI; never local bin/dtest on this ARM Mac

🤖 Generated with Claude Code

Answering 'should we finish C2 and C3?' - C2 is already finished (both
items merged today), C3.1 is done, and C3.2/C3.3 are closed WITHOUT being
built.

Closed rather than carried, because a dangling 'someday' item has a real
cost: these got re-litigated in three separate sessions. Three independent
reads say the same thing - the 2026-08-13 panel demoted them to
opportunistic, the Aug-14 read said aim template work at M2-M3 because
M4/M5 are 'pages almost no one reaches', and the Aug-20 GA/GSC pull shows
~23 real course arrivals in 28 days against course URLs sitting at
positions 5-13 with 2 clicks. Rebuilding the course template for that
traffic is work gated on a number that has not moved.

C3.1 was built for the opposite reason and the contrast is the point: a
390px overflow is a defect every visitor hits, not an improvement for a
hypothetical one.

Recorded with a REOPEN TRIGGER (arrivals >~50/28d from one channel, or a
funnel drop located at the template layer rather than at arrival) and an
explicit 'do not reopen merely because the items exist'. Re-groom from
20.15 §W4 at that point, not from this file - the spec will be stale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4c58ab77-5019-4261-bc77-0bf5c5e6ebb7


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

pftg and others added 7 commits August 20, 2026 16:04
… half

Paul overrode the closure: 'let's finish them, we will fix distribution
later and we should give them good top level course and experience.' The
override is better reasoning than the panel's - every closure argument was
about SEQUENCING (don't polish what nobody reaches), his is about PRODUCT
(the quality bar is not conditional on this month's traffic, and fixing it
later against a live audience is the worse order). Kept the overruled
closure in the file rather than deleting it, so the trade-off stays legible.

Then a second correction, also Paul: 'we work on UI design in parallel, so
only content and visuals should be handled here.' C3.2's template half
(course-single.css, course/single.html, TL;DR accent, walkthrough hooks)
is retired from this queue - a concurrent redesign owns those files and a
content sprint editing them would collide. The queue keeps the visual half
only, which drops the gate class from TEMPLATE to CONTENT-ONLY.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
W4/V3-B's real remaining item. Audited the spec before building it, and
most of W4 turned out to be already shipped: the TL;DR accent exists
(bq-tldr render hook + styling, PR #356), and the walkthrough heroes and
artifact trails exist too - I redrew the latter this morning in C2.2. What
had NOT been done is the one the spec named first.

The course reading scale (8 rules) was living in the site-wide style.css,
so every blog and marketing visitor downloaded selectors that can only
match a course page. Moved to css/pages/course-single.css, loaded only by
layouts/course/single.html, after single-post.css because it overrides
that file's body type.

Deliberately NOT moved: the bq-tldr / bq-good / bq-bad callout accents.
They are course-only in practice today (0 blog pages use them) but they
are driven by the render-blockquote hook, which any page can trigger.
Extract on what the selector GUARANTEES, not on what currently uses it -
otherwise a future blog post silently loses its callout colours.

Kept the  prefix even though the file is course-only:
dropping it would lower specificity from (0,4,2) to (0,3,2) and hand the
cascade back to single-post.css - the exact trap course-typography.md
documents.

Behaviour preserved: body p 20px/33px, blockquote p 19px/30.4px, li 20px
with 12px margin, all verified in-browser. bin/qtest --changed: 34 runs,
53 screenshots, ZERO diffs - which is the bar for a refactor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The lesson describes the four copy blocks as rules, then hands the reader a
builder prompt - but nothing shows what a generic draft actually looks like
next to the version worth shipping. Adds one O2 exhibit between the Step 2
prompt and the Build steps, at the moment the reader is holding a fresh draft
and has to judge it: headline and value prop, builder draft vs rewrite, using
the copy already canon in the body ("Smart Solutions for Modern Businesses",
"Calendar integration").

Exhibit: hand-authored SVG (O2 flat-vector, matching page-anatomy.svg on the
same page), viewBox 720x400, min font 17px.

Gates:
- bin/hugo-build green (8/8 validators)
- bin/check-svg-floor does not list draft-vs-rewrite.svg
- text fit measured with getComputedTextLength, not budgeted: widest card
  string 261 of 284 available; title 623 of 704
- rendered at 1280x800 (684x380, no overflow, console clean) and in a true
  358px mobile column (358x199, every label readable without zoom)

Scores: look YES / readable YES / earns-scroll YES / helpful YES.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The section's diagnostic is a sample-size argument stated in prose - 60 clicks
with 3 payments means the checkout is broken, 6 clicks with the same 3 means
nothing yet. Prose can state that; it cannot show it. Adds a unit-dot exhibit
where the reader reads their Stripe numbers: one dot per click, 3 green paid in
both fields, and 20 dashed empty slots on the right marking the minimum before
the ratio is worth trusting. Exact counts, no scale distortion.

Numbers are the section's own (60/3, 6/3, 20+); no new figures introduced.
Green is money (completed payments), ruby carries the one actionable reading,
amber the sample-size warning.

Exhibit: hand-authored SVG (O2 flat-vector, matching stripe-payment-link.svg on
the same page), viewBox 720x468, min font 17px.

Gates:
- bin/hugo-build green (8/8 validators)
- bin/check-svg-floor does not list clicks-vs-payments.svg
- text fit measured with getComputedTextLength: widest in-card string 254 of
  284 available; title 582 of 704; legend span centred at 364
- rendered at 1280x800 (684x445, no overflow, console clean) and in a true
  358px mobile column (358x233, dot fields and both verdicts readable)

Scores: look YES / readable YES / earns-scroll YES / helpful YES.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The lesson tells the reader to send 30 messages and expect 3-8% replies, then
warns 200 words later that 0-1 replies on batch 1 is the median rather than a
failure. That reassurance arrives after the reader has already sent and started
counting. Adds a four-stage funnel between the pipeline stages and the message
script, so the realistic shape of one batch - and the "0-1 is normal" reading -
is visible before the send, not after.

The demo-call stage carries no number on purpose: the page states 3-5 in its
header block and 2-3 in the success check, and an exhibit is the wrong place to
pick a side. Every other figure is the page's own.

Exhibit: mermaid flowchart TD (vertical - LR fails at 390px with 4+ nodes),
pre-rendered via bin/render-mermaid to mermaid-244b4dfc.svg and committed.
accTitle/accDescr carry the full reading into the SVG title and desc. Amber
marks the expectation warning, green the money outcome.

Gates:
- bin/hugo-build green (8/8 validators)
- bin/check-svg-floor unaffected (mermaid renders at native size, not scaled)
- rendered at 1280x800 (272x653, no overflow, console clean) and at a narrow
  mobile column (272x653 unscaled, so it clears a 358px column with room)
- height 653px, well under the 2x-viewport wall ceiling

Scores: look YES / readable YES / earns-scroll YES / helpful YES.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The C3.3 agent left the exhibit's demo stage deliberately unnumbered
because the page contradicted itself - the header block promised '3-5 demo
calls booked' while the success check said '2-3'. Declining to pick a side
in artwork was the right call: an exhibit is the wrong instrument for
resolving a body inconsistency.

The header was the wrong one, and not just inconsistent - arithmetically
impossible at the top end, since the same page caps replies at 1-4 and you
cannot book 5 demos from 4 replies. Corrected to 2-3, matching the success
check and the reply range.

With the contradiction resolved the stage can carry its number, so the
fence and its accDescr now say '2-3 demo calls booked' and the pre-rendered
SVG was regenerated (hash changed, orphan deleted). A funnel numbered at
every stage but one reads as an omission.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pftg pftg changed the title Close C3.2/C3.3 unbuilt; C2 and C3.1 done C3 complete: course CSS extraction + mid-body lesson visuals Aug 20, 2026
pftg and others added 4 commits August 20, 2026 16:50
Not my change - it comes in with #487 (blog-first design system), which
passed its own CI on Linux while this macOS baseline went stale. Rendered
content verified correct: the three case-study cards, logos, tech pills
and CTA all intact.

Noting what the screenshot also shows: the cards carry 'to the next level'
twice, which is the banned marketing phrase C0.1's ratchet baselined. That
is the one-partial-25-violations syndicated defect, live on the homepage.
Not fixed here - it is content work, not a baseline decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 2608 design system (#487) added the container itself to the blog
typography selector list, not just p/li. Without matching it, bare text
directly inside .fl-rich-text on a course page would fall back to the blog
size. Verified at desktop: container/p/li all 20px, blockquote 19px.

Exactly the interaction course-typography.md's specificity trap predicts -
worth catching by merging the parallel branch and re-measuring rather than
assuming a clean textual merge means a clean semantic one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul caught it. Verified: every commit of mine on master carries a PR
number except 4acb018 (~40 Linux baseline PNGs, github-actions[bot]).
I dispatched that with --ref master, and the record job commits to
whatever ref it is given.

The rule worth stating is subtler than 'do not commit to master': a tool
that writes to the repo inherits your obligations. Delegating a write to
CI does not exempt it from branch+PR any more than delegating to a
subagent would. I would not have hand-committed 40 PNGs to master - I
dispatched a job that did it for me and did not notice the difference.

Aggravating: screenshot baselines are exactly the artifact class that
hides banned copy from text ratchets, which is WHY I was re-recording
them. And the correct form costs nothing - the workflow honours
--ref <branch>, so they could have ridden the PR that needed them.

ci-gates.md now carries the wrong and right invocations side by side.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pftg
pftg merged commit 959a1a8 into master Aug 20, 2026
6 checks passed
@pftg
pftg deleted the close-c3-2026-08-20 branch August 20, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant