Skip to content

fix: mermaid light-mode + add About page (Variation B)#50

Open
avrabe wants to merge 4 commits intomainfrom
fix/mermaid-classdef-light-mode
Open

fix: mermaid light-mode + add About page (Variation B)#50
avrabe wants to merge 4 commits intomainfrom
fix/mermaid-classdef-light-mode

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 3, 2026

Two changes bundled (per request):

1. Mermaid light-mode color override

User reported diagrams in light mode show a "weird half-way" state — half cream-paper, half dark-mode internals.

Root cause: each blog post's `classDef` lines compile to CSS rules INSIDE the rendered SVG's `<style>` tag, scoped by a dynamic `#mermaid-NNN` id and marked `!important`. That combination — ID specificity + `!important` + later source order than main.css — means outer CSS cannot override them. Verified by headless dump of actual rendered SVG.

Fix: after mermaid renders, JS walks every `.mermaid svg style` element and replaces 7 greyscale hex values (3 fills + 2 borders + 2 text tones) with cream-mode equivalents. Semantic accent strokes (blue/green/amber/red/purple) are left alone — they read on either background and carry meaning.

Dark Light
`#1a1d27` (surface) `#fbf7ee`
`#13161f` (bg-subtle) `#ebe5d6`
`#0f1117` (bg) `#f4efe4`
`#3d4258` (border-subtle) `#b8ac8c`
`#4a5068` (border) `#8a7e62`
`#e1e4ed` (text) `#1a2235`
`#8b90a0` (text-dim) `#44516a`

Note on the timing: first attempt used a `MutationObserver` which created an infinite loop (modifying the style tag triggered more mutations → recursion → site hung in browser). Replaced with three bounded `setTimeout` calls (300ms, 1000ms, 2500ms). Idempotent so multiple firings are harmless.

2. About page (Variation B)

The page the multi-persona panel agreed on (16 of 20 picks) as the highest-leverage addition for non-specialist readers. Five-section structure:

  • Hero + framing
  • The bench, today — live demo card: `witness verify gale.wasm` · 805 properties · 39/39 modules · signed attestations · honest "pre-1.0, DO-330 TQL not yet qualified" posture
  • 3 claims / 3 ships / 2 unknowns (Mission Thesis pattern)
  • Where to start, by role — Embedded · Formal-methods · Safety-compliance · AI-tooling
  • Get involved (community-only — no commercial CTA pending Impressum + Datenschutzerklärung)

Files: `content/about.md`, `templates/about.html`, `templates/base.html` nav link added between Home and Blog.

Live at `/about/` after merge.

Test plan

  • zola build clean (27 pages → /about/ present in output)
  • Browser console clean (mermaid renders normally now, no infinite loop)
  • About page renders with Variation B layout
  • CI passes
  • After merge: visit `/blog/spec-driven-development-is-half-the-loop/` in light mode — diagrams cream + navy with semantic accents, no dark blobs
  • After merge: `/about/` reachable + nav shows Home · About · Blog · Projects · Reports · GitHub · 🌗

🤖 Generated with Claude Code

avrabe and others added 4 commits May 2, 2026 09:18
Per the org-wide CI Concurrency Hardening brief. Adds top-level
`concurrency:` blocks to cancel superseded PR runs while preserving
main-branch / scheduled / release runs.

Classification per file:

- ci.yml         → default variant
                   Cancels superseded runs on PRs only; main-branch
                   runs (which this workflow doesn't currently have,
                   but the conditional `cancel-in-progress` is a
                   future-proofing default) are never cancelled.

- deploy.yml     → release variant
                   Never cancels a deploy. The deploy script does
                   `find . -delete && tar -xzf` on Netcup; cancelling
                   mid-flight could leave the site in a half-deleted
                   state. Group by ref so parallel pushes serialize
                   without race-deleting each other.

- blog-autopublish.yml → ALREADY HAS the correct concurrency block
                   (group: blog-autopublish, cancel-in-progress: false).
                   This is a fixed-group pattern that serializes ALL
                   autopublish runs (cron + workflow_dispatch). For
                   this workflow that's correct, NOT the brief's
                   "scheduled variant" with ${{ github.run_id }}: this
                   workflow mutates repo state (creates branches and
                   PRs), so concurrent runs would race. Per idempotency
                   rule, leaving unchanged.

No job-level concurrency. No `runs-on:` changes. No matrix
restructuring. Scope is strictly `.github/workflows/`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous attempt (CSS attribute selectors on inline `style="..."`)
never worked — mermaid v11 doesn't emit inline styles. Each post's
`classDef` lines compile to CSS rules INSIDE the rendered SVG's
`<style>` tag, scoped by a dynamic `#mermaid-NNN` id and marked
`!important`. That combination (ID specificity + !important + later
source order than main.css) means outer CSS cannot override them.

Fix: after mermaid renders, walk every `.mermaid svg style` element
and rewrite the hardcoded dark hex values (the greyscale bg + text
tones) to their cream-mode equivalents. The semantic accent strokes
(blue/green/amber/red/purple) are left alone — they read on either
background and carry meaning (good=green, warn=amber, etc.).

Replacements only apply to mermaid-injected `<style>` content, never
the wider page CSS. The patch is idempotent — re-running on
already-patched CSS finds no dark hex strings to replace.

A MutationObserver catches mermaid's async render; two fallback
setTimeouts handle the case where the observer attaches after render.

Removed the stale CSS-based attempt from `_blog.scss`; left a
comment explaining why outer CSS can't solve this and pointing at the
JS fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…hanging the site)

The MutationObserver approach was watching every childList mutation in
document.body, then modifying the SVG's style tag textContent, which
itself triggered more mutations, which re-triggered the observer.
Infinite loop — site hung in the browser.

Bounded setTimeouts (300ms / 1000ms / 2500ms) cover the same timing
windows without the recursion risk. The patch function remains
idempotent so multiple firings are harmless.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The page that the multi-persona panel agreed on as the highest-leverage
addition for non-specialist readers. Variation B framing: hero +
artifact card (witness on gale: 805 properties · 39/39 modules · signed
attestations) + 3 claims / 3 ships / 2 unknowns + role-keyed routing
(Embedded / Formal-methods / Safety-compliance / AI-tooling) + community
engagement.

No commercial CTA — keeps the site within the German Impressum +
GDPR Datenschutzerklärung constraints (no email contact links, no
'design partners welcome' framing) until those documents exist.

Files: content/about.md (frontmatter + template directive),
templates/about.html (full page layout), templates/base.html (nav link
between Home and Blog).

Pages: 27 → 28 in the build output (the new /about/ page).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@avrabe avrabe changed the title fix: light-mode mermaid color override via SVG style-tag patching fix: mermaid light-mode + add About page (Variation B) May 3, 2026
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