From e77bb8ed7b49dfc3fa10c4e1b81b72930a7a2148 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Sun, 10 May 2026 21:31:13 +0200 Subject: [PATCH 1/3] style: tables, code blocks, blockquotes for essay prose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CV repo's stylesheet had no rules for
, , or 
because the CV body never used them. Essays do, and the unstyled output looked bad — tables had no header distinction or row dividers, fenced code blocks inherited the inline- tinted background (making each line look stamped onto a band), blockquotes were invisible. Added: .prose pre warm cream (#f3efe6) panel, 1px wine-tinted border, 6 px radius, 0.85 rem mono, overflow-x: auto for long lines, tab-size 2, ligatures off. .prose pre code reset background/padding/radius from the inline rule so the panel reads as one block. .prose code (refined) only applies to inline code now; slight bump to background tint contrast. .prose table block + overflow-x for narrow viewports; hairline row dividers; tabular-nums on numeric cells; padding only on inter-column gaps so the column aligns flush-left with the prose. .prose th Inter small-caps header in muted color, 2 px bottom rule. .prose blockquote 3 px wine accent left rule, italic, muted; reset margins on first/last

child to avoid double spacing; cancel italic on nested . Print sheet: pre / table / blockquote get break-inside: avoid so they don't split awkwardly mid-block; pre keeps its background on print. Verified visually against http://localhost:8782/essays/: table reads as a metric grid, blockquote reads as a quote, code block reads as one panel rather than per-line stamped strips. Signed-off-by: Sebastian Mendel --- assets/style.css | 94 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/assets/style.css b/assets/style.css index 92c2619..df28192 100644 --- a/assets/style.css +++ b/assets/style.css @@ -255,14 +255,96 @@ body { .prose em { font-style: italic; } +/* Inline `` — only when NOT inside a

. */
 .prose code {
   font-family: ui-monospace, "SF Mono", "JetBrains Mono", Consolas, monospace;
   font-size: 0.9em;
-  background: rgba(0, 0, 0, 0.04);
+  background: rgba(0, 0, 0, 0.045);
   padding: 0.1em 0.3em;
   border-radius: 3px;
+  word-break: break-word;
 }
 
+/* Fenced code blocks: container is 
, child  resets the inline
+   tint/padding so we don't get a "background per line" look. */
+.prose pre {
+  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Consolas, monospace;
+  font-size: 0.85rem;
+  line-height: 1.55;
+  background: #f3efe6;          /* warmer than the page (#fbfaf6) */
+  color: var(--color-text);
+  border: 1px solid var(--color-rule-bold);
+  border-radius: 6px;
+  padding: 0.95rem 1.1rem;
+  margin: 1.3rem 0;
+  overflow-x: auto;             /* horizontal scroll, no line wrap */
+  -webkit-overflow-scrolling: touch;
+  tab-size: 2;
+  font-variant-ligatures: none;
+}
+.prose pre code {
+  background: none;
+  padding: 0;
+  border-radius: 0;
+  font-size: inherit;
+  line-height: inherit;
+  color: inherit;
+  white-space: pre;
+  word-break: normal;
+}
+
+/* Tables — editorial: header row in Inter small caps, hairline row dividers,
+   tabular numerics for metric columns, horizontal scroll on overflow. */
+.prose table {
+  display: block;             /* enables overflow-x on the wrapper */
+  max-width: 100%;
+  overflow-x: auto;
+  border-collapse: collapse;
+  margin: 1.3rem 0;
+  font-size: 0.92rem;
+  font-variant-numeric: tabular-nums;
+}
+.prose table thead,
+.prose table tbody,
+.prose table tr { width: 100%; }
+.prose th,
+.prose td {
+  text-align: left;
+  padding: 0.55rem 0.85rem 0.55rem 0;
+  border-bottom: 1px solid var(--color-rule);
+  vertical-align: top;
+}
+.prose th:last-child,
+.prose td:last-child {
+  padding-right: 0;
+}
+.prose th {
+  font-family: var(--sans);
+  font-weight: 600;
+  font-size: 0.74rem;
+  letter-spacing: 0.08em;
+  text-transform: uppercase;
+  color: var(--color-muted);
+  border-bottom: 2px solid var(--color-rule-bold);
+  padding-bottom: 0.5rem;
+}
+.prose tbody tr:last-child th,
+.prose tbody tr:last-child td {
+  border-bottom: 0;
+}
+
+/* Blockquotes — left rule in accent, italic, slightly muted. */
+.prose blockquote {
+  margin: 1.3rem 0;
+  padding: 0.2rem 0 0.2rem 1.1rem;
+  border-left: 3px solid var(--color-accent);
+  color: var(--color-muted);
+  font-style: italic;
+}
+.prose blockquote p:first-child { margin-top: 0; }
+.prose blockquote p:last-child { margin-bottom: 0; }
+.prose blockquote em { font-style: normal; }   /* avoid double-italic on nested em */
+
 /* -------- Footer -------- */
 
 .page-footer {
@@ -484,6 +566,16 @@ a:focus-visible,
   .prose ul, .prose ol, .prose p { orphans: 3; widows: 3; }
   .prose li { break-inside: avoid; page-break-inside: avoid; }
 
+  /* Code, tables, blockquotes — avoid splitting across pages where possible. */
+  .prose pre,
+  .prose table,
+  .prose blockquote {
+    break-inside: avoid;
+    page-break-inside: avoid;
+  }
+  .prose pre { font-size: 9pt; background: #f3efe6; }
+  .prose table { font-size: 9.5pt; }
+
   .prose a[href^="http"]::after {
     content: " (" attr(href) ")";
     color: #5a5a5a;

From f88878a396f89bdcce88d12284b02a375c3433a8 Mon Sep 17 00:00:00 2001
From: Sebastian Mendel 
Date: Sun, 10 May 2026 21:35:42 +0200
Subject: [PATCH 2/3] fix(build): depth-aware @font-face URLs + link
 coding_agent_cli_toolset
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Two related issues caught by Lighthouse-CI on PR #1.

1. Console errors (best-practices score 0)

   The inlined CSS was using url("assets/fonts/…") for every page,
   which only resolves correctly when the HTML page sits at the site
   root. For essay pages at /essays/.html, the same relative
   URL resolved to /essays/assets/fonts/… and 404'd, raising console
   errors and tanking the best-practices category.

   Fix: load_inline_css() now takes a font_url_prefix string and
   rewrites the on-disk url("fonts/…") tokens accordingly:

     index page (depth 0):  url("assets/fonts/…")
     essay     (depth 1):  url("../assets/fonts/…")

   This matches what the  hints emit via the
   asset() helper, so the preloaded font URL and the @font-face URL
   match exactly and the preload is reused for the fetch.

2. Toolset reference

   The 'Skills und CLI-Tools bereitstellen' section listed example
   tools (jq, yq, xmlstarlet, mlr, Serena, ripgrep, Explore/subagent)
   but didn't point readers at a curated bundle. Added a one-sentence
   reference to netresearch/coding_agent_cli_toolset — a maintained,
   installable bundle of the CLI tools that actually save coding-
   agent tokens in practice.

Verified locally:
  index inlined CSS uses 'assets/fonts/…'
  essay inlined CSS uses '../assets/fonts/…'
  essay preload hints use '../assets/fonts/…'

The build pipeline change is small but the fix is structural — any
future essay folder depth would just need a new prefix passed to
load_inline_css().

Signed-off-by: Sebastian Mendel 
---
 ...mizing-claude-code-cache-read-inflation.md |  2 +
 scripts/build.py                              | 38 +++++++++++--------
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/essays/optimizing-claude-code-cache-read-inflation.md b/essays/optimizing-claude-code-cache-read-inflation.md
index ff6e154..3e73357 100644
--- a/essays/optimizing-claude-code-cache-read-inflation.md
+++ b/essays/optimizing-claude-code-cache-read-inflation.md
@@ -440,6 +440,8 @@ Beispiele:
 
 Der schlechteste Weg ist oft: komplette Datei lesen und dann im Chat "verstehen".
 
+Wer das Werkzeug-Set systematisch aufbauen möchte, findet eine kuratierte und dokumentierte Auswahl unter [`netresearch/coding_agent_cli_toolset`](https://github.com/netresearch/coding_agent_cli_toolset) — ein installierbares Bündel der CLI-Tools, die Coding-Agents in der Praxis tatsächlich Tokens sparen.
+
 ### `/insights` und `/status` nutzen
 
 Fragt regelmäßig:
diff --git a/scripts/build.py b/scripts/build.py
index e01ad49..995278f 100644
--- a/scripts/build.py
+++ b/scripts/build.py
@@ -123,17 +123,24 @@ def render_md(body: str) -> str:
     return md.convert(body)
 
 
-def load_inline_css() -> str:
-    """Read assets/style.css, rewrite font URLs for inlining into HTML.
-
-    Same trick as the CV repo: source CSS references fonts as
-    `url("fonts/...")` (relative to the CSS file), but when inlined into
-    HTML via