Merge remote-tracking branch 'origin/main' into codex/pr24-final

This commit is contained in:
Cathryn Lavery
2026-08-11 21:37:11 -07:00
105 changed files with 1123 additions and 422 deletions
+46
View File
@@ -0,0 +1,46 @@
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
validate:
name: Lint & Verify
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
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
- name: Verify sequence OAuth specs
run: python3 scripts/verify-sequence-oauth.py
- name: Verify draw.io import script
run: python3 scripts/verify-drawio-import.py
- name: Verify generated icon assets
run: |
python3 scripts/build-icons.py
git diff --ignore-space-at-eol --exit-code -- \
skills/diagram-design/assets/icons.html \
skills/diagram-design/references/primitive-icons.md
+8
View File
@@ -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. 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 `<title>` / `<desc>` 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 ### 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`). 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`).
@@ -348,6 +352,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 <your-new-example.html>`. Before submitting a new example, run `python3 scripts/lint-skin.py <your-new-example.html>`.
The repository-wide check `python3 scripts/lint-skin.py --all --baseline` must stay green. 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 — 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 it drives the real extractor against `scripts/fixtures/sample-architecture.drawio` in all four
container formats and checks the references stay in sync. container formats and checks the references stay in sync.
@@ -355,6 +361,8 @@ If you touch the Mermaid import path, `python3 scripts/verify-mermaid-import.py`
it covers all supported grammars, multi-block Markdown, adversarial labels, trust-boundary it covers all supported grammars, multi-block Markdown, adversarial labels, trust-boundary
behavior, resource caps, named failures, and reference/command wiring. behavior, resource caps, named failures, and reference/command wiring.
All pull requests and pushes are automatically validated via GitHub Actions CI (`.github/workflows/ci.yml`).
### What loads when ### What loads when
At startup, the agent sees only the skill name and description. When a request matches, it loads `SKILL.md`; type references are pulled in only when relevant. This keeps the skill fast even with 37 reference files. At startup, the agent sees only the skill name and description. When a request matches, it loads `SKILL.md`; type references are pulled in only when relevant. This keeps the skill fast even with 37 reference files.
+5 -5
View File
@@ -218,7 +218,7 @@ def normalize_tabler(raw: str) -> str:
body = re.sub(r'<path\s+stroke="none"[^/]*?/>', "", body) body = re.sub(r'<path\s+stroke="none"[^/]*?/>', "", body)
body = re.sub(r"\s+", " ", body).strip() body = re.sub(r"\s+", " ", body).strip()
return ( return (
'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" ' '<svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24" fill="none" '
'stroke="currentColor" stroke-width="1.5" stroke-linecap="round" ' 'stroke="currentColor" stroke-width="1.5" stroke-linecap="round" '
f'stroke-linejoin="round">{body}</svg>' f'stroke-linejoin="round">{body}</svg>'
) )
@@ -232,7 +232,7 @@ def normalize_simple(raw: str) -> str:
body = inner.group(1).strip() body = inner.group(1).strip()
body = re.sub(r"\s+", " ", body).strip() body = re.sub(r"\s+", " ", body).strip()
return ( return (
'<svg width="24" height="24" viewBox="0 0 24 24" ' '<svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24" '
f'fill="currentColor">{body}</svg>' f'fill="currentColor">{body}</svg>'
) )
@@ -284,7 +284,7 @@ def normalize_url(raw: str) -> str:
body = re.sub(r'\bfill="none"', '', body) body = re.sub(r'\bfill="none"', '', body)
body = re.sub(r"\s+", " ", body).strip() body = re.sub(r"\s+", " ", body).strip()
return ( return (
f'<svg width="24" height="24" viewBox="{viewbox}" ' f'<svg aria-hidden="true" width="24" height="24" viewBox="{viewbox}" '
f'fill="currentColor">{body}</svg>' f'fill="currentColor">{body}</svg>'
) )
@@ -303,7 +303,7 @@ def normalize_devicon(raw: str) -> str:
body = re.sub(r'\bclass="[^"]*"', 'fill="currentColor"', body) body = re.sub(r'\bclass="[^"]*"', 'fill="currentColor"', body)
body = re.sub(r"\s+", " ", body).strip() body = re.sub(r"\s+", " ", body).strip()
return ( return (
'<svg width="24" height="24" viewBox="0 0 128 128" ' '<svg aria-hidden="true" width="24" height="24" viewBox="0 0 128 128" '
f'fill="currentColor">{body}</svg>' f'fill="currentColor">{body}</svg>'
) )
@@ -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'\bfill="#[0-9a-fA-F]{3,8}"', 'fill="currentColor"', body)
body = re.sub(r"\s+", " ", body).strip() body = re.sub(r"\s+", " ", body).strip()
return ( return (
'<svg width="24" height="24" viewBox="0 0 100 100" ' '<svg aria-hidden="true" width="24" height="24" viewBox="0 0 100 100" '
f'fill="currentColor">{body}</svg>' f'fill="currentColor">{body}</svg>'
) )
+253 -7
View File
@@ -8,6 +8,8 @@ skin. Use ``--all --baseline`` to skip those documented legacy files.
import argparse import argparse
import re import re
import sys import sys
from dataclasses import dataclass, field
from html.parser import HTMLParser
from pathlib import Path from pathlib import Path
@@ -50,6 +52,244 @@ ALLOWED_FONTS = {
CSS_FONT_KEYWORDS = {"inherit", "initial", "revert", "revert-layer", "unset"} 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 <svg> 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 <title> and <desc>",
)
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 <svg> must contain a <title>")
else:
if svg.first_child != "title":
add(
title.line,
title.offset,
"<title> must be the first child element of <svg>",
)
if not "".join(title.text).strip():
add(title.line, title.offset, "<title> must not be empty")
if description is None:
add(svg.line, svg.offset, "diagram <svg> must contain a <desc>")
elif not "".join(description.text).strip():
add(description.line, description.offset, "<desc> 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 <title> and <desc> IDs",
)
return findings
def normalize_hex(value): def normalize_hex(value):
value = value.lower() value = value.lower()
if len(value) == 4: if len(value) == 4:
@@ -102,6 +342,10 @@ def display_path(path):
return str(path) return str(path)
def diagram_slug(path):
return path.stem.removeprefix("example-")
def named_families(value): def named_families(value):
families = [] families = []
for raw_family in value.split(","): for raw_family in value.split(","):
@@ -114,8 +358,8 @@ def named_families(value):
return families return families
def lint_text(text, colors, rgb_triplets): def lint_text(text, colors, rgb_triplets, expected_slug):
findings = [] findings = lint_accessible_svgs(text, expected_slug)
def add(offset, category, message): def add(offset, category, message):
findings.append((line_number(text, offset), offset, category, message)) findings.append((line_number(text, offset), offset, category, message))
@@ -228,18 +472,15 @@ def main():
colors, rgb_triplets = allowed_colors() colors, rgb_triplets = allowed_colors()
skipped = 0 skipped = 0
baseline = set()
if args.all: if args.all:
paths = sorted(ASSET_DIR.glob("example-*.html")) paths = sorted(ASSET_DIR.glob("example-*.html"))
if args.baseline: if args.baseline:
baseline = load_baseline() baseline = load_baseline()
selected = []
for path in paths: for path in paths:
relative = display_path(path) relative = display_path(path)
if path.name in baseline or relative in baseline: if path.name in baseline or relative in baseline:
skipped += 1 skipped += 1
else:
selected.append(path)
paths = selected
else: else:
paths = args.files paths = args.files
@@ -247,7 +488,12 @@ def main():
for path in paths: for path in paths:
try: try:
text = path.read_text(encoding="utf-8") 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: except OSError as error:
findings = [(0, 0, "read-error", str(error))] findings = [(0, 0, "read-error", str(error))]
+229
View File
@@ -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 = """\
<svg xmlns="http://www.w3.org/2000/svg" role="img"
aria-labelledby="fixture-title fixture-desc">
<title id="fixture-title">Fixture diagram</title>
<desc id="fixture-desc">Diagram showing a fixture connected to a result.</desc>
<rect width="10" height="10"/>
</svg>
"""
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 <svg> 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(
' <rect width="10" height="10"/>',
' <g id="fixture-title"></g>\n'
' <g id="fixture-desc"></g>\n'
' <rect width="10" height="10"/>',
),
"aria-labelledby must name the <title> and <desc> IDs",
directory,
)
require_failure(
"late-title",
VALID_SVG.replace(
' <title id="fixture-title">Fixture diagram</title>\n <desc',
' <defs></defs>\n <title id="fixture-title">Fixture diagram</title>\n <desc',
),
"<title> must be the first child element of <svg>",
directory,
)
require_failure(
"empty-desc",
VALID_SVG.replace(
"Diagram showing a fixture connected to a result.", " "
),
"<desc> 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",
'<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true">'
'<path d="M0 0h1v1z"/></svg>\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("<svg><path/></svg>"),
"simple": build_icons.normalize_simple("<svg><path/></svg>"),
"url": build_icons.normalize_url(
'<svg viewBox="0 0 24 24"><path/></svg>'
),
"devicon": build_icons.normalize_devicon("<svg><path/></svg>"),
"logz": build_icons.normalize_logz("<svg><path/></svg>"),
}
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("</svg>", f" {icon}\n</svg>"),
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(
'<svg style="color: #123456"></svg>\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 <svg> 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())
+15 -1
View File
@@ -430,6 +430,9 @@ Run before producing any diagram.
**Technical:** **Technical:**
- [ ] Diagram `<svg>` has `role="img"` and `aria-labelledby` resolving to its `<title>` and `<desc>`?
- [ ] `<title>` is the first child of `<svg>` (before `<defs>`) and both `<title>` and `<desc>` are filled in?
- [ ] `<title>` / `<desc>` IDs are prefixed for this diagram and variant — never bare `title` / `desc`?
- [ ] Arrows drawn before boxes? - [ ] Arrows drawn before boxes?
- [ ] **Every connector between off-axis nodes uses a rounded right-angle elbow (`r=8`)? No diagonal `<line>` slants?** - [ ] **Every connector between off-axis nodes uses a rounded right-angle elbow (`r=8`)? No diagonal `<line>` slants?**
- [ ] **Every arrow label has a visible 6–10px gap above its connector? (Mask rect not touching the stroke.)** - [ ] **Every arrow label has a visible 6–10px gap above its connector? (Mask rect not touching the stroke.)**
@@ -471,7 +474,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). 1. Copy the variant closest to what you want (`template.html` for minimal, `template-full.html` for cards).
2. Load the matching `references/type-<name>.md` for layout conventions. 2. Load the matching `references/type-<name>.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 `<title>` / `<desc>` placeholders, and do not delete them.
4. Run the §9 taste gate. 4. Run the §9 taste gate.
--- ---
@@ -517,6 +520,17 @@ Always produce a single self-contained `.html` file:
Renders correctly in any modern browser. Renders correctly in any modern browser.
### Accessible SVG contract
Every diagram is an accessible figure by default:
1. Its `<svg>` carries `role="img"` and `aria-labelledby` naming the diagram's `<title>` and `<desc>`.
2. `<title>` is the first child of `<svg>`, before `<defs>`. Assistive technology may ignore a title placed later.
3. The IDs are prefixed per diagram and variant: `<slug>-title` / `<slug>-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. `<title>` is the short name of the subject — roughly the page `<h1>`, and about 60 characters or fewer.
5. `<desc>` 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 ### 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 `<svg>` node) — editorial wrappers like cards and headers are dropped by design. Export is **manual** — never produce export files unprompted. 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 `<svg>` node) — editorial wrappers like cards and headers are dropped by design. Export is **manual** — never produce export files unprompted.
@@ -58,7 +58,9 @@
<p class="eyebrow">Architecture · Diagram Design</p> <p class="eyebrow">Architecture · Diagram Design</p>
<h1>Content site in production</h1> <h1>Content site in production</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="architecture-dark-title architecture-dark-desc">
<title id="architecture-dark-title">Content site in production</title>
<desc id="architecture-dark-desc">Architecture diagram showing reader requests moving through Cloudflare to an Astro origin, MDX bundle, and content CMS.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -48,7 +48,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="architecture-full-title architecture-full-desc">
<title id="architecture-full-title">Content site in production</title>
<desc id="architecture-full-desc">Architecture diagram showing reader requests moving through Cloudflare to an Astro origin, MDX bundle, and content CMS.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Architecture · Diagram Design</p> <p class="eyebrow">Architecture · Diagram Design</p>
<h1>Content site in production</h1> <h1>Content site in production</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="architecture-title architecture-desc">
<title id="architecture-title">Content site in production</title>
<desc id="architecture-desc">Architecture diagram showing reader requests moving through Cloudflare to an Astro origin, MDX bundle, and content CMS.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -28,7 +28,9 @@
<p class="eyebrow">Bar · Diagram Design</p> <p class="eyebrow">Bar · Diagram Design</p>
<h1>Sprint velocity · 8-sprint view</h1> <h1>Sprint velocity · 8-sprint view</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="bar-dark-title bar-dark-desc">
<title id="bar-dark-title">Sprint velocity · 8-sprint view</title>
<desc id="bar-dark-desc">Bar chart showing story points delivered across sprints S1 through S8, with Sprint 5 as the record high.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -36,7 +36,9 @@
<p class="subtitle">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.</p> <p class="subtitle">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.</p>
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="bar-full-title bar-full-desc">
<title id="bar-full-title">Sprint velocity · 8-sprint view</title>
<desc id="bar-full-desc">Bar chart showing story points delivered across sprints S1 through S8, with Sprint 5 as the record high.</desc>
<defs><pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern></defs> <defs><pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern></defs>
<rect width="100%" height="100%" fill="#f5f5f5"/> <rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/> <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
@@ -28,7 +28,9 @@
<p class="eyebrow">Bar · Diagram Design</p> <p class="eyebrow">Bar · Diagram Design</p>
<h1>Sprint velocity · 8-sprint view</h1> <h1>Sprint velocity · 8-sprint view</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="bar-title bar-desc">
<title id="bar-title">Sprint velocity · 8-sprint view</title>
<desc id="bar-desc">Bar chart showing story points delivered across sprints S1 through S8, with Sprint 5 as the record high.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -38,9 +38,9 @@
<p class="eyebrow">Data flow · Diagram Design</p> <p class="eyebrow">Data flow · Diagram Design</p>
<h1>Role-scoped analytics pipeline</h1> <h1>Role-scoped analytics pipeline</h1>
<svg viewBox="0 0 728 356" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="flow-title flow-desc"> <svg viewBox="0 0 728 356" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="data-flow-dark-title data-flow-dark-desc">
<title id="flow-title">Role-scoped analytics data flow</title> <title id="data-flow-dark-title">Role-scoped analytics data flow</title>
<desc id="flow-desc">A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.</desc> <desc id="data-flow-dark-desc">A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="rgba(245,245,245,0.10)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="rgba(245,245,245,0.10)"/></pattern>
<marker id="arr-muted" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#bfc0c0"/></marker> <marker id="arr-muted" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#bfc0c0"/></marker>
@@ -58,9 +58,9 @@
</header> </header>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 728 356" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="flow-title flow-desc"> <svg viewBox="0 0 728 356" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="data-flow-full-title data-flow-full-desc">
<title id="flow-title">Role-scoped analytics data flow</title> <title id="data-flow-full-title">Role-scoped analytics data flow</title>
<desc id="flow-desc">A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.</desc> <desc id="data-flow-full-desc">A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="rgba(45,49,66,0.10)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="rgba(45,49,66,0.10)"/></pattern>
<marker id="arr-muted" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#4f5d75"/></marker> <marker id="arr-muted" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#4f5d75"/></marker>
@@ -38,9 +38,9 @@
<p class="eyebrow">Data flow · Diagram Design</p> <p class="eyebrow">Data flow · Diagram Design</p>
<h1>Role-scoped analytics pipeline</h1> <h1>Role-scoped analytics pipeline</h1>
<svg viewBox="0 0 728 356" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="flow-title flow-desc"> <svg viewBox="0 0 728 356" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="data-flow-title data-flow-desc">
<title id="flow-title">Role-scoped analytics data flow</title> <title id="data-flow-title">Role-scoped analytics data flow</title>
<desc id="flow-desc">A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.</desc> <desc id="data-flow-desc">A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="rgba(45,49,66,0.10)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="rgba(45,49,66,0.10)"/></pattern>
<marker id="arr-muted" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#4f5d75"/></marker> <marker id="arr-muted" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#4f5d75"/></marker>
@@ -52,7 +52,9 @@
<p class="eyebrow">Architecture · Diagram Design</p> <p class="eyebrow">Architecture · Diagram Design</p>
<h1>Open data lake · End-to-end stack</h1> <h1>Open data lake · End-to-end stack</h1>
<svg viewBox="0 0 1000 488" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 488" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="datalake-dark-title datalake-dark-desc">
<title id="datalake-dark-title">Open data lake · End-to-end stack</title>
<desc id="datalake-dark-desc">Data lake architecture showing app servers and databases flowing through Apache NiFi into MinIO, then Trino, StarRocks, Superset, JupyterLab, and Python.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -106,7 +108,7 @@
<rect x="16" y="60" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="16" y="60" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="24" y="66" width="26" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="24" y="66" width="26" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="37" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="37" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="72" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="72" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/> <path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/>
<path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/> <path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/>
<path d="M7 8l0 .01"/><path d="M7 16l0 .01"/> <path d="M7 8l0 .01"/><path d="M7 16l0 .01"/>
@@ -119,7 +121,7 @@
<rect x="16" y="164" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="16" y="164" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="24" y="170" width="26" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="24" y="170" width="26" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="37" y="179" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="37" y="179" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="72" y="170" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="72" y="170" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/> <path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/>
<path d="M4 6v6a8 3 0 0 0 16 0v-6"/> <path d="M4 6v6a8 3 0 0 0 16 0v-6"/>
<path d="M4 12v6a8 3 0 0 0 16 0v-6"/> <path d="M4 12v6a8 3 0 0 0 16 0v-6"/>
@@ -132,7 +134,7 @@
<rect x="188" y="60" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="188" y="60" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="196" y="66" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="196" y="66" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="210" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">FLOW</text> <text x="210" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">FLOW</text>
<svg x="244" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="244" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/> <path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/>
</svg> </svg>
<text x="256" y="102" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="256" y="102" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
@@ -143,7 +145,7 @@
<rect x="188" y="164" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="188" y="164" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="196" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="196" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="210" y="179" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORCH</text> <text x="210" y="179" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORCH</text>
<svg x="244" y="170" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="244" y="170" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/> <path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/>
</svg> </svg>
<text x="256" y="206" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Airflow</text> <text x="256" y="206" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Airflow</text>
@@ -154,7 +156,7 @@
<rect x="392" y="100" width="160" height="80" rx="8" fill="rgba(240,138,89,0.10)" stroke="#f08a59" stroke-width="1.2"/> <rect x="392" y="100" width="160" height="80" rx="8" fill="rgba(240,138,89,0.10)" stroke="#f08a59" stroke-width="1.2"/>
<rect x="400" y="106" width="36" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.50)" stroke-width="0.8"/> <rect x="400" y="106" width="36" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.50)" stroke-width="0.8"/>
<text x="418" y="115" fill="rgba(240,138,89,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="418" y="115" fill="rgba(240,138,89,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="460" y="108" width="24" height="24" viewBox="0 0 24 24" fill="#f08a59"> <svg x="460" y="108" width="24" height="24" viewBox="0 0 24 24" fill="#f08a59" aria-hidden="true">
<path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/> <path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/>
</svg> </svg>
<text x="472" y="148" fill="#f08a59" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO</text> <text x="472" y="148" fill="#f08a59" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO</text>
@@ -165,7 +167,7 @@
<rect x="616" y="60" width="144" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="616" y="60" width="144" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="624" y="66" width="36" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="624" y="66" width="36" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="642" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text> <text x="642" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<svg x="676" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="676" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/> <path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/>
</svg> </svg>
<text x="688" y="102" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="688" y="102" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
@@ -176,7 +178,7 @@
<rect x="616" y="164" width="144" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="616" y="164" width="144" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="624" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="624" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="638" y="179" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">OLAP</text> <text x="638" y="179" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">OLAP</text>
<svg x="676" y="170" width="24" height="24" viewBox="0 0 100 100" fill="#f5f5f5"> <svg x="676" y="170" width="24" height="24" viewBox="0 0 100 100" fill="#f5f5f5" aria-hidden="true">
<path d="M11.8,26.4c-0.1,2.2,0.9,3.4,2.3,4.5c9,7.4,18,14.8,27,22.2c2.5,2.1,2.7,3.5,1,6.2c-4.4,6.7-8.8,13.4-13.2,20.1c-1.7,2.5-3.2,2.9-5.9,1.4c-2.8-1.6-5.6-3.2-8.4-4.8c-3.2-1.8-4.8-4.6-4.8-8.3c0-11.8,0-23.6,0-35.5C9.8,30.2,10.3,28.4,11.8,26.4z"/> <path d="M11.8,26.4c-0.1,2.2,0.9,3.4,2.3,4.5c9,7.4,18,14.8,27,22.2c2.5,2.1,2.7,3.5,1,6.2c-4.4,6.7-8.8,13.4-13.2,20.1c-1.7,2.5-3.2,2.9-5.9,1.4c-2.8-1.6-5.6-3.2-8.4-4.8c-3.2-1.8-4.8-4.6-4.8-8.3c0-11.8,0-23.6,0-35.5C9.8,30.2,10.3,28.4,11.8,26.4z"/>
<path d="M87.9,73.8c0.6-2.3-0.5-3.5-1.9-4.6c-9-7.4-17.9-14.7-26.8-22.1c-2.9-2.4-3.1-3.6-1.1-6.7c4.3-6.6,8.7-13.2,13-19.8c1.7-2.6,3.3-2.9,6-1.4c2.8,1.6,5.6,3.2,8.3,4.8c3.2,1.8,4.7,4.5,4.7,8.2c0,11.9,0,23.7,0,35.6C90.2,69.9,89.6,71.9,87.9,73.8z"/> <path d="M87.9,73.8c0.6-2.3-0.5-3.5-1.9-4.6c-9-7.4-17.9-14.7-26.8-22.1c-2.9-2.4-3.1-3.6-1.1-6.7c4.3-6.6,8.7-13.2,13-19.8c1.7-2.6,3.3-2.9,6-1.4c2.8,1.6,5.6,3.2,8.3,4.8c3.2,1.8,4.7,4.5,4.7,8.2c0,11.9,0,23.7,0,35.6C90.2,69.9,89.6,71.9,87.9,73.8z"/>
<path d="M67.1,56.8c0.6,0.4,17.3,14.1,17.5,14.3c2.4,2.2,2.2,4.1-0.6,5.8C76.8,81,57.3,92.1,54.8,93.6c-3.2,1.9-6.4,1.9-9.6,0c-4.6-2.7-9.2-5.3-13.8-8c-2.2-1.3-2.2-2.7,0-3.9C42.3,75.5,53.1,69.2,64,63C66.5,61.6,68.2,60.1,67.1,56.8z"/> <path d="M67.1,56.8c0.6,0.4,17.3,14.1,17.5,14.3c2.4,2.2,2.2,4.1-0.6,5.8C76.8,81,57.3,92.1,54.8,93.6c-3.2,1.9-6.4,1.9-9.6,0c-4.6-2.7-9.2-5.3-13.8-8c-2.2-1.3-2.2-2.7,0-3.9C42.3,75.5,53.1,69.2,64,63C66.5,61.6,68.2,60.1,67.1,56.8z"/>
@@ -190,7 +192,7 @@
<rect x="816" y="60" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="816" y="60" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="824" y="66" width="18" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="824" y="66" width="18" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="833" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BI</text> <text x="833" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BI</text>
<svg x="872" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="872" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/> <path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/>
</svg> </svg>
<text x="884" y="102" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text> <text x="884" y="102" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text>
@@ -201,7 +203,7 @@
<rect x="816" y="152" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="816" y="152" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="824" y="158" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="824" y="158" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="835" y="167" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">NB</text> <text x="835" y="167" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">NB</text>
<svg x="872" y="158" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="872" y="158" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/> <path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/>
</svg> </svg>
<text x="884" y="194" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">JupyterLab</text> <text x="884" y="194" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">JupyterLab</text>
@@ -212,7 +214,7 @@
<rect x="816" y="244" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="816" y="244" width="136" height="56" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="824" y="250" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="824" y="250" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="840" y="259" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PROC</text> <text x="840" y="259" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PROC</text>
<svg x="872" y="250" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="872" y="250" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"/> <path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"/>
</svg> </svg>
<text x="884" y="286" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Python</text> <text x="884" y="286" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Python</text>
@@ -43,7 +43,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 488" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 488" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="datalake-full-title datalake-full-desc">
<title id="datalake-full-title">Open data lake · End-to-end stack</title>
<desc id="datalake-full-desc">Data lake architecture showing app servers and databases flowing through Apache NiFi into MinIO, then Trino, StarRocks, Superset, JupyterLab, and Python.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -91,7 +93,7 @@
<rect x="16" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="16" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="24" y="66" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="24" y="66" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="37" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="37" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="72" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="72" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/> <path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/>
<path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/> <path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/>
<path d="M7 8l0 .01"/><path d="M7 16l0 .01"/> <path d="M7 8l0 .01"/><path d="M7 16l0 .01"/>
@@ -103,7 +105,7 @@
<rect x="16" y="164" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="16" y="164" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="24" y="170" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="24" y="170" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="37" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="37" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="72" y="170" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="72" y="170" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/> <path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/>
<path d="M4 6v6a8 3 0 0 0 16 0v-6"/> <path d="M4 6v6a8 3 0 0 0 16 0v-6"/>
<path d="M4 12v6a8 3 0 0 0 16 0v-6"/> <path d="M4 12v6a8 3 0 0 0 16 0v-6"/>
@@ -115,7 +117,7 @@
<rect x="188" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="188" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="196" y="66" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="196" y="66" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="210" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">FLOW</text> <text x="210" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">FLOW</text>
<svg x="244" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="244" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/> <path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/>
</svg> </svg>
<text x="256" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="256" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
@@ -125,7 +127,7 @@
<rect x="188" y="164" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="188" y="164" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="196" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="196" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="210" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORCH</text> <text x="210" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORCH</text>
<svg x="244" y="170" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="244" y="170" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/> <path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/>
</svg> </svg>
<text x="256" y="206" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Airflow</text> <text x="256" y="206" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Airflow</text>
@@ -135,7 +137,7 @@
<rect x="392" y="100" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/> <rect x="392" y="100" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/>
<rect x="400" y="106" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/> <rect x="400" y="106" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="418" y="115" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="418" y="115" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="460" y="108" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36"> <svg x="460" y="108" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36" aria-hidden="true">
<path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/> <path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/>
</svg> </svg>
<text x="472" y="148" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO</text> <text x="472" y="148" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO</text>
@@ -145,7 +147,7 @@
<rect x="616" y="60" width="144" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="616" y="60" width="144" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="624" y="66" width="36" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="624" y="66" width="36" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="642" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text> <text x="642" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<svg x="676" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="676" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/> <path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/>
</svg> </svg>
<text x="688" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="688" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
@@ -155,7 +157,7 @@
<rect x="616" y="164" width="144" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="616" y="164" width="144" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="624" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="624" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="638" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">OLAP</text> <text x="638" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">OLAP</text>
<svg x="676" y="170" width="24" height="24" viewBox="0 0 100 100" fill="#2d3142"> <svg x="676" y="170" width="24" height="24" viewBox="0 0 100 100" fill="#2d3142" aria-hidden="true">
<path d="M11.8,26.4c-0.1,2.2,0.9,3.4,2.3,4.5c9,7.4,18,14.8,27,22.2c2.5,2.1,2.7,3.5,1,6.2c-4.4,6.7-8.8,13.4-13.2,20.1c-1.7,2.5-3.2,2.9-5.9,1.4c-2.8-1.6-5.6-3.2-8.4-4.8c-3.2-1.8-4.8-4.6-4.8-8.3c0-11.8,0-23.6,0-35.5C9.8,30.2,10.3,28.4,11.8,26.4z"/> <path d="M11.8,26.4c-0.1,2.2,0.9,3.4,2.3,4.5c9,7.4,18,14.8,27,22.2c2.5,2.1,2.7,3.5,1,6.2c-4.4,6.7-8.8,13.4-13.2,20.1c-1.7,2.5-3.2,2.9-5.9,1.4c-2.8-1.6-5.6-3.2-8.4-4.8c-3.2-1.8-4.8-4.6-4.8-8.3c0-11.8,0-23.6,0-35.5C9.8,30.2,10.3,28.4,11.8,26.4z"/>
<path d="M87.9,73.8c0.6-2.3-0.5-3.5-1.9-4.6c-9-7.4-17.9-14.7-26.8-22.1c-2.9-2.4-3.1-3.6-1.1-6.7c4.3-6.6,8.7-13.2,13-19.8c1.7-2.6,3.3-2.9,6-1.4c2.8,1.6,5.6,3.2,8.3,4.8c3.2,1.8,4.7,4.5,4.7,8.2c0,11.9,0,23.7,0,35.6C90.2,69.9,89.6,71.9,87.9,73.8z"/> <path d="M87.9,73.8c0.6-2.3-0.5-3.5-1.9-4.6c-9-7.4-17.9-14.7-26.8-22.1c-2.9-2.4-3.1-3.6-1.1-6.7c4.3-6.6,8.7-13.2,13-19.8c1.7-2.6,3.3-2.9,6-1.4c2.8,1.6,5.6,3.2,8.3,4.8c3.2,1.8,4.7,4.5,4.7,8.2c0,11.9,0,23.7,0,35.6C90.2,69.9,89.6,71.9,87.9,73.8z"/>
<path d="M67.1,56.8c0.6,0.4,17.3,14.1,17.5,14.3c2.4,2.2,2.2,4.1-0.6,5.8C76.8,81,57.3,92.1,54.8,93.6c-3.2,1.9-6.4,1.9-9.6,0c-4.6-2.7-9.2-5.3-13.8-8c-2.2-1.3-2.2-2.7,0-3.9C42.3,75.5,53.1,69.2,64,63C66.5,61.6,68.2,60.1,67.1,56.8z"/> <path d="M67.1,56.8c0.6,0.4,17.3,14.1,17.5,14.3c2.4,2.2,2.2,4.1-0.6,5.8C76.8,81,57.3,92.1,54.8,93.6c-3.2,1.9-6.4,1.9-9.6,0c-4.6-2.7-9.2-5.3-13.8-8c-2.2-1.3-2.2-2.7,0-3.9C42.3,75.5,53.1,69.2,64,63C66.5,61.6,68.2,60.1,67.1,56.8z"/>
@@ -168,7 +170,7 @@
<rect x="816" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="816" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="824" y="66" width="18" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="824" y="66" width="18" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="833" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BI</text> <text x="833" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BI</text>
<svg x="872" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="872" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/> <path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/>
</svg> </svg>
<text x="884" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text> <text x="884" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text>
@@ -178,7 +180,7 @@
<rect x="816" y="152" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="816" y="152" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="824" y="158" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="824" y="158" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="835" y="167" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">NB</text> <text x="835" y="167" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">NB</text>
<svg x="872" y="158" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="872" y="158" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/> <path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/>
</svg> </svg>
<text x="884" y="194" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">JupyterLab</text> <text x="884" y="194" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">JupyterLab</text>
@@ -188,7 +190,7 @@
<rect x="816" y="244" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="816" y="244" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="824" y="250" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="824" y="250" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="840" y="259" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PROC</text> <text x="840" y="259" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PROC</text>
<svg x="872" y="250" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="872" y="250" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"/> <path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"/>
</svg> </svg>
<text x="884" y="286" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Python</text> <text x="884" y="286" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Python</text>
@@ -52,7 +52,9 @@
<p class="eyebrow">Architecture · Diagram Design</p> <p class="eyebrow">Architecture · Diagram Design</p>
<h1>Open data lake · End-to-end stack</h1> <h1>Open data lake · End-to-end stack</h1>
<svg viewBox="0 0 1000 488" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 488" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="datalake-title datalake-desc">
<title id="datalake-title">Open data lake · End-to-end stack</title>
<desc id="datalake-desc">Data lake architecture showing app servers and databases flowing through Apache NiFi into MinIO, then Trino, StarRocks, Superset, JupyterLab, and Python.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -129,7 +131,7 @@
<rect x="16" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="16" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="24" y="66" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="24" y="66" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="37" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="37" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="72" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="72" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/> <path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/>
<path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/> <path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/>
<path d="M7 8l0 .01"/><path d="M7 16l0 .01"/> <path d="M7 8l0 .01"/><path d="M7 16l0 .01"/>
@@ -142,7 +144,7 @@
<rect x="16" y="164" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="16" y="164" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="24" y="170" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="24" y="170" width="26" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="37" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="37" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="72" y="170" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="72" y="170" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/> <path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/>
<path d="M4 6v6a8 3 0 0 0 16 0v-6"/> <path d="M4 6v6a8 3 0 0 0 16 0v-6"/>
<path d="M4 12v6a8 3 0 0 0 16 0v-6"/> <path d="M4 12v6a8 3 0 0 0 16 0v-6"/>
@@ -155,7 +157,7 @@
<rect x="188" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="188" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="196" y="66" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="196" y="66" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="210" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">FLOW</text> <text x="210" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">FLOW</text>
<svg x="244" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="244" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/> <path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/>
</svg> </svg>
<text x="256" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="256" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
@@ -166,7 +168,7 @@
<rect x="188" y="164" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="188" y="164" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="196" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="196" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="210" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORCH</text> <text x="210" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ORCH</text>
<svg x="244" y="170" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="244" y="170" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/> <path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/>
</svg> </svg>
<text x="256" y="206" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Airflow</text> <text x="256" y="206" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Airflow</text>
@@ -177,7 +179,7 @@
<rect x="392" y="100" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/> <rect x="392" y="100" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/>
<rect x="400" y="106" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/> <rect x="400" y="106" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="418" y="115" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="418" y="115" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="460" y="108" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36"> <svg x="460" y="108" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36" aria-hidden="true">
<path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/> <path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/>
</svg> </svg>
<text x="472" y="148" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO</text> <text x="472" y="148" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO</text>
@@ -188,7 +190,7 @@
<rect x="616" y="60" width="144" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="616" y="60" width="144" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="624" y="66" width="36" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="624" y="66" width="36" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="642" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text> <text x="642" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">QUERY</text>
<svg x="676" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="676" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/> <path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/>
</svg> </svg>
<text x="688" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="688" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
@@ -199,7 +201,7 @@
<rect x="616" y="164" width="144" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="616" y="164" width="144" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="624" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="624" y="170" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="638" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">OLAP</text> <text x="638" y="179" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">OLAP</text>
<svg x="676" y="170" width="24" height="24" viewBox="0 0 100 100" fill="#2d3142"> <svg x="676" y="170" width="24" height="24" viewBox="0 0 100 100" fill="#2d3142" aria-hidden="true">
<path d="M11.8,26.4c-0.1,2.2,0.9,3.4,2.3,4.5c9,7.4,18,14.8,27,22.2c2.5,2.1,2.7,3.5,1,6.2c-4.4,6.7-8.8,13.4-13.2,20.1c-1.7,2.5-3.2,2.9-5.9,1.4c-2.8-1.6-5.6-3.2-8.4-4.8c-3.2-1.8-4.8-4.6-4.8-8.3c0-11.8,0-23.6,0-35.5C9.8,30.2,10.3,28.4,11.8,26.4z"/> <path d="M11.8,26.4c-0.1,2.2,0.9,3.4,2.3,4.5c9,7.4,18,14.8,27,22.2c2.5,2.1,2.7,3.5,1,6.2c-4.4,6.7-8.8,13.4-13.2,20.1c-1.7,2.5-3.2,2.9-5.9,1.4c-2.8-1.6-5.6-3.2-8.4-4.8c-3.2-1.8-4.8-4.6-4.8-8.3c0-11.8,0-23.6,0-35.5C9.8,30.2,10.3,28.4,11.8,26.4z"/>
<path d="M87.9,73.8c0.6-2.3-0.5-3.5-1.9-4.6c-9-7.4-17.9-14.7-26.8-22.1c-2.9-2.4-3.1-3.6-1.1-6.7c4.3-6.6,8.7-13.2,13-19.8c1.7-2.6,3.3-2.9,6-1.4c2.8,1.6,5.6,3.2,8.3,4.8c3.2,1.8,4.7,4.5,4.7,8.2c0,11.9,0,23.7,0,35.6C90.2,69.9,89.6,71.9,87.9,73.8z"/> <path d="M87.9,73.8c0.6-2.3-0.5-3.5-1.9-4.6c-9-7.4-17.9-14.7-26.8-22.1c-2.9-2.4-3.1-3.6-1.1-6.7c4.3-6.6,8.7-13.2,13-19.8c1.7-2.6,3.3-2.9,6-1.4c2.8,1.6,5.6,3.2,8.3,4.8c3.2,1.8,4.7,4.5,4.7,8.2c0,11.9,0,23.7,0,35.6C90.2,69.9,89.6,71.9,87.9,73.8z"/>
<path d="M67.1,56.8c0.6,0.4,17.3,14.1,17.5,14.3c2.4,2.2,2.2,4.1-0.6,5.8C76.8,81,57.3,92.1,54.8,93.6c-3.2,1.9-6.4,1.9-9.6,0c-4.6-2.7-9.2-5.3-13.8-8c-2.2-1.3-2.2-2.7,0-3.9C42.3,75.5,53.1,69.2,64,63C66.5,61.6,68.2,60.1,67.1,56.8z"/> <path d="M67.1,56.8c0.6,0.4,17.3,14.1,17.5,14.3c2.4,2.2,2.2,4.1-0.6,5.8C76.8,81,57.3,92.1,54.8,93.6c-3.2,1.9-6.4,1.9-9.6,0c-4.6-2.7-9.2-5.3-13.8-8c-2.2-1.3-2.2-2.7,0-3.9C42.3,75.5,53.1,69.2,64,63C66.5,61.6,68.2,60.1,67.1,56.8z"/>
@@ -213,7 +215,7 @@
<rect x="816" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="816" y="60" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="824" y="66" width="18" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="824" y="66" width="18" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="833" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BI</text> <text x="833" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">BI</text>
<svg x="872" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="872" y="66" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/> <path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/>
</svg> </svg>
<text x="884" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text> <text x="884" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text>
@@ -224,7 +226,7 @@
<rect x="816" y="152" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="816" y="152" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="824" y="158" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="824" y="158" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="835" y="167" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">NB</text> <text x="835" y="167" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">NB</text>
<svg x="872" y="158" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="872" y="158" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/> <path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/>
</svg> </svg>
<text x="884" y="194" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">JupyterLab</text> <text x="884" y="194" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">JupyterLab</text>
@@ -235,7 +237,7 @@
<rect x="816" y="244" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="816" y="244" width="136" height="56" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="824" y="250" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/> <rect x="824" y="250" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.30)" stroke-width="0.8"/>
<text x="840" y="259" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PROC</text> <text x="840" y="259" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">PROC</text>
<svg x="872" y="250" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="872" y="250" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"/> <path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"/>
</svg> </svg>
<text x="884" y="286" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Python</text> <text x="884" y="286" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Python</text>
@@ -15,7 +15,9 @@
<div class="frame"> <div class="frame">
<p class="eyebrow">DP Integration · Diagram Design</p> <p class="eyebrow">DP Integration · Diagram Design</p>
<h1>Generic data platform integration topology</h1> <h1>Generic data platform integration topology</h1>
<svg viewBox="0 0 1200 664" xmlns="http://www.w3.org/2000/svg" aria-label="Sources connect to a core data platform and three consumer surfaces"> <svg viewBox="0 0 1200 664" xmlns="http://www.w3.org/2000/svg" aria-label="Sources connect to a core data platform and three consumer surfaces" role="img" aria-labelledby="dp-integration-dark-title dp-integration-dark-desc">
<title id="dp-integration-dark-title">Generic data platform integration topology</title>
<desc id="dp-integration-dark-desc">Integration topology showing CRM, POS exports, and an event stream landing in object storage for query, notebooks, dashboards, and a partner API.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="var(--dot)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="var(--dot)"/></pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker>
@@ -18,7 +18,9 @@
<h1>Generic data platform integration topology</h1> <h1>Generic data platform integration topology</h1>
<p class="subtitle">Three source patterns land in shared object storage, a query surface serves three consumer modes, and platform-wide services remain visibly cross-cutting.</p> <p class="subtitle">Three source patterns land in shared object storage, a query surface serves three consumer modes, and platform-wide services remain visibly cross-cutting.</p>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1200 664" xmlns="http://www.w3.org/2000/svg" aria-label="Sources connect to a core data platform and three consumer surfaces"> <svg viewBox="0 0 1200 664" xmlns="http://www.w3.org/2000/svg" aria-label="Sources connect to a core data platform and three consumer surfaces" role="img" aria-labelledby="dp-integration-full-title dp-integration-full-desc">
<title id="dp-integration-full-title">Generic data platform integration topology</title>
<desc id="dp-integration-full-desc">Integration topology showing CRM, POS exports, and an event stream landing in object storage for query, notebooks, dashboards, and a partner API.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="var(--dot)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="var(--dot)"/></pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker>
@@ -15,7 +15,9 @@
<div class="frame"> <div class="frame">
<p class="eyebrow">DP Integration · Diagram Design</p> <p class="eyebrow">DP Integration · Diagram Design</p>
<h1>Generic data platform integration topology</h1> <h1>Generic data platform integration topology</h1>
<svg viewBox="0 0 1200 664" xmlns="http://www.w3.org/2000/svg" aria-label="Sources connect to a core data platform and three consumer surfaces"> <svg viewBox="0 0 1200 664" xmlns="http://www.w3.org/2000/svg" aria-label="Sources connect to a core data platform and three consumer surfaces" role="img" aria-labelledby="dp-integration-title dp-integration-desc">
<title id="dp-integration-title">Generic data platform integration topology</title>
<desc id="dp-integration-desc">Integration topology showing CRM, POS exports, and an event stream landing in object storage for query, notebooks, dashboards, and a partner API.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="var(--dot)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="var(--dot)"/></pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker>
@@ -16,8 +16,8 @@
</style> </style>
</head> </head>
<body><main class="frame"><p class="eyebrow">DP security matrix · Diagram Design</p><h1>Data platform access matrix</h1><p class="subtitle">Five operating roles × five platform components, expressed as admin, write, read, or none.</p><div class="diagram"> <body><main class="frame"><p class="eyebrow">DP security matrix · Diagram Design</p><h1>Data platform access matrix</h1><p class="subtitle">Five operating roles × five platform components, expressed as admin, write, read, or none.</p><div class="diagram">
<svg viewBox="0 0 1084 400" role="img" aria-labelledby="matrix-dark-title matrix-dark-desc" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1084 400" role="img" aria-labelledby="dp-security-matrix-dark-title dp-security-matrix-dark-desc" xmlns="http://www.w3.org/2000/svg">
<title id="matrix-dark-title">Data platform access matrix</title><desc id="matrix-dark-desc">A five by five permission matrix for platform roles and components.</desc><rect width="1084" height="400" fill="#2d3142"/> <title id="dp-security-matrix-dark-title">Data platform access matrix</title><desc id="dp-security-matrix-dark-desc">A five by five permission matrix for platform roles and components.</desc><rect width="1084" height="400" fill="#2d3142"/>
<rect class="component-head" x="12" y="72" width="208" height="52" rx="6"/><text class="head-name" x="116" y="96" text-anchor="middle">Component</text><text class="head-sub" x="116" y="112" text-anchor="middle">vs. AD group</text> <rect class="component-head" x="12" y="72" width="208" height="52" rx="6"/><text class="head-name" x="116" y="96" text-anchor="middle">Component</text><text class="head-sub" x="116" y="112" text-anchor="middle">vs. AD group</text>
<rect class="role" x="232" y="72" width="148" height="52" rx="6"/><text class="role-name" x="306" y="92" text-anchor="middle">Data Engineer</text><text class="role-code" x="306" y="108" text-anchor="middle">GRP-DATA-ENG</text><rect class="role" x="396" y="72" width="148" height="52" rx="6"/><text class="role-name" x="470" y="92" text-anchor="middle">Data Scientist</text><text class="role-code" x="470" y="108" text-anchor="middle">GRP-DATA-SCI</text><rect class="role" x="560" y="72" width="148" height="52" rx="6"/><text class="role-name" x="634" y="92" text-anchor="middle">Analyst</text><text class="role-code" x="634" y="108" text-anchor="middle">GRP-ANALYST</text><rect class="role" x="724" y="72" width="148" height="52" rx="6"/><text class="role-name" x="798" y="92" text-anchor="middle">Administrator</text><text class="role-code" x="798" y="108" text-anchor="middle">GRP-ADMIN</text><rect class="role" x="888" y="72" width="148" height="52" rx="6"/><text class="role-name" x="962" y="92" text-anchor="middle">External Partner</text><text class="role-code" x="962" y="108" text-anchor="middle">GRP-PARTNER</text> <rect class="role" x="232" y="72" width="148" height="52" rx="6"/><text class="role-name" x="306" y="92" text-anchor="middle">Data Engineer</text><text class="role-code" x="306" y="108" text-anchor="middle">GRP-DATA-ENG</text><rect class="role" x="396" y="72" width="148" height="52" rx="6"/><text class="role-name" x="470" y="92" text-anchor="middle">Data Scientist</text><text class="role-code" x="470" y="108" text-anchor="middle">GRP-DATA-SCI</text><rect class="role" x="560" y="72" width="148" height="52" rx="6"/><text class="role-name" x="634" y="92" text-anchor="middle">Analyst</text><text class="role-code" x="634" y="108" text-anchor="middle">GRP-ANALYST</text><rect class="role" x="724" y="72" width="148" height="52" rx="6"/><text class="role-name" x="798" y="92" text-anchor="middle">Administrator</text><text class="role-code" x="798" y="108" text-anchor="middle">GRP-ADMIN</text><rect class="role" x="888" y="72" width="148" height="52" rx="6"/><text class="role-name" x="962" y="92" text-anchor="middle">External Partner</text><text class="role-code" x="962" y="108" text-anchor="middle">GRP-PARTNER</text>
<rect class="component" x="12" y="140" width="208" height="36" rx="4"/><text class="component-name" x="24" y="162">Object storage</text><text class="hint" x="208" y="162" text-anchor="end">S3</text><rect class="cell write" x="232" y="140" width="148" height="36" rx="4"/><text class="value write-text" x="306" y="162" text-anchor="middle">Write</text><rect class="cell read" x="396" y="140" width="148" height="36" rx="4"/><text class="value read-text" x="470" y="162" text-anchor="middle">Read</text><rect class="cell none" x="560" y="140" width="148" height="36" rx="4"/><text class="value none-text" x="634" y="162" text-anchor="middle">None</text><rect class="cell full" x="724" y="140" width="148" height="36" rx="4"/><text class="value full-text" x="798" y="162" text-anchor="middle">Admin</text><rect class="cell none" x="888" y="140" width="148" height="36" rx="4"/><text class="value none-text" x="962" y="162" text-anchor="middle">None</text> <rect class="component" x="12" y="140" width="208" height="36" rx="4"/><text class="component-name" x="24" y="162">Object storage</text><text class="hint" x="208" y="162" text-anchor="end">S3</text><rect class="cell write" x="232" y="140" width="148" height="36" rx="4"/><text class="value write-text" x="306" y="162" text-anchor="middle">Write</text><rect class="cell read" x="396" y="140" width="148" height="36" rx="4"/><text class="value read-text" x="470" y="162" text-anchor="middle">Read</text><rect class="cell none" x="560" y="140" width="148" height="36" rx="4"/><text class="value none-text" x="634" y="162" text-anchor="middle">None</text><rect class="cell full" x="724" y="140" width="148" height="36" rx="4"/><text class="value full-text" x="798" y="162" text-anchor="middle">Admin</text><rect class="cell none" x="888" y="140" width="148" height="36" rx="4"/><text class="value none-text" x="962" y="162" text-anchor="middle">None</text>
@@ -14,8 +14,8 @@
</style> </style>
</head> </head>
<body><main class="container"><header class="header"><p class="header-eyebrow">DP security matrix · Diagram Design</p><h1>Data platform access matrix</h1><p class="subtitle">A compact policy view for five human roles across storage, query, analysis, reporting, and orchestration. Each intersection resolves to one explicit permission level.</p></header><div class="diagram-container"> <body><main class="container"><header class="header"><p class="header-eyebrow">DP security matrix · Diagram Design</p><h1>Data platform access matrix</h1><p class="subtitle">A compact policy view for five human roles across storage, query, analysis, reporting, and orchestration. Each intersection resolves to one explicit permission level.</p></header><div class="diagram-container">
<svg viewBox="0 0 1084 400" role="img" aria-labelledby="matrix-full-title matrix-full-desc" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1084 400" role="img" aria-labelledby="dp-security-matrix-full-title dp-security-matrix-full-desc" xmlns="http://www.w3.org/2000/svg">
<title id="matrix-full-title">Data platform access matrix</title><desc id="matrix-full-desc">A five by five permission matrix for platform roles and components.</desc><rect width="1084" height="400" fill="#f5f5f5"/> <title id="dp-security-matrix-full-title">Data platform access matrix</title><desc id="dp-security-matrix-full-desc">A five by five permission matrix for platform roles and components.</desc><rect width="1084" height="400" fill="#f5f5f5"/>
<rect class="component-head" x="12" y="72" width="208" height="52" rx="6"/><text class="head-name" x="116" y="96" text-anchor="middle">Component</text><text class="head-sub" x="116" y="112" text-anchor="middle">vs. AD group</text> <rect class="component-head" x="12" y="72" width="208" height="52" rx="6"/><text class="head-name" x="116" y="96" text-anchor="middle">Component</text><text class="head-sub" x="116" y="112" text-anchor="middle">vs. AD group</text>
<rect class="role" x="232" y="72" width="148" height="52" rx="6"/><text class="role-name" x="306" y="92" text-anchor="middle">Data Engineer</text><text class="role-code" x="306" y="108" text-anchor="middle">GRP-DATA-ENG</text><rect class="role" x="396" y="72" width="148" height="52" rx="6"/><text class="role-name" x="470" y="92" text-anchor="middle">Data Scientist</text><text class="role-code" x="470" y="108" text-anchor="middle">GRP-DATA-SCI</text><rect class="role" x="560" y="72" width="148" height="52" rx="6"/><text class="role-name" x="634" y="92" text-anchor="middle">Analyst</text><text class="role-code" x="634" y="108" text-anchor="middle">GRP-ANALYST</text><rect class="role" x="724" y="72" width="148" height="52" rx="6"/><text class="role-name" x="798" y="92" text-anchor="middle">Administrator</text><text class="role-code" x="798" y="108" text-anchor="middle">GRP-ADMIN</text><rect class="role" x="888" y="72" width="148" height="52" rx="6"/><text class="role-name" x="962" y="92" text-anchor="middle">External Partner</text><text class="role-code" x="962" y="108" text-anchor="middle">GRP-PARTNER</text> <rect class="role" x="232" y="72" width="148" height="52" rx="6"/><text class="role-name" x="306" y="92" text-anchor="middle">Data Engineer</text><text class="role-code" x="306" y="108" text-anchor="middle">GRP-DATA-ENG</text><rect class="role" x="396" y="72" width="148" height="52" rx="6"/><text class="role-name" x="470" y="92" text-anchor="middle">Data Scientist</text><text class="role-code" x="470" y="108" text-anchor="middle">GRP-DATA-SCI</text><rect class="role" x="560" y="72" width="148" height="52" rx="6"/><text class="role-name" x="634" y="92" text-anchor="middle">Analyst</text><text class="role-code" x="634" y="108" text-anchor="middle">GRP-ANALYST</text><rect class="role" x="724" y="72" width="148" height="52" rx="6"/><text class="role-name" x="798" y="92" text-anchor="middle">Administrator</text><text class="role-code" x="798" y="108" text-anchor="middle">GRP-ADMIN</text><rect class="role" x="888" y="72" width="148" height="52" rx="6"/><text class="role-name" x="962" y="92" text-anchor="middle">External Partner</text><text class="role-code" x="962" y="108" text-anchor="middle">GRP-PARTNER</text>
<rect class="component" x="12" y="140" width="208" height="36" rx="4"/><text class="component-name" x="24" y="162">Object storage</text><text class="hint" x="208" y="162" text-anchor="end">S3</text><rect class="cell write" x="232" y="140" width="148" height="36" rx="4"/><text class="value write-text" x="306" y="162" text-anchor="middle">Write</text><rect class="cell read" x="396" y="140" width="148" height="36" rx="4"/><text class="value read-text" x="470" y="162" text-anchor="middle">Read</text><rect class="cell none" x="560" y="140" width="148" height="36" rx="4"/><text class="value none-text" x="634" y="162" text-anchor="middle">None</text><rect class="cell full" x="724" y="140" width="148" height="36" rx="4"/><text class="value full-text" x="798" y="162" text-anchor="middle">Admin</text><rect class="cell none" x="888" y="140" width="148" height="36" rx="4"/><text class="value none-text" x="962" y="162" text-anchor="middle">None</text> <rect class="component" x="12" y="140" width="208" height="36" rx="4"/><text class="component-name" x="24" y="162">Object storage</text><text class="hint" x="208" y="162" text-anchor="end">S3</text><rect class="cell write" x="232" y="140" width="148" height="36" rx="4"/><text class="value write-text" x="306" y="162" text-anchor="middle">Write</text><rect class="cell read" x="396" y="140" width="148" height="36" rx="4"/><text class="value read-text" x="470" y="162" text-anchor="middle">Read</text><rect class="cell none" x="560" y="140" width="148" height="36" rx="4"/><text class="value none-text" x="634" y="162" text-anchor="middle">None</text><rect class="cell full" x="724" y="140" width="148" height="36" rx="4"/><text class="value full-text" x="798" y="162" text-anchor="middle">Admin</text><rect class="cell none" x="888" y="140" width="148" height="36" rx="4"/><text class="value none-text" x="962" y="162" text-anchor="middle">None</text>
@@ -26,8 +26,8 @@
<main class="frame"> <main class="frame">
<p class="eyebrow">DP security matrix · Diagram Design</p><h1>Data platform access matrix</h1><p class="subtitle">Five operating roles × five platform components, expressed as admin, write, read, or none.</p> <p class="eyebrow">DP security matrix · Diagram Design</p><h1>Data platform access matrix</h1><p class="subtitle">Five operating roles × five platform components, expressed as admin, write, read, or none.</p>
<div class="diagram"> <div class="diagram">
<svg viewBox="0 0 1084 400" role="img" aria-labelledby="matrix-title matrix-desc" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1084 400" role="img" aria-labelledby="dp-security-matrix-title dp-security-matrix-desc" xmlns="http://www.w3.org/2000/svg">
<title id="matrix-title">Data platform access matrix</title><desc id="matrix-desc">A five by five permission matrix for platform roles and components.</desc> <title id="dp-security-matrix-title">Data platform access matrix</title><desc id="dp-security-matrix-desc">A five by five permission matrix for platform roles and components.</desc>
<rect width="1084" height="400" fill="#f5f5f5"/> <rect width="1084" height="400" fill="#f5f5f5"/>
<!-- Header: y=72, h=52; role x positions derive from the 148px column formula --> <!-- Header: y=72, h=52; role x positions derive from the 148px column formula -->
@@ -58,7 +58,9 @@
<p class="eyebrow">ER · Diagram Design</p> <p class="eyebrow">ER · Diagram Design</p>
<h1>Content platform · data model</h1> <h1>Content platform · data model</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="er-dark-title er-dark-desc">
<title id="er-dark-title">Content platform · data model</title>
<desc id="er-dark-desc">Entity-relationship diagram showing authors writing articles and articles connecting to tags and categories.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="er-full-title er-full-desc">
<title id="er-full-title">Content platform · data model</title>
<desc id="er-full-desc">Entity-relationship diagram showing authors writing articles and articles connecting to tags and categories.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
+3 -1
View File
@@ -58,7 +58,9 @@
<p class="eyebrow">ER · Diagram Design</p> <p class="eyebrow">ER · Diagram Design</p>
<h1>Content platform · data model</h1> <h1>Content platform · data model</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="er-title er-desc">
<title id="er-title">Content platform · data model</title>
<desc id="er-desc">Entity-relationship diagram showing authors writing articles and articles connecting to tags and categories.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Flowchart · Diagram Design</p> <p class="eyebrow">Flowchart · Diagram Design</p>
<h1>Should you write this as a skill?</h1> <h1>Should you write this as a skill?</h1>
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="flowchart-dark-title flowchart-dark-desc">
<title id="flowchart-dark-title">Should you write this as a skill?</title>
<desc id="flowchart-dark-desc">Flowchart showing when a new workflow should stay manual, become a project note, or be written as a reusable skill.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="flowchart-full-title flowchart-full-desc">
<title id="flowchart-full-title">Should you write this as a skill?</title>
<desc id="flowchart-full-desc">Flowchart showing when a new workflow should stay manual, become a project note, or be written as a reusable skill.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Flowchart · Diagram Design</p> <p class="eyebrow">Flowchart · Diagram Design</p>
<h1>Should you write this as a skill?</h1> <h1>Should you write this as a skill?</h1>
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="flowchart-title flowchart-desc">
<title id="flowchart-title">Should you write this as a skill?</title>
<desc id="flowchart-desc">Flowchart showing when a new workflow should stay manual, become a project note, or be written as a reusable skill.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -24,7 +24,9 @@
<!-- Rows: label col x=20-196, timeline x=200-956 --> <!-- Rows: label col x=20-196, timeline x=200-956 -->
<!-- Row height=40, bar h=24, bar top pad=8 --> <!-- Row height=40, bar h=24, bar top pad=8 -->
<!-- Week x = 200 + i*63, i=0..12 --> <!-- Week x = 200 + i*63, i=0..12 -->
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="gantt-dark-title gantt-dark-desc">
<title id="gantt-dark-title">Q2 product launch · 12-week plan</title>
<desc id="gantt-dark-desc">Gantt chart showing a twelve-week product launch from market research and interviews through design review, development, beta testing, and launch.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -36,7 +36,9 @@
<p class="subtitle">Three phases from research through launch. Design review in week 8 is the critical gate — development doesn't continue until sign-off.</p> <p class="subtitle">Three phases from research through launch. Design review in week 8 is the critical gate — development doesn't continue until sign-off.</p>
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="gantt-full-title gantt-full-desc">
<title id="gantt-full-title">Q2 product launch · 12-week plan</title>
<desc id="gantt-full-desc">Gantt chart showing a twelve-week product launch from market research and interviews through design review, development, beta testing, and launch.</desc>
<defs><pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern></defs> <defs><pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern></defs>
<rect width="100%" height="100%" fill="#f5f5f5"/> <rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/> <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
@@ -24,7 +24,9 @@
<!-- Rows: label col x=20-196, timeline x=200-956 --> <!-- Rows: label col x=20-196, timeline x=200-956 -->
<!-- Row height=40, bar h=24, bar top pad=8 --> <!-- Row height=40, bar h=24, bar top pad=8 -->
<!-- Week x = 200 + i*63, i=0..12 --> <!-- Week x = 200 + i*63, i=0..12 -->
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="gantt-title gantt-desc">
<title id="gantt-title">Q2 product launch · 12-week plan</title>
<desc id="gantt-desc">Gantt chart showing a twelve-week product launch from market research and interviews through design review, development, beta testing, and launch.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -52,7 +52,9 @@
<p class="eyebrow">Architecture · Diagram Design</p> <p class="eyebrow">Architecture · Diagram Design</p>
<h1>High-level architecture · End-to-end stack</h1> <h1>High-level architecture · End-to-end stack</h1>
<svg viewBox="0 0 1000 540" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="high-level-dark-title high-level-dark-desc">
<title id="high-level-dark-title">High-level architecture · End-to-end stack</title>
<desc id="high-level-dark-desc">Architecture diagram showing data sources moving through Apache NiFi and MinIO into Trino, data modeling, and Superset dashboards, with Airflow orchestration.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -110,7 +112,7 @@
<rect x="12" y="60" width="132" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="12" y="60" width="132" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="20" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="20" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="31" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="75" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="66" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="9"/> <circle cx="12" cy="12" r="9"/>
<path d="M3.6 9h16.8M3.6 15h16.8"/> <path d="M3.6 9h16.8M3.6 15h16.8"/>
<path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/> <path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/>
@@ -122,7 +124,7 @@
<rect x="12" y="140" width="132" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="12" y="140" width="132" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="20" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="20" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="31" y="155" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="155" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="66" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/> <path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/>
<path d="M7 9l5 -5l5 5"/><path d="M12 4l0 12"/> <path d="M7 9l5 -5l5 5"/><path d="M12 4l0 12"/>
</svg> </svg>
@@ -133,7 +135,7 @@
<rect x="12" y="220" width="132" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="12" y="220" width="132" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="20" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="20" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="31" y="235" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="235" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="66" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/> <path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/>
<path d="M4 6v6a8 3 0 0 0 16 0v-6"/> <path d="M4 6v6a8 3 0 0 0 16 0v-6"/>
<path d="M4 12v6a8 3 0 0 0 16 0v-6"/> <path d="M4 12v6a8 3 0 0 0 16 0v-6"/>
@@ -145,7 +147,7 @@
<rect x="12" y="304" width="132" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="12" y="304" width="132" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="20" y="310" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="20" y="310" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="31" y="319" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="319" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="310" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="66" y="310" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/> <path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/>
<path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/> <path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/>
<path d="M7 8l0 .01"/><path d="M7 16l0 .01"/> <path d="M7 8l0 .01"/><path d="M7 16l0 .01"/>
@@ -155,7 +157,7 @@
<!-- Airflow bar --> <!-- Airflow bar -->
<rect x="176" y="52" width="808" height="44" rx="4" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.18)" stroke-width="0.8"/> <rect x="176" y="52" width="808" height="44" rx="4" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.18)" stroke-width="0.8"/>
<svg x="950" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#bfc0c0"> <svg x="950" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#bfc0c0" aria-hidden="true">
<path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/> <path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/>
</svg> </svg>
<text x="564" y="71" fill="#f5f5f5" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text> <text x="564" y="71" fill="#f5f5f5" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text>
@@ -165,7 +167,7 @@
<rect x="176" y="112" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="176" y="112" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="184" y="118" width="30" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="184" y="118" width="30" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="199" y="127" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text> <text x="199" y="127" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text>
<svg x="240" y="118" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="240" y="118" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/> <path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/>
</svg> </svg>
<text x="252" y="154" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="252" y="154" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
@@ -175,7 +177,7 @@
<rect x="372" y="104" width="160" height="72" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="372" y="104" width="160" height="72" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="380" y="110" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="380" y="110" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="394" y="119" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text> <text x="394" y="119" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text>
<svg x="440" y="110" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="440" y="110" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/> <path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/>
</svg> </svg>
<text x="452" y="146" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="452" y="146" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
@@ -185,7 +187,7 @@
<rect x="372" y="208" width="160" height="80" rx="8" fill="rgba(240,138,89,0.12)" stroke="#f08a59" stroke-width="1.2"/> <rect x="372" y="208" width="160" height="80" rx="8" fill="rgba(240,138,89,0.12)" stroke="#f08a59" stroke-width="1.2"/>
<rect x="380" y="214" width="36" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.55)" stroke-width="0.8"/> <rect x="380" y="214" width="36" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.55)" stroke-width="0.8"/>
<text x="398" y="223" fill="rgba(240,138,89,0.85)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="398" y="223" fill="rgba(240,138,89,0.85)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="440" y="214" width="24" height="24" viewBox="0 0 24 24" fill="#f08a59"> <svg x="440" y="214" width="24" height="24" viewBox="0 0 24 24" fill="#f08a59" aria-hidden="true">
<path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/> <path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/>
</svg> </svg>
<text x="452" y="252" fill="#f08a59" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text> <text x="452" y="252" fill="#f08a59" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text>
@@ -195,7 +197,7 @@
<rect x="600" y="144" width="164" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="600" y="144" width="164" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="608" y="150" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="608" y="150" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="624" y="159" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text> <text x="624" y="159" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text>
<svg x="670" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="670" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/> <path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/>
</svg> </svg>
<text x="682" y="186" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Data Modeling</text> <text x="682" y="186" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Data Modeling</text>
@@ -205,14 +207,14 @@
<rect x="820" y="144" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="820" y="144" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="828" y="150" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/> <rect x="828" y="150" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.25)" stroke-width="0.8"/>
<text x="842" y="159" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text> <text x="842" y="159" fill="rgba(245,245,245,0.45)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text>
<svg x="884" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="884" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/> <path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/>
</svg> </svg>
<text x="896" y="186" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Dashboards</text> <text x="896" y="186" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Dashboards</text>
<text x="896" y="198" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Superset · reports</text> <text x="896" y="198" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Superset · reports</text>
<!-- Kubernetes label --> <!-- Kubernetes label -->
<svg x="180" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#bfc0c0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="180" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#bfc0c0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/> <path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/>
<circle cx="12" cy="12" r="3"/> <circle cx="12" cy="12" r="3"/>
<line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/> <line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/>
@@ -222,7 +224,7 @@
<text x="204" y="362" fill="#bfc0c0" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text> <text x="204" y="362" fill="#bfc0c0" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text>
<!-- Identity Manager --> <!-- Identity Manager -->
<svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#bfc0c0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#bfc0c0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1-8.5 15a12 12 0 0 1-8.5-15a12 12 0 0 0 8.5-3"/> <path d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1-8.5 15a12 12 0 0 1-8.5-15a12 12 0 0 0 8.5-3"/>
<circle cx="12" cy="11" r="1" fill="#bfc0c0"/> <circle cx="12" cy="11" r="1" fill="#bfc0c0"/>
<line x1="12" y1="12" x2="12" y2="14.5"/> <line x1="12" y1="12" x2="12" y2="14.5"/>
@@ -41,7 +41,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 540" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="high-level-full-title high-level-full-desc">
<title id="high-level-full-title">High-level architecture · End-to-end stack</title>
<desc id="high-level-full-desc">Architecture diagram showing data sources moving through Apache NiFi and MinIO into Trino, data modeling, and Superset dashboards, with Airflow orchestration.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -98,34 +100,34 @@
<rect x="12" y="60" width="132" height="64" rx="6" fill="#f5f5f5"/><rect x="12" y="60" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="12" y="60" width="132" height="64" rx="6" fill="#f5f5f5"/><rect x="12" y="60" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="20" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="20" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="31" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3.6 9h16.8M3.6 15h16.8"/><path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/></svg> <svg x="66" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M3.6 9h16.8M3.6 15h16.8"/><path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/></svg>
<text x="78" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">WEB</text> <text x="78" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">WEB</text>
<text x="78" y="114" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Census · Survey · Admin</text> <text x="78" y="114" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Census · Survey · Admin</text>
<rect x="12" y="140" width="132" height="64" rx="6" fill="#f5f5f5"/><rect x="12" y="140" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="12" y="140" width="132" height="64" rx="6" fill="#f5f5f5"/><rect x="12" y="140" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="20" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="20" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="31" y="155" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="155" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/><path d="M7 9l5 -5l5 5"/><path d="M12 4l0 12"/></svg> <svg x="66" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/><path d="M7 9l5 -5l5 5"/><path d="M12 4l0 12"/></svg>
<text x="78" y="182" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">FTP</text> <text x="78" y="182" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">FTP</text>
<text x="78" y="194" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Census · Business</text> <text x="78" y="194" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Census · Business</text>
<rect x="12" y="220" width="132" height="64" rx="6" fill="#f5f5f5"/><rect x="12" y="220" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="12" y="220" width="132" height="64" rx="6" fill="#f5f5f5"/><rect x="12" y="220" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="20" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="20" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="31" y="235" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="235" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/><path d="M4 6v6a8 3 0 0 0 16 0v-6"/><path d="M4 12v6a8 3 0 0 0 16 0v-6"/></svg> <svg x="66" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/><path d="M4 6v6a8 3 0 0 0 16 0v-6"/><path d="M4 12v6a8 3 0 0 0 16 0v-6"/></svg>
<text x="78" y="262" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">DB Connection</text> <text x="78" y="262" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">DB Connection</text>
<text x="78" y="274" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">CDC · SQL · API</text> <text x="78" y="274" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">CDC · SQL · API</text>
<rect x="12" y="304" width="132" height="64" rx="6" fill="#f5f5f5"/><rect x="12" y="304" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="12" y="304" width="132" height="64" rx="6" fill="#f5f5f5"/><rect x="12" y="304" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="20" y="310" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="20" y="310" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="31" y="319" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="319" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="310" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/><path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/><path d="M7 8l0 .01"/><path d="M7 16l0 .01"/></svg> <svg x="66" y="310" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/><path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/><path d="M7 8l0 .01"/><path d="M7 16l0 .01"/></svg>
<text x="78" y="346" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Legacy System</text> <text x="78" y="346" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Legacy System</text>
<text x="78" y="358" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Trade data</text> <text x="78" y="358" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Trade data</text>
<!-- Airflow bar --> <!-- Airflow bar -->
<rect x="176" y="52" width="808" height="44" rx="4" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.18)" stroke-width="0.8"/> <rect x="176" y="52" width="808" height="44" rx="4" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.18)" stroke-width="0.8"/>
<svg x="950" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#4f5d75"><path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/></svg> <svg x="950" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#4f5d75" aria-hidden="true"><path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/></svg>
<text x="564" y="71" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text> <text x="564" y="71" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text>
<text x="564" y="84" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Apache Airflow)</text> <text x="564" y="84" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Apache Airflow)</text>
@@ -133,7 +135,7 @@
<rect x="176" y="112" width="152" height="80" rx="6" fill="#f5f5f5"/><rect x="176" y="112" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="176" y="112" width="152" height="80" rx="6" fill="#f5f5f5"/><rect x="176" y="112" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="184" y="118" width="30" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="184" y="118" width="30" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="199" y="127" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text> <text x="199" y="127" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text>
<svg x="240" y="118" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"><path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/></svg> <svg x="240" y="118" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true"><path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/></svg>
<text x="252" y="154" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="252" y="154" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
<text x="252" y="166" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Collect · route · transform</text> <text x="252" y="166" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Collect · route · transform</text>
@@ -141,7 +143,7 @@
<rect x="372" y="104" width="160" height="72" rx="6" fill="#f5f5f5"/><rect x="372" y="104" width="160" height="72" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="372" y="104" width="160" height="72" rx="6" fill="#f5f5f5"/><rect x="372" y="104" width="160" height="72" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="380" y="110" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="380" y="110" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="394" y="119" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text> <text x="394" y="119" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text>
<svg x="440" y="110" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"><path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/></svg> <svg x="440" y="110" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true"><path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/></svg>
<text x="452" y="146" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="452" y="146" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
<text x="452" y="158" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">SQL · data virtualization</text> <text x="452" y="158" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">SQL · data virtualization</text>
@@ -149,7 +151,7 @@
<rect x="372" y="208" width="160" height="80" rx="8" fill="#f5f5f5"/><rect x="372" y="208" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/> <rect x="372" y="208" width="160" height="80" rx="8" fill="#f5f5f5"/><rect x="372" y="208" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/>
<rect x="380" y="214" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/> <rect x="380" y="214" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="398" y="223" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="398" y="223" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="440" y="214" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36"><path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/></svg> <svg x="440" y="214" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36" aria-hidden="true"><path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/></svg>
<text x="452" y="252" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text> <text x="452" y="252" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text>
<text x="452" y="268" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" opacity="0.75">Object store · S3-API</text> <text x="452" y="268" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" opacity="0.75">Object store · S3-API</text>
@@ -157,7 +159,7 @@
<rect x="600" y="144" width="164" height="80" rx="6" fill="#f5f5f5"/><rect x="600" y="144" width="164" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="600" y="144" width="164" height="80" rx="6" fill="#f5f5f5"/><rect x="600" y="144" width="164" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="608" y="150" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="608" y="150" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="624" y="159" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text> <text x="624" y="159" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text>
<svg x="670" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"><path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/></svg> <svg x="670" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true"><path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/></svg>
<text x="682" y="186" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Data Modeling</text> <text x="682" y="186" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Data Modeling</text>
<text x="682" y="198" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Notebook · Python · R</text> <text x="682" y="198" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Notebook · Python · R</text>
@@ -165,16 +167,16 @@
<rect x="820" y="144" width="152" height="80" rx="6" fill="#f5f5f5"/><rect x="820" y="144" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="820" y="144" width="152" height="80" rx="6" fill="#f5f5f5"/><rect x="820" y="144" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="828" y="150" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="828" y="150" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="842" y="159" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text> <text x="842" y="159" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text>
<svg x="884" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"><path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/></svg> <svg x="884" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true"><path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/></svg>
<text x="896" y="186" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Dashboards</text> <text x="896" y="186" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Dashboards</text>
<text x="896" y="198" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Superset · reports</text> <text x="896" y="198" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Superset · reports</text>
<!-- Kubernetes label --> <!-- Kubernetes label -->
<svg x="180" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/><circle cx="12" cy="12" r="3"/><line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/><line x1="20.2" y1="7.5" x2="14.9" y2="10.5"/><line x1="9.1" y1="13.5" x2="3.8" y2="16.5"/><line x1="20.2" y1="16.5" x2="14.9" y2="13.5"/><line x1="9.1" y1="10.5" x2="3.8" y2="7.5"/></svg> <svg x="180" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/><circle cx="12" cy="12" r="3"/><line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/><line x1="20.2" y1="7.5" x2="14.9" y2="10.5"/><line x1="9.1" y1="13.5" x2="3.8" y2="16.5"/><line x1="20.2" y1="16.5" x2="14.9" y2="13.5"/><line x1="9.1" y1="10.5" x2="3.8" y2="7.5"/></svg>
<text x="204" y="362" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text> <text x="204" y="362" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text>
<!-- Identity Manager --> <!-- Identity Manager -->
<svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1-8.5 15a12 12 0 0 1-8.5-15a12 12 0 0 0 8.5-3"/><circle cx="12" cy="11" r="1" fill="#4f5d75"/><line x1="12" y1="12" x2="12" y2="14.5"/></svg> <svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1-8.5 15a12 12 0 0 1-8.5-15a12 12 0 0 0 8.5-3"/><circle cx="12" cy="11" r="1" fill="#4f5d75"/><line x1="12" y1="12" x2="12" y2="14.5"/></svg>
<text x="500" y="410" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Identity Manager</text> <text x="500" y="410" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Identity Manager</text>
<text x="500" y="422" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Active Directory)</text> <text x="500" y="422" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Active Directory)</text>
@@ -52,7 +52,9 @@
<p class="eyebrow">Architecture · Diagram Design · Parametric</p> <p class="eyebrow">Architecture · Diagram Design · Parametric</p>
<h1>High-level architecture · Vertical Orchestration + Security</h1> <h1>High-level architecture · Vertical Orchestration + Security</h1>
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="high-level-vertical-dark-title high-level-vertical-dark-desc">
<title id="high-level-vertical-dark-title">High-level architecture · Vertical Orchestration + Security</title>
<desc id="high-level-vertical-dark-desc">Architecture diagram showing data sources moving through ingestion, storage, transformation, and visualization alongside orchestration, security, and observability.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -122,7 +124,7 @@
<rect x="8" y="60" width="176" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="8" y="60" width="176" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="16" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/> <rect x="16" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/>
<text x="27" y="75" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="75" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="62" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/> <path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/>
<path d="M4 6v6a8 3 0 0 0 16 0v-6"/> <path d="M4 6v6a8 3 0 0 0 16 0v-6"/>
<path d="M4 12v6a8 3 0 0 0 16 0v-6"/> <path d="M4 12v6a8 3 0 0 0 16 0v-6"/>
@@ -133,7 +135,7 @@
<rect x="8" y="140" width="176" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="8" y="140" width="176" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="16" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/> <rect x="16" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/>
<text x="27" y="155" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="155" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="62" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/> <path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/>
<path d="M7 9l5 -5l5 5"/> <path d="M7 9l5 -5l5 5"/>
<path d="M12 4l0 12"/> <path d="M12 4l0 12"/>
@@ -144,7 +146,7 @@
<rect x="8" y="220" width="176" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="8" y="220" width="176" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="16" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/> <rect x="16" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/>
<text x="27" y="235" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="235" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="62" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="9"/> <circle cx="12" cy="12" r="9"/>
<path d="M3.6 9h16.8M3.6 15h16.8"/> <path d="M3.6 9h16.8M3.6 15h16.8"/>
<path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/> <path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/>
@@ -155,7 +157,7 @@
<rect x="8" y="300" width="176" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="8" y="300" width="176" height="64" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="16" y="306" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/> <rect x="16" y="306" width="22" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/>
<text x="27" y="315" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="315" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="306" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="62" y="306" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f5f5f5" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/> <path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/>
<path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/> <path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/>
<path d="M7 8l0 .01"/><path d="M7 16l0 .01"/> <path d="M7 8l0 .01"/><path d="M7 16l0 .01"/>
@@ -165,7 +167,7 @@
<!-- Airflow bar --> <!-- Airflow bar -->
<rect x="208" y="52" width="744" height="44" rx="4" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.18)" stroke-width="0.8"/> <rect x="208" y="52" width="744" height="44" rx="4" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.18)" stroke-width="0.8"/>
<svg x="914" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#bfc0c0"> <svg x="914" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#bfc0c0" aria-hidden="true">
<path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/> <path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/>
</svg> </svg>
<text x="580" y="71" fill="#f5f5f5" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text> <text x="580" y="71" fill="#f5f5f5" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text>
@@ -175,7 +177,7 @@
<rect x="212" y="120" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="212" y="120" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="220" y="126" width="30" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/> <rect x="220" y="126" width="30" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/>
<text x="235" y="135" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text> <text x="235" y="135" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text>
<svg x="332" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="332" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0z"/> <path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0z"/>
</svg> </svg>
<text x="288" y="166" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="288" y="166" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
@@ -184,7 +186,7 @@
<rect x="404" y="120" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="404" y="120" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="412" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/> <rect x="412" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/>
<text x="426" y="135" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text> <text x="426" y="135" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text>
<svg x="524" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="524" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075z"/> <path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075z"/>
</svg> </svg>
<text x="480" y="166" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="480" y="166" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
@@ -194,7 +196,7 @@
<rect x="404" y="216" width="152" height="80" rx="8" fill="rgba(240,138,89,0.12)" stroke="#f08a59" stroke-width="1.2"/> <rect x="404" y="216" width="152" height="80" rx="8" fill="rgba(240,138,89,0.12)" stroke="#f08a59" stroke-width="1.2"/>
<rect x="412" y="222" width="36" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.55)" stroke-width="0.8"/> <rect x="412" y="222" width="36" height="12" rx="2" fill="transparent" stroke="rgba(240,138,89,0.55)" stroke-width="0.8"/>
<text x="430" y="231" fill="rgba(240,138,89,0.95)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="430" y="231" fill="rgba(240,138,89,0.95)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="524" y="222" width="24" height="24" viewBox="0 0 24 24" fill="#f08a59"> <svg x="524" y="222" width="24" height="24" viewBox="0 0 24 24" fill="#f08a59" aria-hidden="true">
<path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Z"/> <path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Z"/>
</svg> </svg>
<text x="480" y="262" fill="#f08a59" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text> <text x="480" y="262" fill="#f08a59" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text>
@@ -203,7 +205,7 @@
<rect x="596" y="120" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="596" y="120" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="604" y="126" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/> <rect x="604" y="126" width="32" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/>
<text x="620" y="135" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text> <text x="620" y="135" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text>
<svg x="716" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="716" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/> <path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/>
</svg> </svg>
<text x="672" y="166" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Notebooks</text> <text x="672" y="166" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Notebooks</text>
@@ -212,14 +214,14 @@
<rect x="790" y="120" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/> <rect x="790" y="120" width="152" height="80" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.20)" stroke-width="1"/>
<rect x="798" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/> <rect x="798" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(245,245,245,0.30)" stroke-width="0.8"/>
<text x="812" y="135" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text> <text x="812" y="135" fill="rgba(245,245,245,0.65)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text>
<svg x="910" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5"> <svg x="910" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#f5f5f5" aria-hidden="true">
<path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/> <path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/>
</svg> </svg>
<text x="866" y="166" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text> <text x="866" y="166" fill="#f5f5f5" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text>
<text x="866" y="178" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Dashboards · reports</text> <text x="866" y="178" fill="#bfc0c0" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Dashboards · reports</text>
<!-- Kubernetes label --> <!-- Kubernetes label -->
<svg x="212" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#bfc0c0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="212" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#bfc0c0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/> <path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/>
<circle cx="12" cy="12" r="3"/> <circle cx="12" cy="12" r="3"/>
<line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/> <line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/>
@@ -229,7 +231,7 @@
<text x="236" y="362" fill="#bfc0c0" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text> <text x="236" y="362" fill="#bfc0c0" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text>
<!-- Cross-cutting bar #1 — Identity (Security row, y=388..428, color=#d97a78 lightened red for dark mode) --> <!-- Cross-cutting bar #1 — Identity (Security row, y=388..428, color=#d97a78 lightened red for dark mode) -->
<svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="#d97a78"> <svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="#d97a78" aria-hidden="true">
<path d="M12.0001.0036C5.376.0036 0 5.3796 0 12.0036c0 6.6276 5.376 12 12.0001 12 6.6275 0 12-5.3724 12-12 0-6.624-5.3725-12-12-12zm5.532 17.0496c-.612 0-3.972-3.144-5.532-5.046C10.452 13.9356 7.092 17.0796 6.48 17.0796c-1.788 0-2.052-3.564-2.052-5.076 0-1.512.264-5.076 2.052-5.076.612 0 3.972 3.144 5.5201 5.046 1.548-1.932 4.908-5.046 5.532-5.046 1.788 0 2.052 3.564 2.052 5.076 0 1.512-.264 5.076-2.052 5.076z"/> <path d="M12.0001.0036C5.376.0036 0 5.3796 0 12.0036c0 6.6276 5.376 12 12.0001 12 6.6275 0 12-5.3724 12-12 0-6.624-5.3725-12-12-12zm5.532 17.0496c-.612 0-3.972-3.144-5.532-5.046C10.452 13.9356 7.092 17.0796 6.48 17.0796c-1.788 0-2.052-3.564-2.052-5.076 0-1.512.264-5.076 2.052-5.076.612 0 3.972 3.144 5.5201 5.046 1.548-1.932 4.908-5.046 5.532-5.046 1.788 0 2.052 3.564 2.052 5.076 0 1.512-.264 5.076-2.052 5.076z"/>
</svg> </svg>
<text x="484" y="410" fill="#d97a78" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Identity Manager</text> <text x="484" y="410" fill="#d97a78" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Identity Manager</text>
@@ -237,7 +239,7 @@
<!-- Cross-cutting bar #2 — Monitoring (Observability row, y=432..472) --> <!-- Cross-cutting bar #2 — Monitoring (Observability row, y=432..472) -->
<rect x="4" y="432" width="960" height="40" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.18)" stroke-width="0.8"/> <rect x="4" y="432" width="960" height="40" rx="6" fill="rgba(245,245,245,0.06)" stroke="rgba(245,245,245,0.18)" stroke-width="0.8"/>
<svg x="16" y="442" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#bfc0c0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="16" y="442" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#bfc0c0" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 3v18h18"/> <path d="M3 3v18h18"/>
<path d="M7 14l3-3 2 2 5-5"/> <path d="M7 14l3-3 2 2 5-5"/>
<path d="M14 8h3v3"/> <path d="M14 8h3v3"/>
@@ -41,7 +41,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="high-level-vertical-full-title high-level-vertical-full-desc">
<title id="high-level-vertical-full-title">High-level architecture · Vertical Orchestration + Security</title>
<desc id="high-level-vertical-full-desc">Architecture diagram showing data sources moving through ingestion, storage, transformation, and visualization alongside orchestration, security, and observability.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -99,34 +101,34 @@
<rect x="8" y="60" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="8" y="60" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="16" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="16" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="27" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/><path d="M4 6v6a8 3 0 0 0 16 0v-6"/><path d="M4 12v6a8 3 0 0 0 16 0v-6"/></svg> <svg x="62" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/><path d="M4 6v6a8 3 0 0 0 16 0v-6"/><path d="M4 12v6a8 3 0 0 0 16 0v-6"/></svg>
<text x="96" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">PostgreSQL</text> <text x="96" y="102" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">PostgreSQL</text>
<text x="96" y="114" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">CDC · SQL · API</text> <text x="96" y="114" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">CDC · SQL · API</text>
<rect x="8" y="140" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="8" y="140" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="16" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="16" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="27" y="155" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="155" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/><path d="M7 9l5 -5l5 5"/><path d="M12 4l0 12"/></svg> <svg x="62" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/><path d="M7 9l5 -5l5 5"/><path d="M12 4l0 12"/></svg>
<text x="96" y="182" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">SFTP drop</text> <text x="96" y="182" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">SFTP drop</text>
<text x="96" y="194" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Batch · landing</text> <text x="96" y="194" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Batch · landing</text>
<rect x="8" y="220" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="8" y="220" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="16" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="16" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="27" y="235" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="235" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3.6 9h16.8M3.6 15h16.8"/><path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/></svg> <svg x="62" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M3.6 9h16.8M3.6 15h16.8"/><path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/></svg>
<text x="96" y="262" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Web forms</text> <text x="96" y="262" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Web forms</text>
<text x="96" y="274" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Survey · admin</text> <text x="96" y="274" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Survey · admin</text>
<rect x="8" y="300" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="8" y="300" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="16" y="306" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="16" y="306" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="27" y="315" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="315" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="306" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/><path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/><path d="M7 8l0 .01"/><path d="M7 16l0 .01"/></svg> <svg x="62" y="306" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/><path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/><path d="M7 8l0 .01"/><path d="M7 16l0 .01"/></svg>
<text x="96" y="342" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Legacy system</text> <text x="96" y="342" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Legacy system</text>
<text x="96" y="354" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Trade · mainframe</text> <text x="96" y="354" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Trade · mainframe</text>
<!-- Airflow bar --> <!-- Airflow bar -->
<rect x="208" y="52" width="744" height="44" rx="4" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.18)" stroke-width="0.8"/> <rect x="208" y="52" width="744" height="44" rx="4" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.18)" stroke-width="0.8"/>
<svg x="914" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#4f5d75"><path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/></svg> <svg x="914" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#4f5d75" aria-hidden="true"><path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/></svg>
<text x="580" y="71" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text> <text x="580" y="71" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text>
<text x="580" y="84" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Apache Airflow)</text> <text x="580" y="84" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Apache Airflow)</text>
@@ -134,50 +136,50 @@
<rect x="212" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="212" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="220" y="126" width="30" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="220" y="126" width="30" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="235" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text> <text x="235" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text>
<svg x="332" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"><path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0z"/></svg> <svg x="332" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true"><path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0z"/></svg>
<text x="288" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="288" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
<text x="288" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Collect · route · transform</text> <text x="288" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Collect · route · transform</text>
<rect x="404" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="404" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="412" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="412" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="426" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text> <text x="426" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text>
<svg x="524" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"><path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075z"/></svg> <svg x="524" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true"><path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075z"/></svg>
<text x="480" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="480" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
<text x="480" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">SQL · data virtualization</text> <text x="480" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">SQL · data virtualization</text>
<rect x="404" y="216" width="152" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/> <rect x="404" y="216" width="152" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/>
<rect x="412" y="222" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/> <rect x="412" y="222" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="430" y="231" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="430" y="231" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="524" y="222" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36"><path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Z"/></svg> <svg x="524" y="222" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36" aria-hidden="true"><path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Z"/></svg>
<text x="480" y="262" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text> <text x="480" y="262" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text>
<text x="480" y="276" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" opacity="0.75">Object store · S3-API</text> <text x="480" y="276" fill="#eb6c36" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" opacity="0.75">Object store · S3-API</text>
<rect x="596" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="596" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="604" y="126" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="604" y="126" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="620" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text> <text x="620" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text>
<svg x="716" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"><path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424z"/></svg> <svg x="716" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true"><path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424z"/></svg>
<text x="672" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Notebooks</text> <text x="672" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Notebooks</text>
<text x="672" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Jupyter · Python · R</text> <text x="672" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Jupyter · Python · R</text>
<rect x="790" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="790" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="798" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="798" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="812" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text> <text x="812" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text>
<svg x="910" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"><path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/></svg> <svg x="910" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true"><path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/></svg>
<text x="866" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text> <text x="866" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text>
<text x="866" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Dashboards · reports</text> <text x="866" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Dashboards · reports</text>
<!-- Kubernetes label --> <!-- Kubernetes label -->
<svg x="212" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/><circle cx="12" cy="12" r="3"/><line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/><line x1="20.2" y1="7.5" x2="14.9" y2="10.5"/><line x1="9.1" y1="13.5" x2="3.8" y2="16.5"/><line x1="20.2" y1="16.5" x2="14.9" y2="13.5"/><line x1="9.1" y1="10.5" x2="3.8" y2="7.5"/></svg> <svg x="212" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/><circle cx="12" cy="12" r="3"/><line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/><line x1="20.2" y1="7.5" x2="14.9" y2="10.5"/><line x1="9.1" y1="13.5" x2="3.8" y2="16.5"/><line x1="20.2" y1="16.5" x2="14.9" y2="13.5"/><line x1="9.1" y1="10.5" x2="3.8" y2="7.5"/></svg>
<text x="236" y="362" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text> <text x="236" y="362" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text>
<!-- Cross-cutting bar #1 — Identity (color=#b85450 rust-red) --> <!-- Cross-cutting bar #1 — Identity (color=#b85450 rust-red) -->
<svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="#b85450"><path d="M12.0001.0036C5.376.0036 0 5.3796 0 12.0036c0 6.6276 5.376 12 12.0001 12 6.6275 0 12-5.3724 12-12 0-6.624-5.3725-12-12-12zm5.532 17.0496c-.612 0-3.972-3.144-5.532-5.046C10.452 13.9356 7.092 17.0796 6.48 17.0796c-1.788 0-2.052-3.564-2.052-5.076 0-1.512.264-5.076 2.052-5.076.612 0 3.972 3.144 5.5201 5.046 1.548-1.932 4.908-5.046 5.532-5.046 1.788 0 2.052 3.564 2.052 5.076 0 1.512-.264 5.076-2.052 5.076z"/></svg> <svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="#b85450" aria-hidden="true"><path d="M12.0001.0036C5.376.0036 0 5.3796 0 12.0036c0 6.6276 5.376 12 12.0001 12 6.6275 0 12-5.3724 12-12 0-6.624-5.3725-12-12-12zm5.532 17.0496c-.612 0-3.972-3.144-5.532-5.046C10.452 13.9356 7.092 17.0796 6.48 17.0796c-1.788 0-2.052-3.564-2.052-5.076 0-1.512.264-5.076 2.052-5.076.612 0 3.972 3.144 5.5201 5.046 1.548-1.932 4.908-5.046 5.532-5.046 1.788 0 2.052 3.564 2.052 5.076 0 1.512-.264 5.076-2.052 5.076z"/></svg>
<text x="484" y="410" fill="#b85450" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Identity Manager</text> <text x="484" y="410" fill="#b85450" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Identity Manager</text>
<text x="484" y="422" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Keycloak · LDAP · OIDC)</text> <text x="484" y="422" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Keycloak · LDAP · OIDC)</text>
<!-- Cross-cutting bar #2 — Monitoring --> <!-- Cross-cutting bar #2 — Monitoring -->
<rect x="4" y="432" width="960" height="40" rx="6" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.20)" stroke-width="0.8"/> <rect x="4" y="432" width="960" height="40" rx="6" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.20)" stroke-width="0.8"/>
<svg x="16" y="442" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="M7 14l3-3 2 2 5-5"/><path d="M14 8h3v3"/></svg> <svg x="16" y="442" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3v18h18"/><path d="M7 14l3-3 2 2 5-5"/><path d="M14 8h3v3"/></svg>
<text x="484" y="454" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Monitoring &amp; Observability</text> <text x="484" y="454" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Monitoring &amp; Observability</text>
<text x="484" y="466" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Prometheus · Grafana · Loki)</text> <text x="484" y="466" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">(Prometheus · Grafana · Loki)</text>
@@ -52,7 +52,9 @@
<p class="eyebrow">Architecture · Diagram Design · Parametric</p> <p class="eyebrow">Architecture · Diagram Design · Parametric</p>
<h1>High-level architecture · Vertical Orchestration + Security</h1> <h1>High-level architecture · Vertical Orchestration + Security</h1>
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="high-level-vertical-title high-level-vertical-desc">
<title id="high-level-vertical-title">High-level architecture · Vertical Orchestration + Security</title>
<desc id="high-level-vertical-desc">Architecture diagram showing data sources moving through ingestion, storage, transformation, and visualization alongside orchestration, security, and observability.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -155,7 +157,7 @@
<rect x="8" y="60" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="8" y="60" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="16" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="16" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="27" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="62" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/> <path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/>
<path d="M4 6v6a8 3 0 0 0 16 0v-6"/> <path d="M4 6v6a8 3 0 0 0 16 0v-6"/>
<path d="M4 12v6a8 3 0 0 0 16 0v-6"/> <path d="M4 12v6a8 3 0 0 0 16 0v-6"/>
@@ -167,7 +169,7 @@
<rect x="8" y="140" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="8" y="140" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="16" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="16" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="27" y="155" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="155" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="62" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/> <path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/>
<path d="M7 9l5 -5l5 5"/> <path d="M7 9l5 -5l5 5"/>
<path d="M12 4l0 12"/> <path d="M12 4l0 12"/>
@@ -179,7 +181,7 @@
<rect x="8" y="220" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="8" y="220" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="16" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="16" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="27" y="235" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="235" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="62" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="9"/> <circle cx="12" cy="12" r="9"/>
<path d="M3.6 9h16.8M3.6 15h16.8"/> <path d="M3.6 9h16.8M3.6 15h16.8"/>
<path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/> <path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/>
@@ -191,7 +193,7 @@
<rect x="8" y="300" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="8" y="300" width="176" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="16" y="306" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="16" y="306" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="27" y="315" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="27" y="315" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="62" y="306" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="62" y="306" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/> <path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/>
<path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/> <path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/>
<path d="M7 8l0 .01"/><path d="M7 16l0 .01"/> <path d="M7 8l0 .01"/><path d="M7 16l0 .01"/>
@@ -203,7 +205,7 @@
AIRFLOW BAR (Orchestration, x=208 y=52 w=744 h=44 — 12-px inside cluster on both sides) AIRFLOW BAR (Orchestration, x=208 y=52 w=744 h=44 — 12-px inside cluster on both sides)
═══════════════════════════════════════════ --> ═══════════════════════════════════════════ -->
<rect x="208" y="52" width="744" height="44" rx="4" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.18)" stroke-width="0.8"/> <rect x="208" y="52" width="744" height="44" rx="4" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.18)" stroke-width="0.8"/>
<svg x="914" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#4f5d75"> <svg x="914" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#4f5d75" aria-hidden="true">
<path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/> <path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/>
</svg> </svg>
<text x="580" y="71" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text> <text x="580" y="71" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text>
@@ -217,7 +219,7 @@
<rect x="212" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="212" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="220" y="126" width="30" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="220" y="126" width="30" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="235" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text> <text x="235" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text>
<svg x="332" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="332" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947z"/> <path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947z"/>
</svg> </svg>
<text x="288" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="288" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
@@ -227,7 +229,7 @@
<rect x="404" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="404" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="412" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="412" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="426" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text> <text x="426" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text>
<svg x="524" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="524" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/> <path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/>
</svg> </svg>
<text x="480" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="480" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
@@ -237,7 +239,7 @@
<rect x="404" y="216" width="152" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/> <rect x="404" y="216" width="152" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/>
<rect x="412" y="222" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/> <rect x="412" y="222" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="430" y="231" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="430" y="231" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="524" y="222" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36"> <svg x="524" y="222" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36" aria-hidden="true">
<path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/> <path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/>
</svg> </svg>
<text x="480" y="262" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text> <text x="480" y="262" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text>
@@ -247,7 +249,7 @@
<rect x="596" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="596" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="604" y="126" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="604" y="126" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="620" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text> <text x="620" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text>
<svg x="716" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="716" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/> <path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/>
</svg> </svg>
<text x="672" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Notebooks</text> <text x="672" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Notebooks</text>
@@ -257,14 +259,14 @@
<rect x="790" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="790" y="120" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="798" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="798" y="126" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="812" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text> <text x="812" y="135" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text>
<svg x="910" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="910" y="126" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/> <path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/>
</svg> </svg>
<text x="866" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text> <text x="866" y="166" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Superset</text>
<text x="866" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Dashboards · reports</text> <text x="866" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Dashboards · reports</text>
<!-- ── Kubernetes label (bottom-left of cluster) ── --> <!-- ── Kubernetes label (bottom-left of cluster) ── -->
<svg x="212" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="212" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/> <path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/>
<circle cx="12" cy="12" r="3"/> <circle cx="12" cy="12" r="3"/>
<line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/> <line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/>
@@ -276,7 +278,7 @@
<!-- ═══════════════════════════════════════════ <!-- ═══════════════════════════════════════════
CROSS-CUTTING BAR #1 — Identity (Security, y=388..428, color=#b85450) CROSS-CUTTING BAR #1 — Identity (Security, y=388..428, color=#b85450)
═══════════════════════════════════════════ --> ═══════════════════════════════════════════ -->
<svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="#b85450"> <svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="#b85450" aria-hidden="true">
<path d="M12.0001.0036C5.376.0036 0 5.3796 0 12.0036c0 6.6276 5.376 12 12.0001 12 6.6275 0 12-5.3724 12-12 0-6.624-5.3725-12-12-12zm5.532 17.0496c-.612 0-3.972-3.144-5.532-5.046C10.452 13.9356 7.092 17.0796 6.48 17.0796c-1.788 0-2.052-3.564-2.052-5.076 0-1.512.264-5.076 2.052-5.076.612 0 3.972 3.144 5.5201 5.046 1.548-1.932 4.908-5.046 5.532-5.046 1.788 0 2.052 3.564 2.052 5.076 0 1.512-.264 5.076-2.052 5.076z"/> <path d="M12.0001.0036C5.376.0036 0 5.3796 0 12.0036c0 6.6276 5.376 12 12.0001 12 6.6275 0 12-5.3724 12-12 0-6.624-5.3725-12-12-12zm5.532 17.0496c-.612 0-3.972-3.144-5.532-5.046C10.452 13.9356 7.092 17.0796 6.48 17.0796c-1.788 0-2.052-3.564-2.052-5.076 0-1.512.264-5.076 2.052-5.076.612 0 3.972 3.144 5.5201 5.046 1.548-1.932 4.908-5.046 5.532-5.046 1.788 0 2.052 3.564 2.052 5.076 0 1.512-.264 5.076-2.052 5.076z"/>
</svg> </svg>
<text x="484" y="410" fill="#b85450" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Identity Manager</text> <text x="484" y="410" fill="#b85450" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Identity Manager</text>
@@ -286,7 +288,7 @@
CROSS-CUTTING BAR #2 — Monitoring (Observability, y=432..472) CROSS-CUTTING BAR #2 — Monitoring (Observability, y=432..472)
═══════════════════════════════════════════ --> ═══════════════════════════════════════════ -->
<rect x="4" y="432" width="960" height="40" rx="6" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.20)" stroke-width="0.8"/> <rect x="4" y="432" width="960" height="40" rx="6" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.20)" stroke-width="0.8"/>
<svg x="16" y="442" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="16" y="442" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 3v18h18"/> <path d="M3 3v18h18"/>
<path d="M7 14l3-3 2 2 5-5"/> <path d="M7 14l3-3 2 2 5-5"/>
<path d="M14 8h3v3"/> <path d="M14 8h3v3"/>
@@ -52,7 +52,9 @@
<p class="eyebrow">Architecture · Diagram Design</p> <p class="eyebrow">Architecture · Diagram Design</p>
<h1>High-level architecture · End-to-end stack</h1> <h1>High-level architecture · End-to-end stack</h1>
<svg viewBox="0 0 1000 540" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 540" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="high-level-title high-level-desc">
<title id="high-level-title">High-level architecture · End-to-end stack</title>
<desc id="high-level-desc">Architecture diagram showing data sources moving through Apache NiFi and MinIO into Trino, data modeling, and Superset dashboards, with Airflow orchestration.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -144,7 +146,7 @@
<rect x="12" y="60" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="12" y="60" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="20" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="20" y="66" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="31" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="75" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="66" y="66" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="9"/> <circle cx="12" cy="12" r="9"/>
<path d="M3.6 9h16.8M3.6 15h16.8"/> <path d="M3.6 9h16.8M3.6 15h16.8"/>
<path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/> <path d="M11.5 3a17 17 0 0 0 0 18M12.5 3a17 17 0 0 1 0 18"/>
@@ -157,7 +159,7 @@
<rect x="12" y="140" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="12" y="140" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="20" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="20" y="146" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="31" y="155" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="155" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="66" y="146" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/> <path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/>
<path d="M7 9l5 -5l5 5"/> <path d="M7 9l5 -5l5 5"/>
<path d="M12 4l0 12"/> <path d="M12 4l0 12"/>
@@ -170,7 +172,7 @@
<rect x="12" y="220" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="12" y="220" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="20" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="20" y="226" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="31" y="235" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="235" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="66" y="226" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/> <path d="M4 6a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"/>
<path d="M4 6v6a8 3 0 0 0 16 0v-6"/> <path d="M4 6v6a8 3 0 0 0 16 0v-6"/>
<path d="M4 12v6a8 3 0 0 0 16 0v-6"/> <path d="M4 12v6a8 3 0 0 0 16 0v-6"/>
@@ -183,7 +185,7 @@
<rect x="12" y="304" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/> <rect x="12" y="304" width="132" height="64" rx="6" fill="white" stroke="rgba(45,49,66,0.22)" stroke-width="1"/>
<rect x="20" y="310" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="20" y="310" width="22" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="31" y="319" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text> <text x="31" y="319" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">EXT</text>
<svg x="66" y="310" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="66" y="310" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2d3142" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/> <path d="M3 7a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3"/>
<path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/> <path d="M3 15a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v2a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3l0 -2"/>
<path d="M7 8l0 .01"/><path d="M7 16l0 .01"/> <path d="M7 8l0 .01"/><path d="M7 16l0 .01"/>
@@ -193,7 +195,7 @@
<!-- ── Airflow orchestration bar ── --> <!-- ── Airflow orchestration bar ── -->
<rect x="176" y="52" width="808" height="44" rx="4" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.18)" stroke-width="0.8"/> <rect x="176" y="52" width="808" height="44" rx="4" fill="rgba(45,49,66,0.05)" stroke="rgba(45,49,66,0.18)" stroke-width="0.8"/>
<svg x="950" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#4f5d75"> <svg x="950" y="58" width="24" height="24" viewBox="0 0 24 24" fill="#4f5d75" aria-hidden="true">
<path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/> <path d="M17.195 16.822l4.002-4.102C23.55 10.308 23.934 5.154 24 .43a.396.396 0 0 0-.246-.373.392.392 0 0 0-.437.09l-6.495 6.658-4.102-4.003C10.309.45 5.154.066.43 0H.423a.397.397 0 0 0-.277.683l6.658 6.494-4.003 4.103C.45 13.692.065 18.846 0 23.57a.398.398 0 0 0 .683.282l6.494-6.657 3.934 3.837.17.165c2.41 2.353 7.565 2.737 12.288 2.803h.006a.397.397 0 0 0 .277-.683l-6.657-6.495z"/>
</svg> </svg>
<text x="564" y="71" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text> <text x="564" y="71" fill="#2d3142" font-size="10" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Orchestration / Workflow Automation</text>
@@ -204,7 +206,7 @@
<rect x="176" y="112" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="176" y="112" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="184" y="118" width="30" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="184" y="118" width="30" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="199" y="127" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text> <text x="199" y="127" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">COLL</text>
<svg x="240" y="118" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="240" y="118" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/> <path d="M11.648 0a.093.093 0 0 0-.084.053A30.71 30.71 0 0 1 8.592 4.73c-2.09 2.728-5.145 6.466-5.145 10.364a8.201 8.201 0 0 0 8.201 8.2v-5.003c0-.106.087-.193.194-.193h2.81v-2.813c0-.106.087-.191.194-.191h5.004c0-3.9-3.056-7.636-5.145-10.364A30.712 30.712 0 0 1 11.732.053.094.094 0 0 0 11.648 0zm-1.632 3.867c.05 0 .08.034.037.112-.11.197-.218.397-.328.593-.396.702-.819 1.389-1.23 2.08-.196-.032-.39-.06-.585-.088.495-.651 1-1.296 1.48-1.959.153-.209.302-.423.454-.634a.24.24 0 0 1 .172-.104zM7.44 7.186c.221.035.444.076.666.119-.073.129-.15.256-.223.383a29.073 29.073 0 0 0-1.625 3.261c-.874 2.123-1.383 4.444-.77 6.707a8.222 8.222 0 0 0 2.217 3.74c.083.083-.02.216-.119.155a7.568 7.568 0 0 1-.93-.686A7.674 7.674 0 0 1 4.1 16.248c-.329-2.156.387-4.246 1.418-6.115a27.44 27.44 0 0 1 1.92-2.947zm7.931 8.435a.193.193 0 0 0-.191.191V18.3h2.677V15.62zm3.299 0V18.3h1.348a7.975 7.975 0 0 0 .515-2.678zm-6.303 3.004a.193.193 0 0 0-.191.193v2.485h2.678v-2.678Zm3.295.484v2.68h2.115a.562.562 0 0 0 .399-.162v-.004a.562.562 0 0 0 .16-.397V19.11zm3.674.182v1.98a7.999 7.999 0 0 0 1.217-1.98zm-6.969 2.824a.193.193 0 0 0-.191.192v1.672a7.997 7.997 0 0 0 2.678-.516v-1.348zm3.48.668V24a8.008 8.008 0 0 0 1.98-1.217z"/>
</svg> </svg>
<text x="252" y="154" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text> <text x="252" y="154" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Apache NiFi</text>
@@ -215,7 +217,7 @@
<rect x="372" y="104" width="160" height="72" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="372" y="104" width="160" height="72" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="380" y="110" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="380" y="110" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="394" y="119" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text> <text x="394" y="119" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">VIRT</text>
<svg x="440" y="110" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="440" y="110" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/> <path d="M14.124 16.8529a.1615.1615 0 1 1 .1576.1614.1577.1577 0 0 1-.1576-.1614zm-5.607-.1576a.1614.1614 0 1 0 0 .3228.1614.1614 0 0 0 0-.3228zm10.1341-.6648v1.9869c-.031.5788-.524 1.0237-1.1029.9954h-.3843a5.0596 5.0596 0 0 1-1.1298 1.7178.3192.3192 0 0 0 0 .465l.2382.2191a.3036.3036 0 0 1 .0385.4304c-1.126 1.3835-2.9669 2.1521-5.0498 2.1521a6.575 6.575 0 0 1-4.8192-1.8985c-.0029-.0032-.0059-.0063-.0087-.0096a.6302.6302 0 0 1 .0548-.8896c.137-.1265.1371-.3462 0-.4727a4.944 4.944 0 0 1-1.126-1.714h-.3497c-.5797.0284-1.0737-.416-1.1068-.9954v-1.9869c.0351-.5779.5286-1.02 1.1068-.9915h.2728a5.7648 5.7648 0 0 1 2.0791-3.0936c-.4227-1.0991-1.1529-3.2551-1.226-5.0075C6.0229 4.4705 6.2189.078 7.8253.001c1.6064-.0768 1.3719 4.0275 1.0991 6.6946a32.732 32.732 0 0 0-.123 4.4503 6.994 6.994 0 0 1 2.4826-.4304 7.2414 7.2414 0 0 1 1.7371.2075c.2614-1.2682.8762-3.574 2.0292-5.1958 1.6717-2.352 3.4357-4.7808 4.6116-4.1006 1.176.6802-.3074 3.1398-1.3297 4.4272-1.0222 1.2874-2.7862 3.2089-3.3742 4.2274-.2114.3843-.4304.8032-.5956 1.1529a5.7375 5.7375 0 0 1 2.9169 3.6125h.073v-2.3058a.3075.3075 0 0 0-.1806-.2844.9148.9148 0 0 1-.5573-.8148 1.0184 1.0184 0 0 1 .9045-.9044c.5593-.0598 1.061.3452 1.1208.9044a.9187.9187 0 0 1-.5534.8148.3074.3074 0 0 0-.1691.2844v2.1522a.3113.3113 0 0 0 .1691.2805.9724.9724 0 0 1 .5648.857z"/>
</svg> </svg>
<text x="452" y="146" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text> <text x="452" y="146" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Trino</text>
@@ -226,7 +228,7 @@
<rect x="372" y="208" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/> <rect x="372" y="208" width="160" height="80" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36" stroke-width="1.2"/>
<rect x="380" y="214" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/> <rect x="380" y="214" width="36" height="12" rx="2" fill="transparent" stroke="rgba(235,108,54,0.50)" stroke-width="0.8"/>
<text x="398" y="223" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text> <text x="398" y="223" fill="rgba(235,108,54,0.80)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">STORE</text>
<svg x="440" y="214" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36"> <svg x="440" y="214" width="24" height="24" viewBox="0 0 24 24" fill="#eb6c36" aria-hidden="true">
<path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/> <path d="M13.2072.006c-.6216-.0478-1.2.1943-1.6211.582a2.15 2.15 0 0 0-.0938 3.0352l3.4082 3.5507a3.042 3.042 0 0 1-.664 4.6875l-.463.2383V7.2853a15.4198 15.4198 0 0 0-8.0174 10.4862v.0176l6.5487-3.3281v7.621L13.7794 24V13.6817l.8965-.4629a4.4432 4.4432 0 0 0 1.2207-7.0292l-3.371-3.5254a.7489.7489 0 0 1 .037-1.0547.7522.7522 0 0 1 1.0567.0371l.4668.4863-.006.0059 4.0704 4.2441a.0566.0566 0 0 0 .082 0 .06.06 0 0 0 0-.0703l-3.1406-5.1425-.1484.1425.1484-.1445C14.4945.3926 13.8287.0538 13.2072.006Zm-.9024 9.8652v2.9941l-4.1523 2.1484a13.9787 13.9787 0 0 1 2.7676-3.9277 14.1784 14.1784 0 0 1 1.3847-1.2148z"/>
</svg> </svg>
<text x="452" y="252" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text> <text x="452" y="252" fill="#eb6c36" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">MinIO / S3</text>
@@ -237,7 +239,7 @@
<rect x="600" y="144" width="164" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="600" y="144" width="164" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="608" y="150" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="608" y="150" width="32" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="624" y="159" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text> <text x="624" y="159" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">ANLZ</text>
<svg x="670" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="670" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/> <path d="M7.157 22.201A1.784 1.799 0 0 1 5.374 24a1.784 1.799 0 0 1-1.784-1.799 1.784 1.799 0 0 1 1.784-1.799 1.784 1.799 0 0 1 1.783 1.799zM20.582 1.427a1.415 1.427 0 0 1-1.415 1.428 1.415 1.427 0 0 1-1.416-1.428A1.415 1.427 0 0 1 19.167 0a1.415 1.427 0 0 1 1.415 1.427zM4.992 3.336A1.047 1.056 0 0 1 3.946 4.39a1.047 1.056 0 0 1-1.047-1.055A1.047 1.056 0 0 1 3.946 2.28a1.047 1.056 0 0 1 1.046 1.056zm7.336 1.517c3.769 0 7.06 1.38 8.768 3.424a9.363 9.363 0 0 0-3.393-4.547 9.238 9.238 0 0 0-5.377-1.728A9.238 9.238 0 0 0 6.95 3.73a9.363 9.363 0 0 0-3.394 4.547c1.713-2.04 5.004-3.424 8.772-3.424zm.001 13.295c-3.768 0-7.06-1.381-8.768-3.425a9.363 9.363 0 0 0 3.394 4.547A9.238 9.238 0 0 0 12.33 21a9.238 9.238 0 0 0 5.377-1.729 9.363 9.363 0 0 0 3.393-4.547c-1.712 2.044-5.003 3.425-8.772 3.425z"/>
</svg> </svg>
<text x="682" y="186" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Data Modeling</text> <text x="682" y="186" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Data Modeling</text>
@@ -248,14 +250,14 @@
<rect x="820" y="144" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/> <rect x="820" y="144" width="152" height="80" rx="6" fill="white" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
<rect x="828" y="150" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/> <rect x="828" y="150" width="28" height="12" rx="2" fill="transparent" stroke="rgba(45,49,66,0.28)" stroke-width="0.8"/>
<text x="842" y="159" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text> <text x="842" y="159" fill="rgba(45,49,66,0.55)" font-size="7" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.08em">DASH</text>
<svg x="884" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142"> <svg x="884" y="150" width="24" height="24" viewBox="0 0 24 24" fill="#2d3142" aria-hidden="true">
<path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/> <path d="M6.168 6.045C2.603 6.045 0 8.579 0 12.014c0 3.434 2.603 5.941 6.168 5.941 2.184 0 3.888-1.026 5.775-3.078 1.53 2.033 4.037 3.136 5.89 3.078 3.566 0 6.167-2.503 6.167-5.941 0-3.438-2.601-5.97-6.168-5.97-2.864 0-5.138 2.425-5.771 3.173-.76-.9-1.674-1.665-2.682-2.274-1.019-.588-2.084-.898-3.211-.898z"/>
</svg> </svg>
<text x="896" y="186" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Dashboards</text> <text x="896" y="186" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Dashboards</text>
<text x="896" y="198" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Superset · reports</text> <text x="896" y="198" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">Superset · reports</text>
<!-- ── Kubernetes label (bottom-left of boundary) ── --> <!-- ── Kubernetes label (bottom-left of boundary) ── -->
<svg x="180" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="180" y="348" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/> <path d="M19.875 6.27a2.225 2.225 0 0 1 1.125 1.948v7.284c0 .809-.443 1.555-1.158 1.948l-6.75 3.98a2.5 2.5 0 0 1-2.184 0l-6.75-3.98a2.225 2.225 0 0 1-1.158-1.948v-7.284c0-.809.443-1.555 1.158-1.948l6.75-3.98a2.5 2.5 0 0 1 2.184 0z"/>
<circle cx="12" cy="12" r="3"/> <circle cx="12" cy="12" r="3"/>
<line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/> <line x1="12" y1="3" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="21"/>
@@ -265,7 +267,7 @@
<text x="204" y="362" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text> <text x="204" y="362" fill="#4f5d75" font-size="8" font-weight="500" font-family="'Geist', sans-serif">Kubernetes</text>
<!-- ── Identity Manager bar ── --> <!-- ── Identity Manager bar ── -->
<svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <svg x="16" y="398" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#4f5d75" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1-8.5 15a12 12 0 0 1-8.5-15a12 12 0 0 0 8.5-3"/> <path d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1-8.5 15a12 12 0 0 1-8.5-15a12 12 0 0 0 8.5-3"/>
<circle cx="12" cy="11" r="1" fill="#4f5d75"/> <circle cx="12" cy="11" r="1" fill="#4f5d75"/>
<line x1="12" y1="12" x2="12" y2="14.5"/> <line x1="12" y1="12" x2="12" y2="14.5"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Architecture · Imported from draw.io · doc-inline · balanced</p> <p class="eyebrow">Architecture · Imported from draw.io · doc-inline · balanced</p>
<h1>Order platform — request path</h1> <h1>Order platform — request path</h1>
<svg viewBox="0 0 960 600" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 960 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="import-drawio-title import-drawio-desc">
<title id="import-drawio-title">Order platform — request path</title>
<desc id="import-drawio-desc">Architecture diagram showing web and mobile clients entering through an API Gateway, then reaching authentication, orders, Postgres, object storage, and Redis.</desc>
<defs> <defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker> <marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
@@ -34,8 +34,8 @@
<h1>Legacy retail reporting landscape</h1> <h1>Legacy retail reporting landscape</h1>
<p class="subtitle">File exports, desktop spreadsheets, and manual publication before a shared data platform.</p> <p class="subtitle">File exports, desktop spreadsheets, and manual publication before a shared data platform.</p>
<div class="diagram"> <div class="diagram">
<svg viewBox="0 0 960 500" role="img" aria-labelledby="it-dark-title it-dark-desc" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 960 500" role="img" aria-labelledby="it-state-dark-title it-state-dark-desc" xmlns="http://www.w3.org/2000/svg">
<title id="it-dark-title">Northwind Retail current IT landscape</title><desc id="it-dark-desc">Three zones show collection, processing, and dissemination through manual file handoffs.</desc> <title id="it-state-dark-title">Northwind Retail current IT landscape</title><desc id="it-state-dark-desc">Three zones show collection, processing, and dissemination through manual file handoffs.</desc>
<defs> <defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#6a95d8"/></marker> <marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#6a95d8"/></marker>
@@ -34,8 +34,8 @@
<main class="container"> <main class="container">
<header class="header"><p class="header-eyebrow">IT current-state · Northwind Retail</p><h1>Legacy retail reporting landscape</h1><p class="subtitle">Sales and supplier files converge on a shared drive, move through desktop workbooks, and reach regional teams through a manually refreshed portal and emailed report packs.</p></header> <header class="header"><p class="header-eyebrow">IT current-state · Northwind Retail</p><h1>Legacy retail reporting landscape</h1><p class="subtitle">Sales and supplier files converge on a shared drive, move through desktop workbooks, and reach regional teams through a manually refreshed portal and emailed report packs.</p></header>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 960 500" role="img" aria-labelledby="it-full-title it-full-desc" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 960 500" role="img" aria-labelledby="it-state-full-title it-state-full-desc" xmlns="http://www.w3.org/2000/svg">
<title id="it-full-title">Northwind Retail current IT landscape</title><desc id="it-full-desc">Three zones show collection, processing, and dissemination through manual file handoffs.</desc> <title id="it-state-full-title">Northwind Retail current IT landscape</title><desc id="it-state-full-desc">Three zones show collection, processing, and dissemination through manual file handoffs.</desc>
<defs> <defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker><marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/></marker><marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker><marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/></marker><marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
<symbol id="icon-file" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 3v4a1 1 0 0 0 1 1h4"/><path d="M17 21H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7l5 5v11a2 2 0 0 1-2 2"/></symbol><symbol id="icon-screen" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="12" rx="1"/><path d="M7 20h10M9 16v4M15 16v4"/></symbol><symbol id="icon-db" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><ellipse cx="12" cy="6" rx="8" ry="3"/><path d="M4 6v6c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></symbol><symbol id="icon-users" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="9" cy="8" r="4"/><path d="M3 21v-2a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v2M16 4.5a4 4 0 0 1 0 7M18 15a4 4 0 0 1 3 4v2"/></symbol> <symbol id="icon-file" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 3v4a1 1 0 0 0 1 1h4"/><path d="M17 21H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7l5 5v11a2 2 0 0 1-2 2"/></symbol><symbol id="icon-screen" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="12" rx="1"/><path d="M7 20h10M9 16v4M15 16v4"/></symbol><symbol id="icon-db" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><ellipse cx="12" cy="6" rx="8" ry="3"/><path d="M4 6v6c0 1.7 3.6 3 8 3s8-1.3 8-3V6M4 12v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></symbol><symbol id="icon-users" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="9" cy="8" r="4"/><path d="M3 21v-2a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v2M16 4.5a4 4 0 0 1 0 7M18 15a4 4 0 0 1 3 4v2"/></symbol>
@@ -44,9 +44,9 @@
<h1>Legacy retail reporting landscape</h1> <h1>Legacy retail reporting landscape</h1>
<p class="subtitle">File exports, desktop spreadsheets, and manual publication before a shared data platform.</p> <p class="subtitle">File exports, desktop spreadsheets, and manual publication before a shared data platform.</p>
<div class="diagram"> <div class="diagram">
<svg viewBox="0 0 960 500" role="img" aria-labelledby="it-title it-desc" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 960 500" role="img" aria-labelledby="it-state-title it-state-desc" xmlns="http://www.w3.org/2000/svg">
<title id="it-title">Northwind Retail current IT landscape</title> <title id="it-state-title">Northwind Retail current IT landscape</title>
<desc id="it-desc">Three zones show collection, processing, and dissemination through manual file handoffs.</desc> <desc id="it-state-desc">Three zones show collection, processing, and dissemination through manual file handoffs.</desc>
<defs> <defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/></marker> <marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#2e5aa8"/></marker>
@@ -58,7 +58,9 @@
<p class="eyebrow">Layer stack · Diagram Design</p> <p class="eyebrow">Layer stack · Diagram Design</p>
<h1>AI app stack · Where the work actually happens</h1> <h1>AI app stack · Where the work actually happens</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="layers-dark-title layers-dark-desc">
<title id="layers-dark-title">AI app stack · Where the work actually happens</title>
<desc id="layers-dark-desc">Layer stack showing model weights, SDK, prompts, agent harness, and UI surface, with the agent harness highlighted as the focal layer.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="layers-full-title layers-full-desc">
<title id="layers-full-title">AI app stack · Where the work actually happens</title>
<desc id="layers-full-desc">Layer stack showing model weights, SDK, prompts, agent harness, and UI surface, with the agent harness highlighted as the focal layer.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Layer stack · Diagram Design</p> <p class="eyebrow">Layer stack · Diagram Design</p>
<h1>AI app stack · Where the work actually happens</h1> <h1>AI app stack · Where the work actually happens</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="layers-title layers-desc">
<title id="layers-title">AI app stack · Where the work actually happens</title>
<desc id="layers-desc">Layer stack showing model weights, SDK, prompts, agent harness, and UI surface, with the agent harness highlighted as the focal layer.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -20,7 +20,9 @@
<p class="eyebrow">Line · Diagram Design</p> <p class="eyebrow">Line · Diagram Design</p>
<h1>Weekly signups · Organic leads the growth</h1> <h1>Weekly signups · Organic leads the growth</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="line-dark-title line-dark-desc">
<title id="line-dark-title">Weekly signups · Organic leads the growth</title>
<desc id="line-dark-desc">Line chart showing weekly signups from organic, direct, and referral channels across weeks W1 through W8.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -36,7 +36,9 @@
<p class="subtitle">Signup volume by acquisition channel over eight weeks. Organic search is both the largest and fastest-growing channel; Direct is the stable baseline.</p> <p class="subtitle">Signup volume by acquisition channel over eight weeks. Organic search is both the largest and fastest-growing channel; Direct is the stable baseline.</p>
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="line-full-title line-full-desc">
<title id="line-full-title">Weekly signups · Organic leads the growth</title>
<desc id="line-full-desc">Line chart showing weekly signups from organic, direct, and referral channels across weeks W1 through W8.</desc>
<defs><pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern></defs> <defs><pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern></defs>
<rect width="100%" height="100%" fill="#f5f5f5"/> <rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/> <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
@@ -20,7 +20,9 @@
<p class="eyebrow">Line · Diagram Design</p> <p class="eyebrow">Line · Diagram Design</p>
<h1>Weekly signups · Organic leads the growth</h1> <h1>Weekly signups · Organic leads the growth</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="line-title line-desc">
<title id="line-title">Weekly signups · Organic leads the growth</title>
<desc id="line-desc">Line chart showing weekly signups from organic, direct, and referral channels across weeks W1 through W8.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -36,9 +36,9 @@
<p class="eyebrow">Loop · Diagram Design</p> <p class="eyebrow">Loop · Diagram Design</p>
<h1>The self-improving loop</h1> <h1>The self-improving loop</h1>
<svg viewBox="0 0 1040 680" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="loop-title loop-desc"> <svg viewBox="0 0 1040 680" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="loop-dark-title loop-dark-desc">
<title id="loop-title">The self-improving loop</title> <title id="loop-dark-title">The self-improving loop</title>
<desc id="loop-desc">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.</desc> <desc id="loop-dark-desc">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.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/></pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
@@ -56,9 +56,9 @@
</header> </header>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1040 680" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="loop-title loop-desc"> <svg viewBox="0 0 1040 680" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="loop-full-title loop-full-desc">
<title id="loop-title">The self-improving loop</title> <title id="loop-full-title">The self-improving loop</title>
<desc id="loop-desc">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.</desc> <desc id="loop-full-desc">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.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
@@ -173,10 +173,10 @@
viewBox="0 0 1040 680" viewBox="0 0 1040 680"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
role="img" role="img"
aria-labelledby="loop-title loop-desc" aria-labelledby="loop-terminal-title loop-terminal-desc"
> >
<title id="loop-title">The self-improving loop</title> <title id="loop-terminal-title">The self-improving loop</title>
<desc id="loop-desc"> <desc id="loop-terminal-desc">
Six stations flow clockwise from Capture through Learn and back to Six stations flow clockwise from Capture through Learn and back to
Capture. Each station writes shared state into one central memory Capture. Each station writes shared state into one central memory
hub, with Decide highlighted as the human approval gate. hub, with Decide highlighted as the human approval gate.
@@ -37,9 +37,9 @@
<p class="eyebrow">Medallion · Diagram Design</p> <p class="eyebrow">Medallion · Diagram Design</p>
<h1>Five-tier e-commerce analytics storage</h1> <h1>Five-tier e-commerce analytics storage</h1>
<svg viewBox="0 0 1040 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="medallion-title medallion-desc"> <svg viewBox="0 0 1040 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="medallion-dark-title medallion-dark-desc">
<title id="medallion-title">Five-tier e-commerce analytics medallion</title> <title id="medallion-dark-title">Five-tier e-commerce analytics medallion</title>
<desc id="medallion-desc">Clickstream events and order records move from raw storage through anonymized, staging, and aggregated tiers before lifecycle archiving.</desc> <desc id="medallion-dark-desc">Clickstream events and order records move from raw storage through anonymized, staging, and aggregated tiers before lifecycle archiving.</desc>
<defs> <defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker> <marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker>
@@ -57,9 +57,9 @@
</header> </header>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1040 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="medallion-title medallion-desc"> <svg viewBox="0 0 1040 548" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="medallion-full-title medallion-full-desc">
<title id="medallion-title">Five-tier e-commerce analytics medallion</title> <title id="medallion-full-title">Five-tier e-commerce analytics medallion</title>
<desc id="medallion-desc">Clickstream events and order records move from raw storage through anonymized, staging, and aggregated tiers before lifecycle archiving.</desc> <desc id="medallion-full-desc">Clickstream events and order records move from raw storage through anonymized, staging, and aggregated tiers before lifecycle archiving.</desc>
<defs> <defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker> <marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#eb6c36"/></marker>
@@ -58,7 +58,9 @@
<p class="eyebrow">Nested · Diagram Design</p> <p class="eyebrow">Nested · Diagram Design</p>
<h1>The CLAUDE.md Hierarchy</h1> <h1>The CLAUDE.md Hierarchy</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="nested-dark-title nested-dark-desc">
<title id="nested-dark-title">The CLAUDE.md Hierarchy</title>
<desc id="nested-dark-desc">Nested diagram showing how project CLAUDE.md instructions inherit broader scopes from the global, vault, business, and marketing levels.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="nested-full-title nested-full-desc">
<title id="nested-full-title">The CLAUDE.md Hierarchy</title>
<desc id="nested-full-desc">Nested diagram showing how project CLAUDE.md instructions inherit broader scopes from the global, vault, business, and marketing levels.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Nested · Diagram Design</p> <p class="eyebrow">Nested · Diagram Design</p>
<h1>The CLAUDE.md Hierarchy</h1> <h1>The CLAUDE.md Hierarchy</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="nested-title nested-desc">
<title id="nested-title">The CLAUDE.md Hierarchy</title>
<desc id="nested-desc">Nested diagram showing how project CLAUDE.md instructions inherit broader scopes from the global, vault, business, and marketing levels.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -3,8 +3,8 @@
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0} *,*::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} :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}} 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}}
</style></head><body><div class="frame"><p class="eyebrow">Org chart · Diagram Design</p><h1>Agent team responsibility map</h1><p class="subtitle">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.</p><svg viewBox="0 0 1040 620" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc"> </style></head><body><div class="frame"><p class="eyebrow">Org chart · Diagram Design</p><h1>Agent team responsibility map</h1><p class="subtitle">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.</p><svg viewBox="0 0 1040 620" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="org-chart-dark-title org-chart-dark-desc">
<title id="title">Agent team org chart</title><desc id="desc">Org chart showing a command center routing work to specialist agents and escalation owners.</desc> <title id="org-chart-dark-title">Agent team org chart</title><desc id="org-chart-dark-desc">Org chart showing a command center routing work to specialist agents and escalation owners.</desc>
<rect width="1040" height="620" fill="#2d3142"/> <rect width="1040" height="620" fill="#2d3142"/>
<defs><marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#bfc0c0"/></marker></defs> <defs><marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#bfc0c0"/></marker></defs>
<text x="40" y="64" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".16em">COMMAND CENTER</text> <text x="40" y="64" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".16em">COMMAND CENTER</text>
@@ -42,4 +42,4 @@ body{font-family:var(--sans);background:var(--paper);color:var(--ink);min-height
<rect x="72" y="480" width="896" height="48" rx="6" fill="#2d3142"/><rect x="72" y="480" width="896" height="48" rx="6" fill="rgba(245,245,245,.04)" stroke="#8e98ac" stroke-dasharray="4,4"/> <rect x="72" y="480" width="896" height="48" rx="6" fill="#2d3142"/><rect x="72" y="480" width="896" height="48" rx="6" fill="rgba(245,245,245,.04)" stroke="#8e98ac" stroke-dasharray="4,4"/>
<text x="96" y="508" fill="#f5f5f5" font-family="'Geist',sans-serif" font-size="12" font-weight="600">Setup gaps stay visible:</text><text x="244" y="508" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9">specialists without Slack bots · approval gates · backend name mismatches</text> <text x="96" y="508" fill="#f5f5f5" font-family="'Geist',sans-serif" font-size="12" font-weight="600">Setup gaps stay visible:</text><text x="244" y="508" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9">specialists without Slack bots · approval gates · backend name mismatches</text>
<line x1="40" y1="560" x2="1000" y2="560" stroke="rgba(245,245,245,.14)"/><text x="40" y="584" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".14em">LEGEND</text><rect x="132" y="572" width="16" height="12" rx="2" fill="rgba(240,138,89,.10)" stroke="#f08a59"/><text x="156" y="582" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9">front door</text><rect x="288" y="572" width="16" height="12" rx="2" fill="#393e53" stroke="#f5f5f5"/><text x="312" y="582" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9">pod / owner</text><rect x="452" y="572" width="16" height="12" rx="2" fill="rgba(245,245,245,.04)" stroke="#8e98ac" stroke-dasharray="4,4"/><text x="476" y="582" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9">needs setup / gap</text> <line x1="40" y1="560" x2="1000" y2="560" stroke="rgba(245,245,245,.14)"/><text x="40" y="584" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".14em">LEGEND</text><rect x="132" y="572" width="16" height="12" rx="2" fill="rgba(240,138,89,.10)" stroke="#f08a59"/><text x="156" y="582" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9">front door</text><rect x="288" y="572" width="16" height="12" rx="2" fill="#393e53" stroke="#f5f5f5"/><text x="312" y="582" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9">pod / owner</text><rect x="452" y="572" width="16" height="12" rx="2" fill="rgba(245,245,245,.04)" stroke="#8e98ac" stroke-dasharray="4,4"/><text x="476" y="582" fill="#bfc0c0" font-family="'Geist Mono',monospace" font-size="9">needs setup / gap</text>
</svg></div></body></html> </svg></div></body></html>
@@ -3,8 +3,8 @@
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0} *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{--paper:#f5f5f5;--paper-2:#fff;--ink:#2d3142;--muted:#4f5d75;--soft:#7a8399;--rule:rgba(45,49,66,.12);--accent:#eb6c36;--accent-tint:rgba(235,108,54,.08);--link:#2e5aa8;--sans:'Geist',system-ui,sans-serif;--serif:'Instrument Serif',serif;--mono:'Geist Mono',ui-monospace,monospace} :root{--paper:#f5f5f5;--paper-2:#fff;--ink:#2d3142;--muted:#4f5d75;--soft:#7a8399;--rule:rgba(45,49,66,.12);--accent:#eb6c36;--accent-tint:rgba(235,108,54,.08);--link:#2e5aa8;--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:#fff;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}} 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:#fff;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}}
</style></head><body><div class="frame"><p class="eyebrow">Org chart · Diagram Design</p><h1>Agent team responsibility map</h1><p class="subtitle">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.</p><svg viewBox="0 0 1040 620" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc"> </style></head><body><div class="frame"><p class="eyebrow">Org chart · Diagram Design</p><h1>Agent team responsibility map</h1><p class="subtitle">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.</p><svg viewBox="0 0 1040 620" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="org-chart-full-title org-chart-full-desc">
<title id="title">Agent team org chart</title><desc id="desc">Org chart showing a command center routing work to specialist agents and escalation owners.</desc> <title id="org-chart-full-title">Agent team org chart</title><desc id="org-chart-full-desc">Org chart showing a command center routing work to specialist agents and escalation owners.</desc>
<rect width="1040" height="620" fill="#f5f5f5"/> <rect width="1040" height="620" fill="#f5f5f5"/>
<defs><marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#4f5d75"/></marker></defs> <defs><marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#4f5d75"/></marker></defs>
<text x="40" y="64" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".16em">COMMAND CENTER</text> <text x="40" y="64" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".16em">COMMAND CENTER</text>
@@ -42,4 +42,4 @@ body{font-family:var(--sans);background:var(--paper);color:var(--ink);min-height
<rect x="72" y="480" width="896" height="48" rx="6" fill="#f5f5f5"/><rect x="72" y="480" width="896" height="48" rx="6" fill="rgba(45,49,66,.02)" stroke="#7a8399" stroke-dasharray="4,4"/> <rect x="72" y="480" width="896" height="48" rx="6" fill="#f5f5f5"/><rect x="72" y="480" width="896" height="48" rx="6" fill="rgba(45,49,66,.02)" stroke="#7a8399" stroke-dasharray="4,4"/>
<text x="96" y="508" fill="#2d3142" font-family="'Geist',sans-serif" font-size="12" font-weight="600">Setup gaps stay visible:</text><text x="244" y="508" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">specialists without Slack bots · approval gates · backend name mismatches</text> <text x="96" y="508" fill="#2d3142" font-family="'Geist',sans-serif" font-size="12" font-weight="600">Setup gaps stay visible:</text><text x="244" y="508" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">specialists without Slack bots · approval gates · backend name mismatches</text>
<line x1="40" y1="560" x2="1000" y2="560" stroke="rgba(45,49,66,.12)"/><text x="40" y="584" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".14em">LEGEND</text><rect x="132" y="572" width="16" height="12" rx="2" fill="rgba(235,108,54,.08)" stroke="#eb6c36"/><text x="156" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">front door</text><rect x="288" y="572" width="16" height="12" rx="2" fill="#ffffff" stroke="#2d3142"/><text x="312" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">pod / owner</text><rect x="452" y="572" width="16" height="12" rx="2" fill="rgba(45,49,66,.02)" stroke="#7a8399" stroke-dasharray="4,4"/><text x="476" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">needs setup / gap</text> <line x1="40" y1="560" x2="1000" y2="560" stroke="rgba(45,49,66,.12)"/><text x="40" y="584" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".14em">LEGEND</text><rect x="132" y="572" width="16" height="12" rx="2" fill="rgba(235,108,54,.08)" stroke="#eb6c36"/><text x="156" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">front door</text><rect x="288" y="572" width="16" height="12" rx="2" fill="#ffffff" stroke="#2d3142"/><text x="312" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">pod / owner</text><rect x="452" y="572" width="16" height="12" rx="2" fill="rgba(45,49,66,.02)" stroke="#7a8399" stroke-dasharray="4,4"/><text x="476" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">needs setup / gap</text>
</svg><div class="cards"><article class="card"><h2>Use when</h2><p>The reader needs to know who owns what, where to route work, and which roles are active vs. still being wired.</p></article><article class="card"><h2>Keep nodes short</h2><p>Name, invocation path, and 2–4 scope words. Put detailed operating rules below the figure.</p></article><article class="card"><h2>Show gaps</h2><p>Unavailable owners and missing routes should be dashed, not hidden. They are operationally useful.</p></article></div></div></body></html> </svg><div class="cards"><article class="card"><h2>Use when</h2><p>The reader needs to know who owns what, where to route work, and which roles are active vs. still being wired.</p></article><article class="card"><h2>Keep nodes short</h2><p>Name, invocation path, and 2–4 scope words. Put detailed operating rules below the figure.</p></article><article class="card"><h2>Show gaps</h2><p>Unavailable owners and missing routes should be dashed, not hidden. They are operationally useful.</p></article></div></div></body></html>
@@ -3,8 +3,8 @@
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0} *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{--paper:#f5f5f5;--paper-2:#fff;--ink:#2d3142;--muted:#4f5d75;--soft:#7a8399;--rule:rgba(45,49,66,.12);--accent:#eb6c36;--accent-tint:rgba(235,108,54,.08);--link:#2e5aa8;--sans:'Geist',system-ui,sans-serif;--serif:'Instrument Serif',serif;--mono:'Geist Mono',ui-monospace,monospace} :root{--paper:#f5f5f5;--paper-2:#fff;--ink:#2d3142;--muted:#4f5d75;--soft:#7a8399;--rule:rgba(45,49,66,.12);--accent:#eb6c36;--accent-tint:rgba(235,108,54,.08);--link:#2e5aa8;--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:#fff;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}} 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:#fff;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}}
</style></head><body><div class="frame"><p class="eyebrow">Org chart · Diagram Design</p><h1>Agent team responsibility map</h1><p class="subtitle">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.</p><svg viewBox="0 0 1040 620" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc"> </style></head><body><div class="frame"><p class="eyebrow">Org chart · Diagram Design</p><h1>Agent team responsibility map</h1><p class="subtitle">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.</p><svg viewBox="0 0 1040 620" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="org-chart-title org-chart-desc">
<title id="title">Agent team org chart</title><desc id="desc">Org chart showing a command center routing work to specialist agents and escalation owners.</desc> <title id="org-chart-title">Agent team org chart</title><desc id="org-chart-desc">Org chart showing a command center routing work to specialist agents and escalation owners.</desc>
<rect width="1040" height="620" fill="#f5f5f5"/> <rect width="1040" height="620" fill="#f5f5f5"/>
<defs><marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#4f5d75"/></marker></defs> <defs><marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#4f5d75"/></marker></defs>
<text x="40" y="64" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".16em">COMMAND CENTER</text> <text x="40" y="64" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".16em">COMMAND CENTER</text>
@@ -42,4 +42,4 @@ body{font-family:var(--sans);background:var(--paper);color:var(--ink);min-height
<rect x="72" y="480" width="896" height="48" rx="6" fill="#f5f5f5"/><rect x="72" y="480" width="896" height="48" rx="6" fill="rgba(45,49,66,.02)" stroke="#7a8399" stroke-dasharray="4,4"/> <rect x="72" y="480" width="896" height="48" rx="6" fill="#f5f5f5"/><rect x="72" y="480" width="896" height="48" rx="6" fill="rgba(45,49,66,.02)" stroke="#7a8399" stroke-dasharray="4,4"/>
<text x="96" y="508" fill="#2d3142" font-family="'Geist',sans-serif" font-size="12" font-weight="600">Setup gaps stay visible:</text><text x="244" y="508" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">specialists without Slack bots · approval gates · backend name mismatches</text> <text x="96" y="508" fill="#2d3142" font-family="'Geist',sans-serif" font-size="12" font-weight="600">Setup gaps stay visible:</text><text x="244" y="508" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">specialists without Slack bots · approval gates · backend name mismatches</text>
<line x1="40" y1="560" x2="1000" y2="560" stroke="rgba(45,49,66,.12)"/><text x="40" y="584" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".14em">LEGEND</text><rect x="132" y="572" width="16" height="12" rx="2" fill="rgba(235,108,54,.08)" stroke="#eb6c36"/><text x="156" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">front door</text><rect x="288" y="572" width="16" height="12" rx="2" fill="#ffffff" stroke="#2d3142"/><text x="312" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">pod / owner</text><rect x="452" y="572" width="16" height="12" rx="2" fill="rgba(45,49,66,.02)" stroke="#7a8399" stroke-dasharray="4,4"/><text x="476" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">needs setup / gap</text> <line x1="40" y1="560" x2="1000" y2="560" stroke="rgba(45,49,66,.12)"/><text x="40" y="584" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9" letter-spacing=".14em">LEGEND</text><rect x="132" y="572" width="16" height="12" rx="2" fill="rgba(235,108,54,.08)" stroke="#eb6c36"/><text x="156" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">front door</text><rect x="288" y="572" width="16" height="12" rx="2" fill="#ffffff" stroke="#2d3142"/><text x="312" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">pod / owner</text><rect x="452" y="572" width="16" height="12" rx="2" fill="rgba(45,49,66,.02)" stroke="#7a8399" stroke-dasharray="4,4"/><text x="476" y="582" fill="#4f5d75" font-family="'Geist Mono',monospace" font-size="9">needs setup / gap</text>
</svg></div></body></html> </svg></div></body></html>
@@ -17,7 +17,9 @@
<div class="frame"> <div class="frame">
<p class="eyebrow">Process · Diagram Design</p> <p class="eyebrow">Process · Diagram Design</p>
<h1>Order fulfillment across four teams</h1> <h1>Order fulfillment across four teams</h1>
<svg viewBox="0 0 1064 436" xmlns="http://www.w3.org/2000/svg" aria-label="Order fulfillment process from customer order to support closure"> <svg viewBox="0 0 1064 436" xmlns="http://www.w3.org/2000/svg" aria-label="Order fulfillment process from customer order to support closure" role="img" aria-labelledby="process-dark-title process-dark-desc">
<title id="process-dark-title">Order fulfillment across four teams</title>
<desc id="process-dark-desc">Process diagram showing an order moving through customer, support, warehouse, and finance ownership from placement to close.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="var(--dot)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="var(--dot)"/></pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker>
@@ -20,7 +20,9 @@
<h1>Order fulfillment across four teams</h1> <h1>Order fulfillment across four teams</h1>
<p class="subtitle">One order moves through customer, support, warehouse, and finance ownership, while the payload chips show what each handoff carries.</p> <p class="subtitle">One order moves through customer, support, warehouse, and finance ownership, while the payload chips show what each handoff carries.</p>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1064 436" xmlns="http://www.w3.org/2000/svg" aria-label="Order fulfillment process from customer order to support closure"> <svg viewBox="0 0 1064 436" xmlns="http://www.w3.org/2000/svg" aria-label="Order fulfillment process from customer order to support closure" role="img" aria-labelledby="process-full-title process-full-desc">
<title id="process-full-title">Order fulfillment across four teams</title>
<desc id="process-full-desc">Process diagram showing an order moving through customer, support, warehouse, and finance ownership from placement to close.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="var(--dot)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="var(--dot)"/></pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker>
@@ -17,7 +17,9 @@
<div class="frame"> <div class="frame">
<p class="eyebrow">Process · Diagram Design</p> <p class="eyebrow">Process · Diagram Design</p>
<h1>Order fulfillment across four teams</h1> <h1>Order fulfillment across four teams</h1>
<svg viewBox="0 0 1064 436" xmlns="http://www.w3.org/2000/svg" aria-label="Order fulfillment process from customer order to support closure"> <svg viewBox="0 0 1064 436" xmlns="http://www.w3.org/2000/svg" aria-label="Order fulfillment process from customer order to support closure" role="img" aria-labelledby="process-title process-desc">
<title id="process-title">Order fulfillment across four teams</title>
<desc id="process-desc">Process diagram showing an order moving through customer, support, warehouse, and finance ownership from placement to close.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="var(--dot)"/></pattern> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="var(--dot)"/></pattern>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="var(--muted)"/></marker>
@@ -58,7 +58,9 @@
<p class="eyebrow">Pyramid · Diagram Design</p> <p class="eyebrow">Pyramid · Diagram Design</p>
<h1>Content pyramid · what compounds</h1> <h1>Content pyramid · what compounds</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="pyramid-dark-title pyramid-dark-desc">
<title id="pyramid-dark-title">Content pyramid · what compounds</title>
<desc id="pyramid-dark-desc">Content pyramid showing short posts, essays, long-form guides, and a flagship book ordered by shipping cadence and leverage.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="pyramid-full-title pyramid-full-desc">
<title id="pyramid-full-title">Content pyramid · what compounds</title>
<desc id="pyramid-full-desc">Content pyramid showing short posts, essays, long-form guides, and a flagship book ordered by shipping cadence and leverage.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Pyramid · Diagram Design</p> <p class="eyebrow">Pyramid · Diagram Design</p>
<h1>Content pyramid · what compounds</h1> <h1>Content pyramid · what compounds</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="pyramid-title pyramid-desc">
<title id="pyramid-title">Content pyramid · what compounds</title>
<desc id="pyramid-desc">Content pyramid showing short posts, essays, long-form guides, and a flagship book ordered by shipping cadence and leverage.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -57,7 +57,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 660" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 660" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="quadrant-consultant-title quadrant-consultant-desc">
<title id="quadrant-consultant-title">Workplace 2030 · Remote × AI automation</title>
<desc id="quadrant-consultant-desc">Scenario matrix showing four workplace futures across remote-to-in-person and human-to-AI axes, with agent teams as the headline bet.</desc>
<defs> <defs>
<!-- Double-ended axis markers --> <!-- Double-ended axis markers -->
<marker id="axis-end" markerWidth="9" markerHeight="7" refX="8" refY="3.5" orient="auto"> <marker id="axis-end" markerWidth="9" markerHeight="7" refX="8" refY="3.5" orient="auto">
@@ -58,7 +58,9 @@
<p class="eyebrow">Quadrant · Diagram Design</p> <p class="eyebrow">Quadrant · Diagram Design</p>
<h1>Content ideas · Impact × Effort</h1> <h1>Content ideas · Impact × Effort</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="quadrant-dark-title quadrant-dark-desc">
<title id="quadrant-dark-title">Content ideas · Impact × Effort</title>
<desc id="quadrant-dark-desc">Impact-effort matrix showing eight content projects across do first, major projects, quick wins, and avoid quadrants.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="quadrant-full-title quadrant-full-desc">
<title id="quadrant-full-title">Content ideas · Impact × Effort</title>
<desc id="quadrant-full-desc">Impact-effort matrix showing eight content projects across do first, major projects, quick wins, and avoid quadrants.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Quadrant · Diagram Design</p> <p class="eyebrow">Quadrant · Diagram Design</p>
<h1>Content ideas · Impact × Effort</h1> <h1>Content ideas · Impact × Effort</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="quadrant-title quadrant-desc">
<title id="quadrant-title">Content ideas · Impact × Effort</title>
<desc id="quadrant-desc">Impact-effort matrix showing eight content projects across do first, major projects, quick wins, and avoid quadrants.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Radar · Diagram Design</p> <p class="eyebrow">Radar · Diagram Design</p>
<h1>Storage backends · Capability radar</h1> <h1>Storage backends · Capability radar</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="radar-dark-title radar-dark-desc">
<title id="radar-dark-title">Storage backends · Capability radar</title>
<desc id="radar-dark-desc">Radar chart comparing MinIO, Amazon S3, Ceph, and Google Cloud Storage across five storage capabilities.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -41,7 +41,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="radar-full-title radar-full-desc">
<title id="radar-full-title">Storage backends · Capability radar</title>
<desc id="radar-full-desc">Radar chart comparing MinIO, Amazon S3, Ceph, and Google Cloud Storage across five storage capabilities.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Radar · Diagram Design</p> <p class="eyebrow">Radar · Diagram Design</p>
<h1>Storage backends · Capability radar</h1> <h1>Storage backends · Capability radar</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="radar-title radar-desc">
<title id="radar-title">Storage backends · Capability radar</title>
<desc id="radar-desc">Radar chart comparing MinIO, Amazon S3, Ceph, and Google Cloud Storage across five storage capabilities.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -22,7 +22,9 @@
<!-- X: 0-20 deploys/week → 880px. x = 80 + f/20*880 = 80+44*f --> <!-- X: 0-20 deploys/week → 880px. x = 80 + f/20*880 = 80+44*f -->
<!-- Y: 0-24 days lead time → 380px. y = 420 - lt/24*380. High lt = high y (worse) --> <!-- Y: 0-24 days lead time → 380px. y = 420 - lt/24*380. High lt = high y (worse) -->
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="scatter-dark-title scatter-dark-desc">
<title id="scatter-dark-title">Deploy frequency vs. lead time · 12 teams</title>
<desc id="scatter-dark-desc">Scatter plot showing twelve engineering teams by deploy frequency and lead time, with Platform in the best-performing quadrant.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -36,7 +36,9 @@
<p class="subtitle">Each point is an engineering team. Moving right means deploying more often; moving down means shipping faster. The Platform team occupies the lower-right — the ideal quadrant.</p> <p class="subtitle">Each point is an engineering team. Moving right means deploying more often; moving down means shipping faster. The Platform team occupies the lower-right — the ideal quadrant.</p>
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="scatter-full-title scatter-full-desc">
<title id="scatter-full-title">Deploy frequency vs. lead time · 12 teams</title>
<desc id="scatter-full-desc">Scatter plot showing twelve engineering teams by deploy frequency and lead time, with Platform in the best-performing quadrant.</desc>
<defs><pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern></defs> <defs><pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/></pattern></defs>
<rect width="100%" height="100%" fill="#f5f5f5"/> <rect width="100%" height="100%" fill="#f5f5f5"/>
<rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/> <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
@@ -22,7 +22,9 @@
<!-- X: 0-20 deploys/week → 880px. x = 80 + f/20*880 = 80+44*f --> <!-- X: 0-20 deploys/week → 880px. x = 80 + f/20*880 = 80+44*f -->
<!-- Y: 0-24 days lead time → 380px. y = 420 - lt/24*380. High lt = high y (worse) --> <!-- Y: 0-24 days lead time → 380px. y = 420 - lt/24*380. High lt = high y (worse) -->
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="scatter-title scatter-desc">
<title id="scatter-title">Deploy frequency vs. lead time · 12 teams</title>
<desc id="scatter-desc">Scatter plot showing twelve engineering teams by deploy frequency and lead time, with Platform in the best-performing quadrant.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Sequence · Diagram Design</p> <p class="eyebrow">Sequence · Diagram Design</p>
<h1>Article request, cold cache</h1> <h1>Article request, cold cache</h1>
<svg viewBox="0 0 1000 584" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 584" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="sequence-dark-title sequence-dark-desc">
<title id="sequence-dark-title">Article request, cold cache</title>
<desc id="sequence-dark-desc">Sequence diagram showing a cold-cache article request moving from reader and browser through Cloudflare to an Astro origin and analytics beacon.</desc>
<defs> <defs>
<!-- Dot grid background --> <!-- Dot grid background -->
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
@@ -183,7 +183,9 @@
<!-- Sequence Diagram --> <!-- Sequence Diagram -->
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 584" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 584" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="sequence-full-title sequence-full-desc">
<title id="sequence-full-title">Article request, cold cache</title>
<desc id="sequence-full-desc">Sequence diagram showing a cold-cache article request moving from reader and browser through Cloudflare to an Astro origin and analytics beacon.</desc>
<defs> <defs>
<!-- Dot grid background --> <!-- Dot grid background -->
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
@@ -58,9 +58,9 @@
<p class="eyebrow">Sequence · Diagram Design · Special</p> <p class="eyebrow">Sequence · Diagram Design · Special</p>
<h1>Bearer call with refresh</h1> <h1>Bearer call with refresh</h1>
<svg viewBox="0 0 960 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="seq-title seq-desc"> <svg viewBox="0 0 960 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="sequence-oauth-dark-title sequence-oauth-dark-desc">
<title id="seq-title">Bearer call with refresh</title> <title id="sequence-oauth-dark-title">Bearer call with refresh</title>
<desc id="seq-desc">Client calls API with a bearer token. An ALT fragment shows either a valid 200 response or a 401 path that refreshes via Auth and retries.</desc> <desc id="sequence-oauth-dark-desc">Client calls API with a bearer token. An ALT fragment shows either a valid 200 response or a 401 path that refreshes via Auth and retries.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -181,9 +181,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 960 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="seq-title seq-desc"> <svg viewBox="0 0 960 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="sequence-oauth-full-title sequence-oauth-full-desc">
<title id="seq-title">Bearer call with refresh</title> <title id="sequence-oauth-full-title">Bearer call with refresh</title>
<desc id="seq-desc">Client calls API with a bearer token. An ALT fragment shows either a valid 200 response or a 401 path that refreshes via Auth and retries.</desc> <desc id="sequence-oauth-full-desc">Client calls API with a bearer token. An ALT fragment shows either a valid 200 response or a 401 path that refreshes via Auth and retries.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,9 +58,9 @@
<p class="eyebrow">Sequence · Diagram Design · Special</p> <p class="eyebrow">Sequence · Diagram Design · Special</p>
<h1>Bearer call with refresh</h1> <h1>Bearer call with refresh</h1>
<svg viewBox="0 0 960 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="seq-title seq-desc"> <svg viewBox="0 0 960 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="sequence-oauth-title sequence-oauth-desc">
<title id="seq-title">Bearer call with refresh</title> <title id="sequence-oauth-title">Bearer call with refresh</title>
<desc id="seq-desc">Client calls API with a bearer token. An ALT fragment shows either a valid 200 response or a 401 path that refreshes via Auth and retries.</desc> <desc id="sequence-oauth-desc">Client calls API with a bearer token. An ALT fragment shows either a valid 200 response or a 401 path that refreshes via Auth and retries.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Sequence · Diagram Design</p> <p class="eyebrow">Sequence · Diagram Design</p>
<h1>Article request, cold cache</h1> <h1>Article request, cold cache</h1>
<svg viewBox="0 0 1000 584" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 584" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="sequence-title sequence-desc">
<title id="sequence-title">Article request, cold cache</title>
<desc id="sequence-desc">Sequence diagram showing a cold-cache article request moving from reader and browser through Cloudflare to an Astro origin and analytics beacon.</desc>
<defs> <defs>
<!-- Dot grid background --> <!-- Dot grid background -->
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
@@ -58,7 +58,9 @@
<p class="eyebrow">State machine · Diagram Design</p> <p class="eyebrow">State machine · Diagram Design</p>
<h1>Article lifecycle</h1> <h1>Article lifecycle</h1>
<svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="state-dark-title state-dark-desc">
<title id="state-dark-title">Article lifecycle</title>
<desc id="state-dark-desc">State machine showing an article moving from Draft through In Review and Published to Archived, including rejection and revision.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="state-full-title state-full-desc">
<title id="state-full-title">Article lifecycle</title>
<desc id="state-full-desc">State machine showing an article moving from Draft through In Review and Published to Archived, including rejection and revision.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">State machine · Diagram Design</p> <p class="eyebrow">State machine · Diagram Design</p>
<h1>Article lifecycle</h1> <h1>Article lifecycle</h1>
<svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 460" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="state-title state-desc">
<title id="state-title">Article lifecycle</title>
<desc id="state-desc">State machine showing an article moving from Draft through In Review and Published to Archived, including rejection and revision.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Swimlane · Diagram Design</p> <p class="eyebrow">Swimlane · Diagram Design</p>
<h1>Publishing an article</h1> <h1>Publishing an article</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="swimlane-dark-title swimlane-dark-desc">
<title id="swimlane-dark-title">Publishing an article</title>
<desc id="swimlane-dark-desc">Swimlane diagram showing an article moving from MDX draft through review, editing, approval, build, and Cloudflare Pages deployment.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="swimlane-full-title swimlane-full-desc">
<title id="swimlane-full-title">Publishing an article</title>
<desc id="swimlane-full-desc">Swimlane diagram showing an article moving from MDX draft through review, editing, approval, build, and Cloudflare Pages deployment.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Swimlane · Diagram Design</p> <p class="eyebrow">Swimlane · Diagram Design</p>
<h1>Publishing an article</h1> <h1>Publishing an article</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="swimlane-title swimlane-desc">
<title id="swimlane-title">Publishing an article</title>
<desc id="swimlane-desc">Swimlane diagram showing an article moving from MDX draft through review, editing, approval, build, and Cloudflare Pages deployment.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Timeline · Diagram Design</p> <p class="eyebrow">Timeline · Diagram Design</p>
<h1>Product launch · fourteen months</h1> <h1>Product launch · fourteen months</h1>
<svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="timeline-dark-title timeline-dark-desc">
<title id="timeline-dark-title">Product launch · fourteen months</title>
<desc id="timeline-dark-desc">Timeline showing product milestones from the first post in February 2025 through three design versions and the schematic skill in April 2026.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="timeline-full-title timeline-full-desc">
<title id="timeline-full-title">Product launch · fourteen months</title>
<desc id="timeline-full-desc">Timeline showing product milestones from the first post in February 2025 through three design versions and the schematic skill in April 2026.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Timeline · Diagram Design</p> <p class="eyebrow">Timeline · Diagram Design</p>
<h1>Product launch · fourteen months</h1> <h1>Product launch · fourteen months</h1>
<svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 420" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="timeline-title timeline-desc">
<title id="timeline-title">Product launch · fourteen months</title>
<desc id="timeline-desc">Timeline showing product milestones from the first post in February 2025 through three design versions and the schematic skill in April 2026.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Tree · Diagram Design</p> <p class="eyebrow">Tree · Diagram Design</p>
<h1>Claude Code skill taxonomy</h1> <h1>Claude Code skill taxonomy</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="tree-dark-title tree-dark-desc">
<title id="tree-dark-title">Claude Code skill taxonomy</title>
<desc id="tree-dark-desc">Tree diagram showing a Skills root branching into Design, Engineering, and Research categories and their leaf skills.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="tree-full-title tree-full-desc">
<title id="tree-full-title">Claude Code skill taxonomy</title>
<desc id="tree-full-desc">Tree diagram showing a Skills root branching into Design, Engineering, and Research categories and their leaf skills.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Tree · Diagram Design</p> <p class="eyebrow">Tree · Diagram Design</p>
<h1>Claude Code skill taxonomy</h1> <h1>Claude Code skill taxonomy</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="tree-title tree-desc">
<title id="tree-title">Claude Code skill taxonomy</title>
<desc id="tree-desc">Tree diagram showing a Skills root branching into Design, Engineering, and Research categories and their leaf skills.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Venn · Diagram Design</p> <p class="eyebrow">Venn · Diagram Design</p>
<h1>Good design · Desirable × Feasible × Viable</h1> <h1>Good design · Desirable × Feasible × Viable</h1>
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="venn-dark-title venn-dark-desc">
<title id="venn-dark-title">Good design · Desirable × Feasible × Viable</title>
<desc id="venn-dark-desc">Venn diagram showing desirable, feasible, and viable product qualities intersecting at shippable.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(245,245,245,0.10)"/>
@@ -39,7 +39,9 @@
</div> </div>
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="venn-full-title venn-full-desc">
<title id="venn-full-title">Good design · Desirable × Feasible × Viable</title>
<desc id="venn-full-desc">Venn diagram showing desirable, feasible, and viable product qualities intersecting at shippable.</desc>
<defs> <defs>
<pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"> <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
<circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/> <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
@@ -58,7 +58,9 @@
<p class="eyebrow">Venn · Diagram Design</p> <p class="eyebrow">Venn · Diagram Design</p>
<h1>Good design · Desirable × Feasible × Viable</h1> <h1>Good design · Desirable × Feasible × Viable</h1>
<svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 1000 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="venn-title venn-desc">
<title id="venn-title">Good design · Desirable × Feasible × Viable</title>
<desc id="venn-desc">Venn diagram showing desirable, feasible, and viable product qualities intersecting at shippable.</desc>
<defs> <defs>
<!-- Chained clips isolate the all-three intersection: clip to Desirable, then to Feasible, then fill via the third circle. --> <!-- Chained clips isolate the all-three intersection: clip to Desirable, then to Feasible, then fill via the third circle. -->
<clipPath id="clip-desirable"> <clipPath id="clip-desirable">
File diff suppressed because one or more lines are too long
@@ -58,7 +58,10 @@
<p class="eyebrow">[Type] · Diagram Design</p> <p class="eyebrow">[Type] · Diagram Design</p>
<h1>[Diagram title]</h1> <h1>[Diagram title]</h1>
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg"> <!-- Replace [diagram-slug] with a unique slug for this diagram before export. -->
<svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="[diagram-slug]-title [diagram-slug]-desc">
<title id="[diagram-slug]-title">[Diagram title]</title>
<desc id="[diagram-slug]-desc">[One sentence describing what the diagram shows]</desc>
<defs> <defs>
<marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker> <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#bfc0c0"/></marker>
<marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker> <marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0, 8 3, 0 6" fill="#f08a59"/></marker>
@@ -175,7 +175,10 @@
<!-- Main Diagram --> <!-- Main Diagram -->
<div class="diagram-container"> <div class="diagram-container">
<svg viewBox="0 0 1000 700" xmlns="http://www.w3.org/2000/svg"> <!-- Replace [diagram-slug] with a unique slug for this diagram before export. -->
<svg viewBox="0 0 1000 700" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="[diagram-slug]-title [diagram-slug]-desc">
<title id="[diagram-slug]-title">[Diagram title]</title>
<desc id="[diagram-slug]-desc">[One sentence describing what the diagram shows]</desc>
<defs> <defs>
<!-- OPTIONAL: dot-pattern background. Uncomment the <pattern> below and the second <rect> in the bg section to enable. --> <!-- OPTIONAL: dot-pattern background. Uncomment the <pattern> below and the second <rect> in the bg section to enable. -->

Some files were not shown because too many files have changed in this diff Show More