diff --git a/NOTICE.md b/NOTICE.md
index 75ea700..210f095 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -8,4 +8,4 @@ The built website uses MathJax 3.2.2 (Apache-2.0) for SVG mathematical typesetti
Python build dependencies retain their own licenses: Mistune (BSD-3-Clause), Jinja2 (BSD-3-Clause), PyYAML (MIT), Pillow (HPND), Beautiful Soup (MIT), and Playwright (Apache-2.0). They are development/build dependencies, not copies of the theory.
-The VDM wordmark is a resized derivative of the author-supplied branding. The small mark and favicon use official VDM branding: the build requests https://www.vdm.io/VDM.png first and can use the official organization's GitHub avatar if that endpoint rejects acquisition. The selected source and digest are recorded, not silently substituted. Brand assets are excluded from the prose and code licenses; no trademark or endorsement rights are granted.
+The VDM Theory wordmark isolates the original blue lettering from the author-supplied branding, removes the mosaic background, and adds matching THEORY lettering on the same baseline. The asset uses source glyph construction, not a separately distributed font. The small mark and favicon use official VDM branding: the build requests https://www.vdm.io/VDM.png first and can use the official organization's GitHub avatar if that endpoint rejects acquisition. The selected source and digest are recorded, not silently substituted. Brand assets are excluded from the prose and code licenses; no trademark or endorsement rights are granted.
diff --git a/tests/test_branding.py b/tests/test_branding.py
new file mode 100644
index 0000000..51e47e8
--- /dev/null
+++ b/tests/test_branding.py
@@ -0,0 +1,53 @@
+"""Source-derived wordmark transparency and responsive placement contracts. MIT."""
+from pathlib import Path
+import unittest
+from bs4 import BeautifulSoup
+from PIL import Image
+
+ROOT = Path(__file__).resolve().parents[1]
+
+
+class WordmarkTests(unittest.TestCase):
+ def test_all_lettering_assets_have_transparent_margins(self):
+ paths = sorted((ROOT / 'web/static/wordmark').glob('*.webp'))
+ self.assertEqual(len(paths), 5)
+ for path in paths:
+ with self.subTest(asset=path.name), Image.open(path) as image:
+ self.assertEqual(image.height, 80)
+ alpha = image.convert('RGBA').getchannel('A')
+ self.assertEqual(alpha.getextrema()[0], 0)
+ self.assertGreaterEqual(alpha.getextrema()[1], 250)
+ self.assertIsNone(alpha.crop((0, 0, image.width, 8)).getbbox())
+ self.assertIsNone(alpha.crop((0, 72, image.width, 80)).getbbox())
+
+ def test_wordmark_has_one_accessible_label_and_no_caption(self):
+ soup = BeautifulSoup((ROOT / 'web/templates/page.html').read_text(), 'html.parser')
+ wordmark = soup.select_one('.wordmark')
+ self.assertIsNotNone(wordmark)
+ root = wordmark.find('svg', recursive=False)
+ self.assertIsNotNone(root)
+ self.assertEqual(root.get('role'), 'img')
+ self.assertEqual(root.find('title').text, 'Vast Development Method Theory')
+ self.assertIsNone(wordmark.find('span'))
+ self.assertEqual(root.get('viewbox'), '0 0 1200 80')
+
+ def test_all_svg_image_references_exist(self):
+ soup = BeautifulSoup((ROOT / 'web/templates/page.html').read_text(), 'html.parser')
+ for image in soup.select('.wordmark image'):
+ href = image.get('href', '')
+ self.assertTrue(href.startswith('/assets/wordmark/'))
+ self.assertTrue((ROOT / 'web/static' / href.removeprefix('/assets/')).is_file())
+
+ def test_glyphs_share_one_baseline(self):
+ soup = BeautifulSoup((ROOT / 'web/templates/page.html').read_text(), 'html.parser')
+ for image in soup.select('.wordmark image'):
+ self.assertEqual(image.get('height'), '80')
+ self.assertIn(image.get('y'), (None, '0'))
+
+ def test_wordmark_styles_are_scoped_and_loaded_after_the_theme(self):
+ css = (ROOT / 'web/static/wordmark.css').read_text()
+ for declaration in ('width: 100%', 'max-width: none', 'background: transparent', 'border: 0', 'padding: 0'):
+ self.assertIn(declaration, css)
+ soup = BeautifulSoup((ROOT / 'web/templates/page.html').read_text(), 'html.parser')
+ sheets = [node.get('href') for node in soup.select('link[rel="stylesheet"]')]
+ self.assertGreater(sheets.index('/assets/wordmark.css'), sheets.index('/assets/site.css'))
diff --git a/web/static/BRAND-NOTICE.txt b/web/static/BRAND-NOTICE.txt
index 07b6683..d264d29 100644
--- a/web/static/BRAND-NOTICE.txt
+++ b/web/static/BRAND-NOTICE.txt
@@ -1,6 +1,10 @@
VDM branding identifies this official Vast Development Method publication.
-wordmark.webp is a resized derivative of vast_development_method.jpg supplied
-by the publication's originator.
+The wordmark/ assets isolate blue lettering from the originator-supplied
+vast_development_method.jpg. The homepage composes them into one accessible,
+transparent, single-line SVG wordmark: VAST DEVELOPMENT METHOD THEORY.
+Existing letter shapes are reused; the R and Y extend the source construction.
+There is no separately loaded font, no mosaic backdrop, and no detached caption.
+The SVG is a layout for raster lettering; it is not represented as a vector font.
The small mark and favicon are derived from official VDM branding. The build
first requests https://www.vdm.io/VDM.png. When that endpoint rejects automated
diff --git a/web/static/wordmark.css b/web/static/wordmark.css
new file mode 100644
index 0000000..80f6ae7
--- /dev/null
+++ b/web/static/wordmark.css
@@ -0,0 +1,16 @@
+/* Source-lettering wordmark only; the publication theme is unchanged. */
+.wordmark {
+ display: block;
+ width: 100%;
+ max-width: none;
+ margin: 4px 0 28px;
+ padding: 0;
+ border: 0;
+ border-radius: 0;
+ background: transparent;
+}
+.wordmark > svg {
+ display: block;
+ width: 100%;
+ height: auto;
+}
diff --git a/web/static/wordmark.webp b/web/static/wordmark.webp
deleted file mode 100644
index d96dd18..0000000
Binary files a/web/static/wordmark.webp and /dev/null differ
diff --git a/web/static/wordmark/development.webp b/web/static/wordmark/development.webp
new file mode 100644
index 0000000..df38c23
Binary files /dev/null and b/web/static/wordmark/development.webp differ
diff --git a/web/static/wordmark/h.webp b/web/static/wordmark/h.webp
new file mode 100644
index 0000000..93eb0b1
Binary files /dev/null and b/web/static/wordmark/h.webp differ
diff --git a/web/static/wordmark/r.webp b/web/static/wordmark/r.webp
new file mode 100644
index 0000000..5a16fe5
Binary files /dev/null and b/web/static/wordmark/r.webp differ
diff --git a/web/static/wordmark/vast.webp b/web/static/wordmark/vast.webp
new file mode 100644
index 0000000..b00f686
Binary files /dev/null and b/web/static/wordmark/vast.webp differ
diff --git a/web/static/wordmark/y.webp b/web/static/wordmark/y.webp
new file mode 100644
index 0000000..7c64cc2
Binary files /dev/null and b/web/static/wordmark/y.webp differ
diff --git a/web/templates/page.html b/web/templates/page.html
index b285ba5..3ead0f9 100644
--- a/web/templates/page.html
+++ b/web/templates/page.html
@@ -22,6 +22,7 @@
window.MathJax = {tex:{inlineMath:[['\\(','\\)']],displayMath:[['$$','$$']],processEscapes:true},svg:{fontCache:'global'},options:{skipHtmlTags:['script','noscript','style','textarea','pre','code']}};
+
@@ -50,7 +51,25 @@