diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f73b626..45c4c34 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,6 +26,9 @@ jobs:
with:
python-version: "3.11"
+ - name: Verify accessible SVG contract
+ run: python3 scripts/test-lint-a11y.py
+
- name: Run skin linter
run: python3 scripts/lint-skin.py --all --baseline
diff --git a/README.md b/README.md
index fb0acc0..c56e453 100644
--- a/README.md
+++ b/README.md
@@ -166,6 +166,10 @@ Every new diagram now uses your colors. Your website's paper color becomes the d
Before writing tokens, the skill verifies WCAG AA contrast on `ink` over `paper`. If your site has a color that fails contrast at diagram sizes (9–12px), it proposes an adjusted value and explains why.
+### Accessible by default
+
+Every diagram template gives the inline SVG an accessible name and description: `role="img"`, a resolving `aria-labelledby`, and first-child `
` / `` slots. IDs are prefixed per diagram and variant, so multiple SVG exports can be safely inlined on one page without duplicate accessible-name IDs. Decorative specimen icons are hidden from assistive technology instead.
+
### Manual override
Prefer to set tokens by hand? Open [`skills/diagram-design/references/style-guide.md`](skills/diagram-design/references/style-guide.md) and edit the table. Everything downstream reads from there — all 27 diagrams, the annotation primitive, and the gallery all inherit semantic role names (`accent`, not `#eb6c36`).
@@ -336,6 +340,8 @@ This keeps the agent's working context tight (only load what you need) and makes
Before submitting a new example, run `python3 scripts/lint-skin.py `.
The repository-wide check `python3 scripts/lint-skin.py --all --baseline` must stay green.
+The linter's `a11y` category rejects diagram SVGs without a resolving accessible name,
+an empty or misplaced title/description, or unsafe bare `title` / `desc` IDs.
If you touch the draw.io import path, `python3 scripts/verify-drawio-import.py` must also pass —
it drives the real extractor against `scripts/fixtures/sample-architecture.drawio` in all four
container formats and checks the references stay in sync.
diff --git a/scripts/build-icons.py b/scripts/build-icons.py
index 1da01fc..b191b2a 100644
--- a/scripts/build-icons.py
+++ b/scripts/build-icons.py
@@ -218,7 +218,7 @@ def normalize_tabler(raw: str) -> str:
body = re.sub(r' ', "", body)
body = re.sub(r"\s+", " ", body).strip()
return (
- '{body} '
)
@@ -232,7 +232,7 @@ def normalize_simple(raw: str) -> str:
body = inner.group(1).strip()
body = re.sub(r"\s+", " ", body).strip()
return (
- '{body} '
)
@@ -284,7 +284,7 @@ def normalize_url(raw: str) -> str:
body = re.sub(r'\bfill="none"', '', body)
body = re.sub(r"\s+", " ", body).strip()
return (
- f'{body} '
)
@@ -303,7 +303,7 @@ def normalize_devicon(raw: str) -> str:
body = re.sub(r'\bclass="[^"]*"', 'fill="currentColor"', body)
body = re.sub(r"\s+", " ", body).strip()
return (
- '{body} '
)
@@ -320,7 +320,7 @@ def normalize_logz(raw: str) -> str:
body = re.sub(r'\bfill="#[0-9a-fA-F]{3,8}"', 'fill="currentColor"', body)
body = re.sub(r"\s+", " ", body).strip()
return (
- '{body} '
)
diff --git a/scripts/lint-skin.py b/scripts/lint-skin.py
index 1662501..c2c3154 100644
--- a/scripts/lint-skin.py
+++ b/scripts/lint-skin.py
@@ -8,6 +8,8 @@ skin. Use ``--all --baseline`` to skip those documented legacy files.
import argparse
import re
import sys
+from dataclasses import dataclass, field
+from html.parser import HTMLParser
from pathlib import Path
@@ -50,6 +52,244 @@ ALLOWED_FONTS = {
CSS_FONT_KEYWORDS = {"inherit", "initial", "revert", "revert-layer", "unset"}
+@dataclass
+class SvgTextElement:
+ tag: str
+ element_id: str | None
+ line: int
+ offset: int
+ text: list[str] = field(default_factory=list)
+
+
+@dataclass
+class SvgElement:
+ attrs: dict[str, str | None]
+ line: int
+ offset: int
+ content_depth: int
+ first_child: str | None = None
+ ids: set[str] = field(default_factory=set)
+ bare_id_locations: list[tuple[int, int]] = field(default_factory=list)
+ titles: list[SvgTextElement] = field(default_factory=list)
+ descriptions: list[SvgTextElement] = field(default_factory=list)
+
+
+class AccessibleSvgParser(HTMLParser):
+ """Collect accessible-name data without rendering or executing HTML.
+
+ Trust boundary: input files are untrusted source text. ``HTMLParser`` only
+ tokenizes that text; this linter never evaluates scripts, fetches URLs, or
+ opens referenced resources.
+ """
+
+ def __init__(self, text):
+ super().__init__(convert_charrefs=True)
+ self.line_offsets = [0]
+ self.line_offsets.extend(
+ match.end() for match in re.finditer(r"\n", text)
+ )
+ self.element_stack = []
+ self.svg_stack = []
+ self.svgs = []
+ self.open_text = []
+ self.id_locations = {}
+
+ def source_offset(self):
+ line, column = self.getpos()
+ return self.line_offsets[line - 1] + column
+
+ def handle_starttag(self, tag, attrs):
+ tag = tag.casefold()
+ attr_map = {name.casefold(): value for name, value in attrs}
+ offset = self.source_offset()
+ line, _column = self.getpos()
+ element_id = attr_map.get("id")
+ if element_id:
+ self.id_locations.setdefault(element_id, []).append((line, offset))
+
+ if self.svg_stack:
+ parent = self.svg_stack[-1]
+ if len(self.element_stack) == parent.content_depth:
+ if parent.first_child is None:
+ parent.first_child = tag
+ if element_id:
+ for svg in self.svg_stack:
+ svg.ids.add(element_id)
+ if element_id in {"title", "desc"}:
+ svg.bare_id_locations.append((line, offset))
+
+ if tag == "svg":
+ svg = SvgElement(
+ attrs=attr_map,
+ line=line,
+ offset=offset,
+ content_depth=len(self.element_stack) + 1,
+ )
+ self.svgs.append(svg)
+ self.svg_stack.append(svg)
+ elif tag in {"title", "desc"} and self.svg_stack:
+ svg = self.svg_stack[-1]
+ if len(self.element_stack) == svg.content_depth:
+ element = SvgTextElement(
+ tag=tag,
+ element_id=attr_map.get("id"),
+ line=line,
+ offset=offset,
+ )
+ if tag == "title":
+ svg.titles.append(element)
+ else:
+ svg.descriptions.append(element)
+ self.open_text.append(element)
+
+ self.element_stack.append(tag)
+
+ def handle_startendtag(self, tag, attrs):
+ self.handle_starttag(tag, attrs)
+ self.handle_endtag(tag)
+
+ def handle_endtag(self, tag):
+ tag = tag.casefold()
+ for index in range(len(self.open_text) - 1, -1, -1):
+ if self.open_text[index].tag == tag:
+ del self.open_text[index]
+ break
+
+ if tag == "svg" and self.svg_stack:
+ self.svg_stack.pop()
+
+ for index in range(len(self.element_stack) - 1, -1, -1):
+ if self.element_stack[index] == tag:
+ del self.element_stack[index:]
+ break
+
+ def handle_data(self, data):
+ for element in self.open_text:
+ element.text.append(data)
+
+
+def lint_accessible_svgs(text, expected_slug):
+ parser = AccessibleSvgParser(text)
+ parser.feed(text)
+ parser.close()
+ findings = []
+
+ def add(line, offset, message):
+ findings.append((line, offset, "a11y", message))
+
+ naming_ids = {
+ element.element_id
+ for svg in parser.svgs
+ if (svg.attrs.get("aria-hidden") or "").casefold() != "true"
+ for element in svg.titles + svg.descriptions
+ if element.element_id
+ }
+ for element_id in sorted(naming_ids):
+ locations = parser.id_locations[element_id]
+ if len(locations) > 1:
+ line, offset = locations[1]
+ add(line, offset, f'duplicate accessible-name id="{element_id}" is not allowed')
+
+ for svg in parser.svgs:
+ aria_hidden = (svg.attrs.get("aria-hidden") or "").casefold()
+ if aria_hidden == "true":
+ continue
+
+ if (svg.attrs.get("role") or "").casefold() != "img":
+ add(svg.line, svg.offset, 'diagram must carry role="img"')
+
+ labelled_by = (svg.attrs.get("aria-labelledby") or "").split()
+ accessible_name_ids = labelled_by + [
+ element.element_id
+ for element in svg.titles + svg.descriptions
+ if element.element_id
+ ]
+ placeholder_ids = list(
+ dict.fromkeys(
+ element_id
+ for element_id in accessible_name_ids
+ if "[" in element_id or "]" in element_id
+ )
+ )
+ if placeholder_ids:
+ add(
+ svg.line,
+ svg.offset,
+ "accessible-name IDs contain unresolved placeholder(s): "
+ + ", ".join(placeholder_ids),
+ )
+ if not labelled_by:
+ add(
+ svg.line,
+ svg.offset,
+ "aria-labelledby must name the and ",
+ )
+ else:
+ missing_ids = [
+ element_id for element_id in labelled_by if element_id not in svg.ids
+ ]
+ if missing_ids:
+ add(
+ svg.line,
+ svg.offset,
+ "aria-labelledby references missing id(s): "
+ + ", ".join(missing_ids),
+ )
+
+ title = svg.titles[0] if svg.titles else None
+ description = svg.descriptions[0] if svg.descriptions else None
+ if title is None:
+ add(svg.line, svg.offset, "diagram must contain a ")
+ else:
+ if svg.first_child != "title":
+ add(
+ title.line,
+ title.offset,
+ " must be the first child element of ",
+ )
+ if not "".join(title.text).strip():
+ add(title.line, title.offset, " must not be empty")
+
+ if description is None:
+ add(svg.line, svg.offset, "diagram must contain a ")
+ elif not "".join(description.text).strip():
+ add(description.line, description.offset, " must not be empty")
+
+ title_id = title.element_id if title else None
+ description_id = description.element_id if description else None
+ if svg.bare_id_locations:
+ line, offset = svg.bare_id_locations[0]
+ add(
+ line,
+ offset,
+ 'bare id="title" and id="desc" are not allowed',
+ )
+
+ expected_title_id = f"{expected_slug}-title"
+ expected_description_id = f"{expected_slug}-desc"
+ if not placeholder_ids and (
+ title_id != expected_title_id or description_id != expected_description_id
+ ):
+ add(
+ svg.line,
+ svg.offset,
+ f'accessible-name IDs must match file slug "{expected_slug}": '
+ f'expected "{expected_title_id}" / "{expected_description_id}"',
+ )
+
+ if (
+ labelled_by
+ and (title_id not in labelled_by or description_id not in labelled_by)
+ ):
+ add(
+ svg.line,
+ svg.offset,
+ "aria-labelledby must name the and IDs",
+ )
+
+ return findings
+
+
def normalize_hex(value):
value = value.lower()
if len(value) == 4:
@@ -102,6 +342,10 @@ def display_path(path):
return str(path)
+def diagram_slug(path):
+ return path.stem.removeprefix("example-")
+
+
def named_families(value):
families = []
for raw_family in value.split(","):
@@ -114,8 +358,8 @@ def named_families(value):
return families
-def lint_text(text, colors, rgb_triplets):
- findings = []
+def lint_text(text, colors, rgb_triplets, expected_slug):
+ findings = lint_accessible_svgs(text, expected_slug)
def add(offset, category, message):
findings.append((line_number(text, offset), offset, category, message))
@@ -228,18 +472,15 @@ def main():
colors, rgb_triplets = allowed_colors()
skipped = 0
+ baseline = set()
if args.all:
paths = sorted(ASSET_DIR.glob("example-*.html"))
if args.baseline:
baseline = load_baseline()
- selected = []
for path in paths:
relative = display_path(path)
if path.name in baseline or relative in baseline:
skipped += 1
- else:
- selected.append(path)
- paths = selected
else:
paths = args.files
@@ -247,7 +488,12 @@ def main():
for path in paths:
try:
text = path.read_text(encoding="utf-8")
- findings = lint_text(text, colors, rgb_triplets)
+ relative = display_path(path)
+ expected_slug = diagram_slug(path)
+ if args.baseline and (path.name in baseline or relative in baseline):
+ findings = lint_accessible_svgs(text, expected_slug)
+ else:
+ findings = lint_text(text, colors, rgb_triplets, expected_slug)
except OSError as error:
findings = [(0, 0, "read-error", str(error))]
diff --git a/scripts/test-lint-a11y.py b/scripts/test-lint-a11y.py
new file mode 100644
index 0000000..e7a7e4b
--- /dev/null
+++ b/scripts/test-lint-a11y.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python3
+"""Adversarial tests for lint-skin.py's accessible-SVG contract."""
+
+from __future__ import annotations
+
+import importlib.util
+import shutil
+import subprocess
+import sys
+import tempfile
+from pathlib import Path
+
+
+ROOT = Path(__file__).resolve().parent.parent
+LINTER = ROOT / "scripts/lint-skin.py"
+BUILD_ICONS = ROOT / "scripts/build-icons.py"
+
+VALID_SVG = """\
+
+ Fixture diagram
+ Diagram showing a fixture connected to a result.
+
+
+"""
+
+
+def run_linter(path: Path) -> subprocess.CompletedProcess[str]:
+ return subprocess.run(
+ [sys.executable, str(LINTER), str(path)],
+ capture_output=True,
+ text=True,
+ check=False,
+ )
+
+
+def require_failure(name: str, html: str, expected: str, directory: Path) -> None:
+ path = directory / f"{name}.html"
+ path.write_text(html, encoding="utf-8")
+ result = run_linter(path)
+ if result.returncode != 1:
+ raise AssertionError(
+ f"{name}: expected exit 1, got {result.returncode}\n{result.stdout}{result.stderr}"
+ )
+ if f"a11y: {expected}" not in result.stdout:
+ raise AssertionError(
+ f"{name}: missing expected a11y finding {expected!r}\n{result.stdout}"
+ )
+ print(f"OK: {name} rejected — {expected}")
+
+
+def require_pass(name: str, html: str, directory: Path) -> None:
+ path = directory / f"{name}.html"
+ path.write_text(html, encoding="utf-8")
+ result = run_linter(path)
+ if result.returncode != 0:
+ raise AssertionError(
+ f"{name}: expected exit 0, got {result.returncode}\n{result.stdout}{result.stderr}"
+ )
+ if "a11y:" in result.stdout:
+ raise AssertionError(f"{name}: unexpected a11y finding\n{result.stdout}")
+ print(f"OK: {name} accepted")
+
+
+def main() -> int:
+ with tempfile.TemporaryDirectory(prefix="lint-a11y-") as temp_dir:
+ directory = Path(temp_dir)
+
+ require_failure(
+ "missing-role",
+ VALID_SVG.replace(' role="img"', ""),
+ 'diagram must carry role="img"',
+ directory,
+ )
+ require_failure(
+ "unresolved-labelled-by",
+ VALID_SVG.replace(
+ 'aria-labelledby="fixture-title fixture-desc"',
+ 'aria-labelledby="absent-title absent-desc"',
+ ),
+ "aria-labelledby references missing id(s): absent-title, absent-desc",
+ directory,
+ )
+ require_failure(
+ "labels-unrelated-elements",
+ VALID_SVG.replace(' id="fixture-title"', "")
+ .replace(' id="fixture-desc"', "")
+ .replace(
+ ' ',
+ ' \n'
+ ' \n'
+ ' ',
+ ),
+ "aria-labelledby must name the and IDs",
+ directory,
+ )
+ require_failure(
+ "late-title",
+ VALID_SVG.replace(
+ ' Fixture diagram \n \n Fixture diagram \n must be the first child element of ",
+ directory,
+ )
+ require_failure(
+ "empty-desc",
+ VALID_SVG.replace(
+ "Diagram showing a fixture connected to a result.", " "
+ ),
+ " must not be empty",
+ directory,
+ )
+ require_failure(
+ "bare-ids",
+ VALID_SVG.replace("fixture-title", "title").replace(
+ "fixture-desc", "desc"
+ ),
+ 'bare id="title" and id="desc" are not allowed',
+ directory,
+ )
+ require_failure(
+ "wrong-file-slug",
+ VALID_SVG,
+ 'accessible-name IDs must match file slug "wrong-file-slug": '
+ 'expected "wrong-file-slug-title" / "wrong-file-slug-desc"',
+ directory,
+ )
+ require_failure(
+ "placeholder-ids",
+ VALID_SVG.replace("fixture-title", "[diagram-slug]-title").replace(
+ "fixture-desc", "[diagram-slug]-desc"
+ ),
+ "accessible-name IDs contain unresolved placeholder(s): "
+ "[diagram-slug]-title, [diagram-slug]-desc",
+ directory,
+ )
+ require_failure(
+ "duplicate-naming-ids",
+ VALID_SVG + VALID_SVG,
+ 'duplicate accessible-name id="fixture-desc" is not allowed',
+ directory,
+ )
+ require_pass(
+ "decorative",
+ ''
+ ' \n',
+ directory,
+ )
+
+ spec = importlib.util.spec_from_file_location("build_icons", BUILD_ICONS)
+ if spec is None or spec.loader is None:
+ raise AssertionError("generated-icons: could not load build-icons.py")
+ build_icons = importlib.util.module_from_spec(spec)
+ previous_bytecode_setting = sys.dont_write_bytecode
+ sys.dont_write_bytecode = True
+ try:
+ spec.loader.exec_module(build_icons)
+ finally:
+ sys.dont_write_bytecode = previous_bytecode_setting
+ generated_icons = {
+ "tabler": build_icons.normalize_tabler(" "),
+ "simple": build_icons.normalize_simple(" "),
+ "url": build_icons.normalize_url(
+ ' '
+ ),
+ "devicon": build_icons.normalize_devicon(" "),
+ "logz": build_icons.normalize_logz(" "),
+ }
+ for source, icon in generated_icons.items():
+ slug = f"generated-{source}-icon"
+ require_pass(
+ slug,
+ VALID_SVG.replace("fixture-title", f"{slug}-title")
+ .replace("fixture-desc", f"{slug}-desc")
+ .replace(" ", f" {icon}\n "),
+ directory,
+ )
+
+ project = directory / "baseline-project"
+ (project / "scripts").mkdir(parents=True)
+ (project / "skills/diagram-design/assets").mkdir(parents=True)
+ (project / "skills/diagram-design/references").mkdir(parents=True)
+ shutil.copy2(LINTER, project / "scripts/lint-skin.py")
+ shutil.copy2(
+ ROOT / "skills/diagram-design/references/style-guide.md",
+ project / "skills/diagram-design/references/style-guide.md",
+ )
+ (project / "scripts/lint-skin-baseline.txt").write_text(
+ "example-baseline.html\n", encoding="utf-8"
+ )
+ (project / "skills/diagram-design/assets/example-baseline.html").write_text(
+ ' \n', encoding="utf-8"
+ )
+ baseline_result = subprocess.run(
+ [
+ sys.executable,
+ str(project / "scripts/lint-skin.py"),
+ "--all",
+ "--baseline",
+ ],
+ capture_output=True,
+ text=True,
+ check=False,
+ )
+ if baseline_result.returncode != 1:
+ raise AssertionError(
+ "baseline-a11y: expected exit 1, got "
+ f"{baseline_result.returncode}\n"
+ f"{baseline_result.stdout}{baseline_result.stderr}"
+ )
+ if "a11y: diagram must carry role=\"img\"" not in baseline_result.stdout:
+ raise AssertionError(
+ "baseline-a11y: missing expected accessibility finding\n"
+ f"{baseline_result.stdout}"
+ )
+ if "color:" in baseline_result.stdout:
+ raise AssertionError(
+ "baseline-a11y: legacy visual finding was not exempted\n"
+ f"{baseline_result.stdout}"
+ )
+ print("OK: baseline file receives a11y checks but keeps visual exemptions")
+
+ print("All accessible-SVG lint cases passed.")
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/skills/diagram-design/SKILL.md b/skills/diagram-design/SKILL.md
index ca6f8b1..13fa9c0 100644
--- a/skills/diagram-design/SKILL.md
+++ b/skills/diagram-design/SKILL.md
@@ -429,6 +429,9 @@ Run before producing any diagram.
**Technical:**
+- [ ] Diagram `` has `role="img"` and `aria-labelledby` resolving to its `` and ``?
+- [ ] `` is the first child of `` (before ``) and both `` and `` are filled in?
+- [ ] `` / `` IDs are prefixed for this diagram and variant — never bare `title` / `desc`?
- [ ] Arrows drawn before boxes?
- [ ] **Every connector between off-axis nodes uses a rounded right-angle elbow (`r=8`)? No diagonal `` slants?**
- [ ] **Every arrow label has a visible 6–10px gap above its connector? (Mask rect not touching the stroke.)**
@@ -470,7 +473,7 @@ Every diagram ships in three variants (see `assets/`):
1. Copy the variant closest to what you want (`template.html` for minimal, `template-full.html` for cards).
2. Load the matching `references/type-.md` for layout conventions.
-3. Replace the eyebrow, h1, and SVG body.
+3. Replace the eyebrow, h1, and SVG body. Replace `[diagram-slug]` with the file's diagram/variant slug, fill the copied `` / `` placeholders, and do not delete them.
4. Run the §9 taste gate.
---
@@ -516,6 +519,17 @@ Always produce a single self-contained `.html` file:
Renders correctly in any modern browser.
+### Accessible SVG contract
+
+Every diagram is an accessible figure by default:
+
+1. Its `` carries `role="img"` and `aria-labelledby` naming the diagram's `` and ``.
+2. `` is the first child of ``, before ``. Assistive technology may ignore a title placed later.
+3. The IDs are prefixed per diagram and variant: `-title` / `-desc`, where the slug matches the file (`loop`, `loop-dark`, `loop-full`). Bare `title` / `desc` IDs are banned because two inline diagrams would create duplicate IDs and the second could be announced with the first diagram's name.
+4. `` is the short name of the subject — roughly the page ``, and about 60 characters or fewer.
+5. `` is one sentence stating what the diagram shows in terms a reader needs without the image. Describe the content, not the geometry: “Org chart showing a command center routing work to specialist agents and escalation owners,” not “A box at the top with five boxes below it.” A shape-by-shape narration is worse than no useful description.
+6. Decorative-only SVG, such as the specimen glyphs in `assets/icons.html`, carries `aria-hidden="true"` instead. Giving decorative marks accessible names adds noise.
+
### Exporting to PNG / SVG
When the user asks to export, save, rasterize, or convert a generated diagram to `.png` or `.svg`, load [`references/export.md`](references/export.md) and follow the procedure there. Both formats deliver the diagram only (the `` node) — editorial wrappers like cards and headers are dropped by design. Export is **manual** — never produce export files unprompted.
diff --git a/skills/diagram-design/assets/example-architecture-dark.html b/skills/diagram-design/assets/example-architecture-dark.html
index 186d97a..ad3e4fa 100644
--- a/skills/diagram-design/assets/example-architecture-dark.html
+++ b/skills/diagram-design/assets/example-architecture-dark.html
@@ -58,7 +58,9 @@
Architecture · Diagram Design
Content site in production
-
+
+ Content site in production
+ Architecture diagram showing reader requests moving through Cloudflare to an Astro origin, MDX bundle, and content CMS.
diff --git a/skills/diagram-design/assets/example-architecture-full.html b/skills/diagram-design/assets/example-architecture-full.html
index 6b89738..2ed4663 100644
--- a/skills/diagram-design/assets/example-architecture-full.html
+++ b/skills/diagram-design/assets/example-architecture-full.html
@@ -48,7 +48,9 @@
-
+
+ Content site in production
+ Architecture diagram showing reader requests moving through Cloudflare to an Astro origin, MDX bundle, and content CMS.
diff --git a/skills/diagram-design/assets/example-architecture.html b/skills/diagram-design/assets/example-architecture.html
index 506a625..5f3e5e3 100644
--- a/skills/diagram-design/assets/example-architecture.html
+++ b/skills/diagram-design/assets/example-architecture.html
@@ -58,7 +58,9 @@
Architecture · Diagram Design
Content site in production
-
+
+ Content site in production
+ Architecture diagram showing reader requests moving through Cloudflare to an Astro origin, MDX bundle, and content CMS.
diff --git a/skills/diagram-design/assets/example-bar-dark.html b/skills/diagram-design/assets/example-bar-dark.html
index b140ef4..0d9aa66 100644
--- a/skills/diagram-design/assets/example-bar-dark.html
+++ b/skills/diagram-design/assets/example-bar-dark.html
@@ -28,7 +28,9 @@
Bar · Diagram Design
Sprint velocity · 8-sprint view
-
+
+ Sprint velocity · 8-sprint view
+ Bar chart showing story points delivered across sprints S1 through S8, with Sprint 5 as the record high.
diff --git a/skills/diagram-design/assets/example-bar-full.html b/skills/diagram-design/assets/example-bar-full.html
index 1763d82..04b7663 100644
--- a/skills/diagram-design/assets/example-bar-full.html
+++ b/skills/diagram-design/assets/example-bar-full.html
@@ -36,7 +36,9 @@
Story points delivered per two-week sprint over one product cycle. Sprint 5 is the standout — a focused scope and no mid-sprint scope additions.
-
+
+ Sprint velocity · 8-sprint view
+ Bar chart showing story points delivered across sprints S1 through S8, with Sprint 5 as the record high.
diff --git a/skills/diagram-design/assets/example-bar.html b/skills/diagram-design/assets/example-bar.html
index 3e08381..3c440f0 100644
--- a/skills/diagram-design/assets/example-bar.html
+++ b/skills/diagram-design/assets/example-bar.html
@@ -28,7 +28,9 @@
Bar · Diagram Design
Sprint velocity · 8-sprint view
-
+
+ Sprint velocity · 8-sprint view
+ Bar chart showing story points delivered across sprints S1 through S8, with Sprint 5 as the record high.
diff --git a/skills/diagram-design/assets/example-data-flow-dark.html b/skills/diagram-design/assets/example-data-flow-dark.html
index 87d3801..cd0ab3e 100644
--- a/skills/diagram-design/assets/example-data-flow-dark.html
+++ b/skills/diagram-design/assets/example-data-flow-dark.html
@@ -38,9 +38,9 @@
Data flow · Diagram Design
Role-scoped analytics pipeline
-
- Role-scoped analytics data flow
- A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.
+
+ Role-scoped analytics data flow
+ A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.
diff --git a/skills/diagram-design/assets/example-data-flow-full.html b/skills/diagram-design/assets/example-data-flow-full.html
index 88da459..194dbf1 100644
--- a/skills/diagram-design/assets/example-data-flow-full.html
+++ b/skills/diagram-design/assets/example-data-flow-full.html
@@ -58,9 +58,9 @@
-
- Role-scoped analytics data flow
- A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.
+
+ Role-scoped analytics data flow
+ A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.
diff --git a/skills/diagram-design/assets/example-data-flow.html b/skills/diagram-design/assets/example-data-flow.html
index f8f2b75..1be90d4 100644
--- a/skills/diagram-design/assets/example-data-flow.html
+++ b/skills/diagram-design/assets/example-data-flow.html
@@ -38,9 +38,9 @@
Data flow · Diagram Design
Role-scoped analytics pipeline
-
- Role-scoped analytics data flow
- A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.
+
+ Role-scoped analytics data flow
+ A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.
diff --git a/skills/diagram-design/assets/example-datalake-dark.html b/skills/diagram-design/assets/example-datalake-dark.html
index 137974d..efb017a 100644
--- a/skills/diagram-design/assets/example-datalake-dark.html
+++ b/skills/diagram-design/assets/example-datalake-dark.html
@@ -52,7 +52,9 @@
Architecture · Diagram Design
Open data lake · End-to-end stack
-
+
+ Open data lake · End-to-end stack
+ Data lake architecture showing app servers and databases flowing through Apache NiFi into MinIO, then Trino, StarRocks, Superset, JupyterLab, and Python.
@@ -106,7 +108,7 @@
EXT
-
+
@@ -119,7 +121,7 @@
EXT
-
+
@@ -132,7 +134,7 @@
FLOW
-
+
Apache NiFi
@@ -143,7 +145,7 @@
ORCH
-
+
Airflow
@@ -154,7 +156,7 @@
STORE
-
+
MinIO
@@ -165,7 +167,7 @@
QUERY
-
+
Trino
@@ -176,7 +178,7 @@
OLAP
-
+
@@ -190,7 +192,7 @@
BI
-
+
Superset
@@ -201,7 +203,7 @@
NB
-
+
JupyterLab
@@ -212,7 +214,7 @@
PROC
-
+
Python
diff --git a/skills/diagram-design/assets/example-datalake-full.html b/skills/diagram-design/assets/example-datalake-full.html
index 85608d0..2bfd388 100644
--- a/skills/diagram-design/assets/example-datalake-full.html
+++ b/skills/diagram-design/assets/example-datalake-full.html
@@ -43,7 +43,9 @@
-
+
+ Open data lake · End-to-end stack
+ Data lake architecture showing app servers and databases flowing through Apache NiFi into MinIO, then Trino, StarRocks, Superset, JupyterLab, and Python.
@@ -91,7 +93,7 @@
EXT
-
+
@@ -103,7 +105,7 @@
EXT
-
+
@@ -115,7 +117,7 @@
FLOW
-
+
Apache NiFi
@@ -125,7 +127,7 @@
ORCH
-
+
Airflow
@@ -135,7 +137,7 @@
STORE
-
+
MinIO
@@ -145,7 +147,7 @@
QUERY
-
+
Trino
@@ -155,7 +157,7 @@
OLAP
-
+
@@ -168,7 +170,7 @@
BI
-
+
Superset
@@ -178,7 +180,7 @@
NB
-
+
JupyterLab
@@ -188,7 +190,7 @@
PROC
-
+
Python
diff --git a/skills/diagram-design/assets/example-datalake.html b/skills/diagram-design/assets/example-datalake.html
index 9c1e268..7f60989 100644
--- a/skills/diagram-design/assets/example-datalake.html
+++ b/skills/diagram-design/assets/example-datalake.html
@@ -52,7 +52,9 @@
Architecture · Diagram Design
Open data lake · End-to-end stack
-
+
+ Open data lake · End-to-end stack
+ Data lake architecture showing app servers and databases flowing through Apache NiFi into MinIO, then Trino, StarRocks, Superset, JupyterLab, and Python.
@@ -129,7 +131,7 @@
EXT
-
+
@@ -142,7 +144,7 @@
EXT
-
+
@@ -155,7 +157,7 @@
FLOW
-
+
Apache NiFi
@@ -166,7 +168,7 @@
ORCH
-
+
Airflow
@@ -177,7 +179,7 @@
STORE
-
+
MinIO
@@ -188,7 +190,7 @@
QUERY
-
+
Trino
@@ -199,7 +201,7 @@
OLAP
-
+
@@ -213,7 +215,7 @@
BI
-
+
Superset
@@ -224,7 +226,7 @@
NB
-
+
JupyterLab
@@ -235,7 +237,7 @@
PROC
-
+
Python
diff --git a/skills/diagram-design/assets/example-dp-integration-dark.html b/skills/diagram-design/assets/example-dp-integration-dark.html
index 2247257..e6cf2b0 100644
--- a/skills/diagram-design/assets/example-dp-integration-dark.html
+++ b/skills/diagram-design/assets/example-dp-integration-dark.html
@@ -15,7 +15,9 @@
DP Integration · Diagram Design
Generic data platform integration topology
-
+
+ Generic data platform integration topology
+ Integration topology showing CRM, POS exports, and an event stream landing in object storage for query, notebooks, dashboards, and a partner API.
diff --git a/skills/diagram-design/assets/example-dp-integration-full.html b/skills/diagram-design/assets/example-dp-integration-full.html
index 8f2e3db..50218f1 100644
--- a/skills/diagram-design/assets/example-dp-integration-full.html
+++ b/skills/diagram-design/assets/example-dp-integration-full.html
@@ -18,7 +18,9 @@
Generic data platform integration topology
Three source patterns land in shared object storage, a query surface serves three consumer modes, and platform-wide services remain visibly cross-cutting.
-
+
+ Generic data platform integration topology
+ Integration topology showing CRM, POS exports, and an event stream landing in object storage for query, notebooks, dashboards, and a partner API.
diff --git a/skills/diagram-design/assets/example-dp-integration.html b/skills/diagram-design/assets/example-dp-integration.html
index 1e3b1be..62d2830 100644
--- a/skills/diagram-design/assets/example-dp-integration.html
+++ b/skills/diagram-design/assets/example-dp-integration.html
@@ -15,7 +15,9 @@
DP Integration · Diagram Design
Generic data platform integration topology
-
+
+ Generic data platform integration topology
+ Integration topology showing CRM, POS exports, and an event stream landing in object storage for query, notebooks, dashboards, and a partner API.
diff --git a/skills/diagram-design/assets/example-dp-security-matrix-dark.html b/skills/diagram-design/assets/example-dp-security-matrix-dark.html
index bf56ebc..670b439 100644
--- a/skills/diagram-design/assets/example-dp-security-matrix-dark.html
+++ b/skills/diagram-design/assets/example-dp-security-matrix-dark.html
@@ -16,8 +16,8 @@
DP security matrix · Diagram Design
Data platform access matrix Five operating roles × five platform components, expressed as admin, write, read, or none.
-
- Data platform access matrix A five by five permission matrix for platform roles and components.
+
+ Data platform access matrix A five by five permission matrix for platform roles and components.
Component vs. AD group
Data Engineer GRP-DATA-ENG Data Scientist GRP-DATA-SCI Analyst GRP-ANALYST Administrator GRP-ADMIN External Partner GRP-PARTNER
Object storage S3 Write Read None Admin None
diff --git a/skills/diagram-design/assets/example-dp-security-matrix-full.html b/skills/diagram-design/assets/example-dp-security-matrix-full.html
index c84f82e..9b9abc2 100644
--- a/skills/diagram-design/assets/example-dp-security-matrix-full.html
+++ b/skills/diagram-design/assets/example-dp-security-matrix-full.html
@@ -14,8 +14,8 @@
-
- Data platform access matrix A five by five permission matrix for platform roles and components.
+
+ Data platform access matrix A five by five permission matrix for platform roles and components.
Component vs. AD group
Data Engineer GRP-DATA-ENG Data Scientist GRP-DATA-SCI Analyst GRP-ANALYST Administrator GRP-ADMIN External Partner GRP-PARTNER
Object storage S3 Write Read None Admin None
diff --git a/skills/diagram-design/assets/example-dp-security-matrix.html b/skills/diagram-design/assets/example-dp-security-matrix.html
index c296051..2b80330 100644
--- a/skills/diagram-design/assets/example-dp-security-matrix.html
+++ b/skills/diagram-design/assets/example-dp-security-matrix.html
@@ -26,8 +26,8 @@
DP security matrix · Diagram Design
Data platform access matrix Five operating roles × five platform components, expressed as admin, write, read, or none.
-
- Data platform access matrix A five by five permission matrix for platform roles and components.
+
+ Data platform access matrix A five by five permission matrix for platform roles and components.
diff --git a/skills/diagram-design/assets/example-er-dark.html b/skills/diagram-design/assets/example-er-dark.html
index 4fd0d72..a21c32e 100644
--- a/skills/diagram-design/assets/example-er-dark.html
+++ b/skills/diagram-design/assets/example-er-dark.html
@@ -58,7 +58,9 @@
ER · Diagram Design
Content platform · data model
-
+
+ Content platform · data model
+ Entity-relationship diagram showing authors writing articles and articles connecting to tags and categories.
diff --git a/skills/diagram-design/assets/example-er-full.html b/skills/diagram-design/assets/example-er-full.html
index 3a4be82..5c8ac99 100644
--- a/skills/diagram-design/assets/example-er-full.html
+++ b/skills/diagram-design/assets/example-er-full.html
@@ -39,7 +39,9 @@
-
+
+ Content platform · data model
+ Entity-relationship diagram showing authors writing articles and articles connecting to tags and categories.
diff --git a/skills/diagram-design/assets/example-er.html b/skills/diagram-design/assets/example-er.html
index b31cd5e..e802c37 100644
--- a/skills/diagram-design/assets/example-er.html
+++ b/skills/diagram-design/assets/example-er.html
@@ -58,7 +58,9 @@
ER · Diagram Design
Content platform · data model
-
+
+ Content platform · data model
+ Entity-relationship diagram showing authors writing articles and articles connecting to tags and categories.
diff --git a/skills/diagram-design/assets/example-flowchart-dark.html b/skills/diagram-design/assets/example-flowchart-dark.html
index 1751a51..bd6fec0 100644
--- a/skills/diagram-design/assets/example-flowchart-dark.html
+++ b/skills/diagram-design/assets/example-flowchart-dark.html
@@ -58,7 +58,9 @@
Flowchart · Diagram Design
Should you write this as a skill?
-
+
+ Should you write this as a skill?
+ Flowchart showing when a new workflow should stay manual, become a project note, or be written as a reusable skill.
diff --git a/skills/diagram-design/assets/example-flowchart-full.html b/skills/diagram-design/assets/example-flowchart-full.html
index 90e7e0b..4a6d029 100644
--- a/skills/diagram-design/assets/example-flowchart-full.html
+++ b/skills/diagram-design/assets/example-flowchart-full.html
@@ -39,7 +39,9 @@
-
+
+ Should you write this as a skill?
+ Flowchart showing when a new workflow should stay manual, become a project note, or be written as a reusable skill.
diff --git a/skills/diagram-design/assets/example-flowchart.html b/skills/diagram-design/assets/example-flowchart.html
index 0e3096a..bcaa172 100644
--- a/skills/diagram-design/assets/example-flowchart.html
+++ b/skills/diagram-design/assets/example-flowchart.html
@@ -58,7 +58,9 @@
Flowchart · Diagram Design
Should you write this as a skill?
-
+
+ Should you write this as a skill?
+ Flowchart showing when a new workflow should stay manual, become a project note, or be written as a reusable skill.
diff --git a/skills/diagram-design/assets/example-gantt-dark.html b/skills/diagram-design/assets/example-gantt-dark.html
index a4e5360..5e195f1 100644
--- a/skills/diagram-design/assets/example-gantt-dark.html
+++ b/skills/diagram-design/assets/example-gantt-dark.html
@@ -24,7 +24,9 @@
-
+
+ Q2 product launch · 12-week plan
+ Gantt chart showing a twelve-week product launch from market research and interviews through design review, development, beta testing, and launch.
diff --git a/skills/diagram-design/assets/example-gantt-full.html b/skills/diagram-design/assets/example-gantt-full.html
index 1beedf6..50a019a 100644
--- a/skills/diagram-design/assets/example-gantt-full.html
+++ b/skills/diagram-design/assets/example-gantt-full.html
@@ -36,7 +36,9 @@
Three phases from research through launch. Design review in week 8 is the critical gate — development doesn't continue until sign-off.
-
+
+ Q2 product launch · 12-week plan
+ Gantt chart showing a twelve-week product launch from market research and interviews through design review, development, beta testing, and launch.
diff --git a/skills/diagram-design/assets/example-gantt.html b/skills/diagram-design/assets/example-gantt.html
index 9d3c6cc..71569e2 100644
--- a/skills/diagram-design/assets/example-gantt.html
+++ b/skills/diagram-design/assets/example-gantt.html
@@ -24,7 +24,9 @@
-
+
+ Q2 product launch · 12-week plan
+ Gantt chart showing a twelve-week product launch from market research and interviews through design review, development, beta testing, and launch.
diff --git a/skills/diagram-design/assets/example-high-level-dark.html b/skills/diagram-design/assets/example-high-level-dark.html
index b963042..95c1705 100644
--- a/skills/diagram-design/assets/example-high-level-dark.html
+++ b/skills/diagram-design/assets/example-high-level-dark.html
@@ -52,7 +52,9 @@
Architecture · Diagram Design
High-level architecture · End-to-end stack
-
+
+ High-level architecture · End-to-end stack
+ Architecture diagram showing data sources moving through Apache NiFi and MinIO into Trino, data modeling, and Superset dashboards, with Airflow orchestration.
@@ -110,7 +112,7 @@
EXT
-
+
@@ -122,7 +124,7 @@
EXT
-
+
@@ -133,7 +135,7 @@
EXT
-
+
@@ -145,7 +147,7 @@
EXT
-
+
@@ -155,7 +157,7 @@
-
+
Orchestration / Workflow Automation
@@ -165,7 +167,7 @@
COLL
-
+
Apache NiFi
@@ -175,7 +177,7 @@
VIRT
-
+
Trino
@@ -185,7 +187,7 @@
STORE
-
+
MinIO / S3
@@ -195,7 +197,7 @@
ANLZ
-
+
Data Modeling
@@ -205,14 +207,14 @@
DASH
-
+
Dashboards
Superset · reports
-
+
@@ -222,7 +224,7 @@
Kubernetes
-
+
diff --git a/skills/diagram-design/assets/example-high-level-full.html b/skills/diagram-design/assets/example-high-level-full.html
index 893d2ab..b62d4e7 100644
--- a/skills/diagram-design/assets/example-high-level-full.html
+++ b/skills/diagram-design/assets/example-high-level-full.html
@@ -41,7 +41,9 @@
-
+
+ High-level architecture · End-to-end stack
+ Architecture diagram showing data sources moving through Apache NiFi and MinIO into Trino, data modeling, and Superset dashboards, with Airflow orchestration.
@@ -98,34 +100,34 @@
EXT
-
+
WEB
Census · Survey · Admin
EXT
-
+
FTP
Census · Business
EXT
-
+
DB Connection
CDC · SQL · API
EXT
-
+
Legacy System
Trade data
-
+
Orchestration / Workflow Automation
(Apache Airflow)
@@ -133,7 +135,7 @@
COLL
-
+
Apache NiFi
Collect · route · transform
@@ -141,7 +143,7 @@
VIRT
-
+
Trino
SQL · data virtualization
@@ -149,7 +151,7 @@
STORE
-
+
MinIO / S3
Object store · S3-API
@@ -157,7 +159,7 @@
ANLZ
-
+
Data Modeling
Notebook · Python · R
@@ -165,16 +167,16 @@
DASH
-
+
Dashboards
Superset · reports
-
+
Kubernetes
-
+
Identity Manager
(Active Directory)
diff --git a/skills/diagram-design/assets/example-high-level-vertical-dark.html b/skills/diagram-design/assets/example-high-level-vertical-dark.html
index 5c67efe..7b7e8c1 100644
--- a/skills/diagram-design/assets/example-high-level-vertical-dark.html
+++ b/skills/diagram-design/assets/example-high-level-vertical-dark.html
@@ -52,7 +52,9 @@
Architecture · Diagram Design · Parametric
High-level architecture · Vertical Orchestration + Security
-
+
+ High-level architecture · Vertical Orchestration + Security
+ Architecture diagram showing data sources moving through ingestion, storage, transformation, and visualization alongside orchestration, security, and observability.
@@ -122,7 +124,7 @@
EXT
-
+
@@ -133,7 +135,7 @@
EXT
-
+
@@ -144,7 +146,7 @@
EXT
-
+
@@ -155,7 +157,7 @@
EXT
-
+
@@ -165,7 +167,7 @@
-
+
Orchestration / Workflow Automation
@@ -175,7 +177,7 @@
COLL
-
+
Apache NiFi
@@ -184,7 +186,7 @@
VIRT
-
+
Trino
@@ -194,7 +196,7 @@
STORE
-
+
MinIO / S3
@@ -203,7 +205,7 @@
ANLZ
-
+
Notebooks
@@ -212,14 +214,14 @@
DASH
-
+
Superset
Dashboards · reports
-
+
@@ -229,7 +231,7 @@
Kubernetes
-
+
Identity Manager
@@ -237,7 +239,7 @@
-
+
diff --git a/skills/diagram-design/assets/example-high-level-vertical-full.html b/skills/diagram-design/assets/example-high-level-vertical-full.html
index eb0a57e..e94366e 100644
--- a/skills/diagram-design/assets/example-high-level-vertical-full.html
+++ b/skills/diagram-design/assets/example-high-level-vertical-full.html
@@ -41,7 +41,9 @@
-
+
+ High-level architecture · Vertical Orchestration + Security
+ Architecture diagram showing data sources moving through ingestion, storage, transformation, and visualization alongside orchestration, security, and observability.
@@ -99,34 +101,34 @@
EXT
-
+
PostgreSQL
CDC · SQL · API
EXT
-
+
SFTP drop
Batch · landing
EXT
-
+
Web forms
Survey · admin
EXT
-
+
Legacy system
Trade · mainframe
-
+
Orchestration / Workflow Automation
(Apache Airflow)
@@ -134,50 +136,50 @@
COLL
-
+
Apache NiFi
Collect · route · transform
VIRT
-
+
Trino
SQL · data virtualization
STORE
-
+
MinIO / S3
Object store · S3-API
ANLZ
-
+
Notebooks
Jupyter · Python · R
DASH
-
+
Superset
Dashboards · reports
-
+
Kubernetes
-
+
Identity Manager
(Keycloak · LDAP · OIDC)
-
+
Monitoring & Observability
(Prometheus · Grafana · Loki)
diff --git a/skills/diagram-design/assets/example-high-level-vertical.html b/skills/diagram-design/assets/example-high-level-vertical.html
index 9541d4e..3b23830 100644
--- a/skills/diagram-design/assets/example-high-level-vertical.html
+++ b/skills/diagram-design/assets/example-high-level-vertical.html
@@ -52,7 +52,9 @@
Architecture · Diagram Design · Parametric
High-level architecture · Vertical Orchestration + Security
-
+
+ High-level architecture · Vertical Orchestration + Security
+ Architecture diagram showing data sources moving through ingestion, storage, transformation, and visualization alongside orchestration, security, and observability.
@@ -155,7 +157,7 @@
EXT
-
+
@@ -167,7 +169,7 @@
EXT
-
+
@@ -179,7 +181,7 @@
EXT
-
+
@@ -191,7 +193,7 @@
EXT
-
+
@@ -203,7 +205,7 @@
AIRFLOW BAR (Orchestration, x=208 y=52 w=744 h=44 — 12-px inside cluster on both sides)
═══════════════════════════════════════════ -->
-
+
Orchestration / Workflow Automation
@@ -217,7 +219,7 @@
COLL
-
+
Apache NiFi
@@ -227,7 +229,7 @@
VIRT
-
+
Trino
@@ -237,7 +239,7 @@
STORE
-
+
MinIO / S3
@@ -247,7 +249,7 @@
ANLZ
-
+
Notebooks
@@ -257,14 +259,14 @@
DASH
-
+
Superset
Dashboards · reports
-
+
@@ -276,7 +278,7 @@
-
+
Identity Manager
@@ -286,7 +288,7 @@
CROSS-CUTTING BAR #2 — Monitoring (Observability, y=432..472)
═══════════════════════════════════════════ -->
-
+
diff --git a/skills/diagram-design/assets/example-high-level.html b/skills/diagram-design/assets/example-high-level.html
index 2f24bc8..c140e6e 100644
--- a/skills/diagram-design/assets/example-high-level.html
+++ b/skills/diagram-design/assets/example-high-level.html
@@ -52,7 +52,9 @@
Architecture · Diagram Design
High-level architecture · End-to-end stack
-
+
+ High-level architecture · End-to-end stack
+ Architecture diagram showing data sources moving through Apache NiFi and MinIO into Trino, data modeling, and Superset dashboards, with Airflow orchestration.
@@ -144,7 +146,7 @@
EXT
-
+
@@ -157,7 +159,7 @@
EXT
-
+
@@ -170,7 +172,7 @@
EXT
-
+
@@ -183,7 +185,7 @@
EXT
-
+
@@ -193,7 +195,7 @@
-
+
Orchestration / Workflow Automation
@@ -204,7 +206,7 @@
COLL
-
+
Apache NiFi
@@ -215,7 +217,7 @@
VIRT
-
+
Trino
@@ -226,7 +228,7 @@
STORE
-
+
MinIO / S3
@@ -237,7 +239,7 @@
ANLZ
-
+
Data Modeling
@@ -248,14 +250,14 @@
DASH
-
+
Dashboards
Superset · reports
-
+
@@ -265,7 +267,7 @@
Kubernetes
-
+
diff --git a/skills/diagram-design/assets/example-import-drawio.html b/skills/diagram-design/assets/example-import-drawio.html
index 30c9d53..1dc3dae 100644
--- a/skills/diagram-design/assets/example-import-drawio.html
+++ b/skills/diagram-design/assets/example-import-drawio.html
@@ -58,7 +58,9 @@
Architecture · Imported from draw.io · doc-inline · balanced
Order platform — request path
-
+
+ Order platform — request path
+ Architecture diagram showing web and mobile clients entering through an API Gateway, then reaching authentication, orders, Postgres, object storage, and Redis.
diff --git a/skills/diagram-design/assets/example-it-state-dark.html b/skills/diagram-design/assets/example-it-state-dark.html
index 09b4af4..5b4000b 100644
--- a/skills/diagram-design/assets/example-it-state-dark.html
+++ b/skills/diagram-design/assets/example-it-state-dark.html
@@ -34,8 +34,8 @@
Legacy retail reporting landscape
File exports, desktop spreadsheets, and manual publication before a shared data platform.
-
- Northwind Retail current IT landscape Three zones show collection, processing, and dissemination through manual file handoffs.
+
+ Northwind Retail current IT landscape Three zones show collection, processing, and dissemination through manual file handoffs.
diff --git a/skills/diagram-design/assets/example-it-state-full.html b/skills/diagram-design/assets/example-it-state-full.html
index 4e59355..564596b 100644
--- a/skills/diagram-design/assets/example-it-state-full.html
+++ b/skills/diagram-design/assets/example-it-state-full.html
@@ -34,8 +34,8 @@
-
- Northwind Retail current IT landscape Three zones show collection, processing, and dissemination through manual file handoffs.
+
+ Northwind Retail current IT landscape Three zones show collection, processing, and dissemination through manual file handoffs.
diff --git a/skills/diagram-design/assets/example-it-state.html b/skills/diagram-design/assets/example-it-state.html
index 4476f94..daefd48 100644
--- a/skills/diagram-design/assets/example-it-state.html
+++ b/skills/diagram-design/assets/example-it-state.html
@@ -44,9 +44,9 @@
Legacy retail reporting landscape
File exports, desktop spreadsheets, and manual publication before a shared data platform.
-
- Northwind Retail current IT landscape
- Three zones show collection, processing, and dissemination through manual file handoffs.
+
+ Northwind Retail current IT landscape
+ Three zones show collection, processing, and dissemination through manual file handoffs.
diff --git a/skills/diagram-design/assets/example-layers-dark.html b/skills/diagram-design/assets/example-layers-dark.html
index d42cead..c03f897 100644
--- a/skills/diagram-design/assets/example-layers-dark.html
+++ b/skills/diagram-design/assets/example-layers-dark.html
@@ -58,7 +58,9 @@
Layer stack · Diagram Design
AI app stack · Where the work actually happens
-
+
+ AI app stack · Where the work actually happens
+ Layer stack showing model weights, SDK, prompts, agent harness, and UI surface, with the agent harness highlighted as the focal layer.
diff --git a/skills/diagram-design/assets/example-layers-full.html b/skills/diagram-design/assets/example-layers-full.html
index 9590245..4e1753b 100644
--- a/skills/diagram-design/assets/example-layers-full.html
+++ b/skills/diagram-design/assets/example-layers-full.html
@@ -39,7 +39,9 @@
-
+
+ AI app stack · Where the work actually happens
+ Layer stack showing model weights, SDK, prompts, agent harness, and UI surface, with the agent harness highlighted as the focal layer.
diff --git a/skills/diagram-design/assets/example-layers.html b/skills/diagram-design/assets/example-layers.html
index 71451d6..5212a1c 100644
--- a/skills/diagram-design/assets/example-layers.html
+++ b/skills/diagram-design/assets/example-layers.html
@@ -58,7 +58,9 @@
Layer stack · Diagram Design
AI app stack · Where the work actually happens
-
+
+ AI app stack · Where the work actually happens
+ Layer stack showing model weights, SDK, prompts, agent harness, and UI surface, with the agent harness highlighted as the focal layer.
diff --git a/skills/diagram-design/assets/example-line-dark.html b/skills/diagram-design/assets/example-line-dark.html
index a5a7859..6ac8044 100644
--- a/skills/diagram-design/assets/example-line-dark.html
+++ b/skills/diagram-design/assets/example-line-dark.html
@@ -20,7 +20,9 @@
Line · Diagram Design
Weekly signups · Organic leads the growth
-
+
+ Weekly signups · Organic leads the growth
+ Line chart showing weekly signups from organic, direct, and referral channels across weeks W1 through W8.
diff --git a/skills/diagram-design/assets/example-line-full.html b/skills/diagram-design/assets/example-line-full.html
index 5535184..9c50242 100644
--- a/skills/diagram-design/assets/example-line-full.html
+++ b/skills/diagram-design/assets/example-line-full.html
@@ -36,7 +36,9 @@
Signup volume by acquisition channel over eight weeks. Organic search is both the largest and fastest-growing channel; Direct is the stable baseline.
-
+
+ Weekly signups · Organic leads the growth
+ Line chart showing weekly signups from organic, direct, and referral channels across weeks W1 through W8.
diff --git a/skills/diagram-design/assets/example-line.html b/skills/diagram-design/assets/example-line.html
index b74d8e5..e5efa6d 100644
--- a/skills/diagram-design/assets/example-line.html
+++ b/skills/diagram-design/assets/example-line.html
@@ -20,7 +20,9 @@
Line · Diagram Design
Weekly signups · Organic leads the growth
-
+
+ Weekly signups · Organic leads the growth
+ Line chart showing weekly signups from organic, direct, and referral channels across weeks W1 through W8.
diff --git a/skills/diagram-design/assets/example-loop-dark.html b/skills/diagram-design/assets/example-loop-dark.html
index d73bdf6..42e7ecf 100644
--- a/skills/diagram-design/assets/example-loop-dark.html
+++ b/skills/diagram-design/assets/example-loop-dark.html
@@ -36,9 +36,9 @@
Loop · Diagram Design
The self-improving loop
-
- The self-improving loop
- Six stations flow clockwise from Capture through Learn and back to Capture. Each station writes shared state into one central memory hub, with Decide highlighted as the human approval gate.
+
+ The self-improving loop
+ Six stations flow clockwise from Capture through Learn and back to Capture. Each station writes shared state into one central memory hub, with Decide highlighted as the human approval gate.
diff --git a/skills/diagram-design/assets/example-loop-full.html b/skills/diagram-design/assets/example-loop-full.html
index 37f3f7f..98701a4 100644
--- a/skills/diagram-design/assets/example-loop-full.html
+++ b/skills/diagram-design/assets/example-loop-full.html
@@ -56,9 +56,9 @@
-
- The self-improving loop
- Six stations flow clockwise from Capture through Learn and back to Capture. Each station writes shared state into one central memory hub, with Decide highlighted as the human approval gate.
+
+ The self-improving loop
+ Six stations flow clockwise from Capture through Learn and back to Capture. Each station writes shared state into one central memory hub, with Decide highlighted as the human approval gate.
diff --git a/skills/diagram-design/assets/example-loop-terminal.html b/skills/diagram-design/assets/example-loop-terminal.html
index 391a952..2e22273 100644
--- a/skills/diagram-design/assets/example-loop-terminal.html
+++ b/skills/diagram-design/assets/example-loop-terminal.html
@@ -173,10 +173,10 @@
viewBox="0 0 1040 680"
xmlns="http://www.w3.org/2000/svg"
role="img"
- aria-labelledby="loop-title loop-desc"
+ aria-labelledby="loop-terminal-title loop-terminal-desc"
>
- The self-improving loop
-
+ The self-improving loop
+
Six stations flow clockwise from Capture through Learn and back to
Capture. Each station writes shared state into one central memory
hub, with Decide highlighted as the human approval gate.
diff --git a/skills/diagram-design/assets/example-medallion-dark.html b/skills/diagram-design/assets/example-medallion-dark.html
index 05a250e..01b56b2 100644
--- a/skills/diagram-design/assets/example-medallion-dark.html
+++ b/skills/diagram-design/assets/example-medallion-dark.html
@@ -37,9 +37,9 @@
Medallion · Diagram Design
Five-tier e-commerce analytics storage
-
- Five-tier e-commerce analytics medallion
- Clickstream events and order records move from raw storage through anonymized, staging, and aggregated tiers before lifecycle archiving.
+
+ Five-tier e-commerce analytics medallion
+ Clickstream events and order records move from raw storage through anonymized, staging, and aggregated tiers before lifecycle archiving.
diff --git a/skills/diagram-design/assets/example-medallion-full.html b/skills/diagram-design/assets/example-medallion-full.html
index e8858b5..c1b9388 100644
--- a/skills/diagram-design/assets/example-medallion-full.html
+++ b/skills/diagram-design/assets/example-medallion-full.html
@@ -57,9 +57,9 @@
-
- Five-tier e-commerce analytics medallion
- Clickstream events and order records move from raw storage through anonymized, staging, and aggregated tiers before lifecycle archiving.
+
+ Five-tier e-commerce analytics medallion
+ Clickstream events and order records move from raw storage through anonymized, staging, and aggregated tiers before lifecycle archiving.
diff --git a/skills/diagram-design/assets/example-nested-dark.html b/skills/diagram-design/assets/example-nested-dark.html
index 5d0822c..1334842 100644
--- a/skills/diagram-design/assets/example-nested-dark.html
+++ b/skills/diagram-design/assets/example-nested-dark.html
@@ -58,7 +58,9 @@
Nested · Diagram Design
The CLAUDE.md Hierarchy
-
+
+ The CLAUDE.md Hierarchy
+ Nested diagram showing how project CLAUDE.md instructions inherit broader scopes from the global, vault, business, and marketing levels.
diff --git a/skills/diagram-design/assets/example-nested-full.html b/skills/diagram-design/assets/example-nested-full.html
index 668734f..3e0081e 100644
--- a/skills/diagram-design/assets/example-nested-full.html
+++ b/skills/diagram-design/assets/example-nested-full.html
@@ -39,7 +39,9 @@
-
+
+ The CLAUDE.md Hierarchy
+ Nested diagram showing how project CLAUDE.md instructions inherit broader scopes from the global, vault, business, and marketing levels.
diff --git a/skills/diagram-design/assets/example-nested.html b/skills/diagram-design/assets/example-nested.html
index def5d0a..2feb24a 100644
--- a/skills/diagram-design/assets/example-nested.html
+++ b/skills/diagram-design/assets/example-nested.html
@@ -58,7 +58,9 @@
Nested · Diagram Design
The CLAUDE.md Hierarchy
-
+
+ The CLAUDE.md Hierarchy
+ Nested diagram showing how project CLAUDE.md instructions inherit broader scopes from the global, vault, business, and marketing levels.
diff --git a/skills/diagram-design/assets/example-org-chart-dark.html b/skills/diagram-design/assets/example-org-chart-dark.html
index 6fa2cde..a2adff5 100644
--- a/skills/diagram-design/assets/example-org-chart-dark.html
+++ b/skills/diagram-design/assets/example-org-chart-dark.html
@@ -3,8 +3,8 @@
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{--paper:#2d3142;--paper-2:#393e53;--ink:#f5f5f5;--muted:#bfc0c0;--soft:#8e98ac;--rule:rgba(245,245,245,.12);--accent:#f08a59;--accent-tint:rgba(240,138,89,.10);--link:#6a95d8;--sans:'Geist',system-ui,sans-serif;--serif:'Instrument Serif',serif;--mono:'Geist Mono',ui-monospace,monospace}
body{font-family:var(--sans);background:var(--paper);color:var(--ink);min-height:100vh;display:flex;align-items:center;justify-content:center;padding:48px 32px}.frame{max-width:1180px;width:100%}.eyebrow{font-family:var(--mono);font-size:9px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--muted);margin-bottom:8px}h1{font-family:var(--serif);font-size:32px;font-weight:400;line-height:1.08;letter-spacing:-.02em;margin-bottom:20px}.subtitle{color:var(--muted);font-size:14px;line-height:1.5;max-width:720px;margin-bottom:24px}svg{width:100%;min-width:980px;display:block}.cards{display:grid;grid-template-columns:1.1fr 1fr .9fr;gap:16px;margin-top:20px}.card{background:var(--paper-2);border:1px solid var(--rule);border-radius:6px;padding:16px}.card h2{font-size:14px;margin-bottom:8px}.card p{font-size:12px;line-height:1.45;color:var(--muted)}@media(max-width:860px){body{display:block;padding:32px 20px}.cards{grid-template-columns:1fr;overflow:visible}.frame{overflow-x:auto}}
-Org chart · Diagram Design
Agent team responsibility map A responsibility map for teams, agents, and escalation paths. Unlike a generic tree, it makes the front door, owners, invocation paths, and setup gaps visible.
-Agent team org chart Org chart showing a command center routing work to specialist agents and escalation owners.
+Org chart · Diagram Design
Agent team responsibility map A responsibility map for teams, agents, and escalation paths. Unlike a generic tree, it makes the front door, owners, invocation paths, and setup gaps visible.
+Agent team org chart Org chart showing a command center routing work to specialist agents and escalation owners.
COMMAND CENTER
@@ -42,4 +42,4 @@ body{font-family:var(--sans);background:var(--paper);color:var(--ink);min-height
Setup gaps stay visible: specialists without Slack bots · approval gates · backend name mismatches
LEGEND front door pod / owner needs setup / gap
-