Isolated-rendering contexts — audit + the inherit-block trap
2026-05-15 · late morning · post-XSL-fix debrief + portfolio audit
Today’s agent-sitemap.xsl regression (Newsreader → Georgia + white background instead of cream) wasn’t an XSL-specific bug — it was a class of bug. Any presentation-layer syntax that renders in its own document context doesn’t inherit page-level CSS, fonts, or variables from the rest of the site. This report names the class, audits every surface in the portfolio that’s vulnerable, and pins recommendations for going forward.
TL;DR
- The class: XSL stylesheets, email HTML, iframes, web components (with Shadow DOM), PDFs, SVG with embedded styles, AMP, RSS feeds — each renders in its own document context. None inherit the site’s
<style>blocks, fonts, or CSS variables. Every visual decision must be explicitly re-stated in each isolated context - Today’s incident:
agent-sitemap.xslwas missing@font-facefor Newsreader + hadbackground: #fffinstead of cream. Two visual regressions until caught + fixed - Other surfaces audited:
main-sitemap.xsl(fine — uses Google Fonts via<link>), Worker email templates (fine — system fonts by design),dogwood-agent-stack-staging/agent-sitemap.xsl(works regardless — Georgia primary, Newsreader fallback) - Inconsistency surfaced: dare.co.uk loads Newsreader via two different mechanisms across the codebase (
<link>Google-Fonts CDN AND inline@font-faceto/cf-fonts/). Both work; the inconsistency is a latent confusion source - Going forward: every new isolated-rendering surface gets the “carefully reassessed” treatment from the discovery checklist below
The pattern
| Context type | What’s isolated | What you have to re-state |
|---|---|---|
| XSL stylesheets | Entire rendering — browser transforms XML→HTML client-side, applies styles fresh | All CSS variables, all @font-face, all colors, all fonts, all spacing |
| HTML email | Email client wraps the content; outer environment is hostile | Inline styles only (most clients strip <style>), web-safe fonts, no external CSS, no JS, no CSS variables |
| iframes | Separate document, no parent CSS access | Everything — <head>, fonts, scripts |
| Web Components / Shadow DOM | Shadow root isolates styles | Inside-shadow styling explicit; CSS custom properties cross the boundary via opt-in only |
| PDFs (browser print) | Different media query | Print stylesheet OR equivalent fallback |
SVG with <style> |
When inlined: shares with HTML. When loaded as <img> / external: isolated |
If external/img: re-state colors, fonts |
| AMP pages | Restricted CSS (no external, size cap, allowed properties) | Re-state in <style amp-custom> |
| RSS feeds (with XSL) | Same as XSL stylesheets | Same as XSL |
The pattern is isolation. The instinct is inheritance (because we’re used to global stylesheets, design tokens, font links). The trap is shipping something that “looks right when previewed in a styled container” — but renders bare in the browser’s actual rendering context.
Today’s incident — what regressed and why
File: ~/Code/dare-co-uk/agent-sitemap.xsl (shipped this morning as part of the agent-discoverability stack)
Symptom (per Dan): “80% great, lost the 20%” — the italic-Newsreader H1 fell back to Georgia, the cream-background brand-feel fell back to white.
Root cause:
/* Original (the bug): */
body { background: #fff; ... } /* white instead of cream */
.hero h1 { font-family: "Newsreader", Georgia, serif; font-style: italic; }
/* ↑ references Newsreader but no @font-face → falls back to Georgia */
The XSL document doesn’t share resources with dare.co.uk’s main pages. The Newsreader font that loads on every other page wasn’t loaded here. The cream background that’s a :root --cream var on every other page wasn’t defined here.
Fix (commit 22a3ba46 + 29c2dc26):
:root { --cream: #f5f0e8; ... } /* define the var */
body { background: var(--cream); ... } /* use it */
/* @font-face blocks added: three unicode-range slices matching
dare.co.uk's main inline @font-face emissions */
@font-face { font-family: Newsreader; src: url(/cf-fonts/v/newsreader/5.0.16/latin/opsz/italic.woff2); ... }
@font-face { /* latin-ext */ }
@font-face { /* vietnamese */ }
Diagnostic bonus: /cf-fonts/... paths on dare.co.uk return HTTP 200 to browsers (with Referer set) but 404 to raw curl. Cloudflare hotlink protection on the font CDN paths. Not a problem in practice (the XSL is loaded by a browser visiting dare.co.uk) but worth knowing for future curl-based font diagnostics.
Audit — every isolated-rendering surface in the portfolio
XSL stylesheets
| File | Status | Notes |
|---|---|---|
~/Code/dare-co-uk/agent-sitemap.xsl |
✓ Fixed today | @font-face for Newsreader (via /cf-fonts/) + cream background restored |
~/Code/dare-co-uk/main-sitemap.xsl |
✓ Healthy | Loads Newsreader via Google Fonts <link> (different mechanism, same effect). Background uses --bg: #fbf8f3 (slightly warmer off-white than archive cream) — intentional |
~/Downloads/dogwood-agent-stack-staging/agent-sitemap.xsl |
✓ Robust by construction | Uses Georgia primary, Newsreader as fallback. Georgia is a system font (always available) so Newsreader never loads — but it’s never needed |
Email templates (Worker)
| File | Status | Notes |
|---|---|---|
~/Code/dare-contact-page/dare-contact-worker.js::buildEmailHtml() |
✓ Email-correct | Uses -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif — system stack. No webfonts (correct for email clients which often strip them). Background colors are explicit hex (#f9f9f9, etc.) — no var reliance |
Email is the most isolated rendering context in existence (Gmail strips half your <style> block) and the Worker template is correctly defensive — inline styles, system fonts, plain hex colors. Good model for any future portfolio email work.
iframes / web components / PDFs
None in current portfolio. Watch item: if dogwood ever embeds a third-party booking widget via iframe, or audrey adds a custom Shopify section with Web Components, the iframe / shadow-DOM rules apply (re-state styling inside the boundary).
Future / planned surfaces
- beta.dogwood.house (flat HTML, planned) — will need its own font loading, separate from Squarespace primary
- Audrey’s future custom Shopify sections — Liquid templates inherit theme CSS, but any Shopify app with Shadow DOM or iframe widget is isolated
- Any RSS feed XSL dare adds — same XSL rules apply
The font-loading inconsistency (latent confusion source)
dare.co.uk currently loads Newsreader via two different mechanisms, both correct, both working:
<!-- Pattern A — Google Fonts <link> (used in main-sitemap.xsl + 8 article pages) -->
<link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@..." rel="stylesheet">
<!-- Pattern B — inline @font-face to Cloudflare-hosted woff2 (used in homepage, agent-sitemap.xsl) -->
<style>
@font-face { font-family: Newsreader; src: url(/cf-fonts/v/newsreader/.../italic.woff2); ... }
</style>
Both produce the same visual outcome. The performance trade-off: - Pattern A (Google Fonts) — easier to maintain, single line, but external request adds DNS + handshake latency - Pattern B (Cloudflare-hosted) — faster (same-origin, edge-cached), but more verbose, depends on Cloudflare Fonts feature being enabled on the zone
Recommendation: standardise on Pattern B (Cloudflare-hosted @font-face) for consistency with the homepage. Migrate main-sitemap.xsl + the 8 article pages over time. NOT urgent — both work today. Worth pinning in a follow-up cleanup pass.
Discovery checklist — for any new isolated-rendering surface
When adding a new XSL stylesheet, email template, Shadow-DOM component, iframe page, or anything-else-rendered-in-isolation, run through this checklist BEFORE shipping:
- Fonts — are all
font-familyreferences backed by an explicit@font-face,<link>, or system-font-only stack? Test in an incognito window (no font cache) - Colors — are all
var(--...)references defined locally in this document’s CSS? Test by deleting one var and confirming the fallback is what you want - Layout fundamentals — is
box-sizing: border-box, the body reset, the viewport meta in place? Don’t assume the surrounding doc has them - Cross-domain resources — does anything reference an external URL that has hotlink protection (image CDNs, font CDNs)? Test with a Referer header that matches production
- Print / dark mode — does the surface need to support
@media printor@media (prefers-color-scheme: dark)? Email clients especially have dark-mode quirks - Browser-render preview — open the file directly in a browser (not in a styled wrapper) before declaring it shipped. If it looks naked, it’s the bug
- Hard-reload verification — after deploy, hard-reload (Cmd+Shift+R or DevTools “Disable cache”) to bypass font/CSS caching
Recommendations + watch items
Immediate
- [x] agent-sitemap.xsl: fixed (Newsreader + cream)
- [x] main-sitemap.xsl: audited, healthy
- [x] dogwood agent-sitemap.xsl: audited, robust by construction
- [x] Worker email templates: audited, email-correct by design
Near-term
- [ ] Standardise font-loading approach. Migrate the 8 article pages + main-sitemap.xsl from Google Fonts
<link>to inline@font-facefor consistency with the homepage pattern. Not urgent - [ ] Add the discovery checklist above to a brief CONTRIBUTING-style doc in
~/Code/dare-co-uk/so it’s at-hand when next adding XSL/email/etc.
Long-term watch
- [ ] When beta.dogwood.house ships: that’s a fresh isolated-rendering context (separate from Squarespace primary). Run the discovery checklist when wiring fonts + colors
- [ ] When audrey gets custom Shopify sections: Liquid templates inherit theme CSS by default, but any apps using Shadow DOM (Loox widget, Judge.me widget if it Shadow-DOMs) need to be tested for visual coherence
- [ ] First time a portfolio site adds RSS / Atom feed: XSL stylesheet for the feed is the same class of bug. Discovery checklist applies
What this earns the portfolio
- A named class of bug (“isolated-rendering inherit trap”) with a discovery protocol, instead of patching each instance ad hoc
- An audited current-state across XSL + email surfaces — no other known regressions hiding
- A documented inconsistency (Google Fonts vs Cloudflare-hosted) with a recommendation to converge — not blocking, but pinned
- A checklist that travels to dogwood, audrey, client work whenever any new isolated-rendering surface gets built
Linked artefacts
feedback_isolated_rendering_inherit_trap— the portable lesson (saved alongside this report)- Commit
22a3ba46—agent-sitemap.xslNewsreader @font-face fix - Commit
29c2dc26—agent-sitemap.xslcream background fix - dare_agent_discoverability_shipped_2026-05-15 — the original ship that surfaced today’s regression
Generated 2026-05-15 after Dan flagged “80% great, lost the 20%” on the live sitemap page. The 20% is now back. The class of bug is named.