` remains at its pre-calculated height ($38\text{px}$).
+ - The text physically overflows the box boundary, and the expanded node overlaps adjacent nodes and arrows!
+2. **Cluster Header Overlap**:
+ - Applying `text-transform: uppercase`, `letter-spacing: 0.05em`, or `font-weight: 700` to `.cluster span` expands cluster titles beyond the header bounding box, forcing titles to wrap and crush the top row of nodes.
+3. **Font Loading Race Condition**:
+ - Rendering diagrams before web fonts (`Inter`) finish loading causes Dagre to measure bounding boxes using fallback system fonts. When `Inter` hydrates, glyph widths change, causing line wraps or clipped text.
+
+### The Constitutional Invariants for Mermaid CSS & Layout:
+1. **Never Apply Padding or Forced Flex to `foreignObject div`**:
+ ```css
+ .mermaid svg foreignObject,
+ .theater-content-surface svg foreignObject {
+ overflow: visible !important;
+ }
+
+ .mermaid svg foreignObject div,
+ .theater-content-surface svg foreignObject div {
+ display: inline-block !important;
+ text-align: center !important;
+ box-sizing: border-box !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ line-height: normal !important;
+ }
+ ```
+2. **Cluster Title Normalization**:
+ ```css
+ .mermaid svg .cluster text,
+ .mermaid svg .cluster span,
+ .theater-content-surface svg .cluster text,
+ .theater-content-surface svg .cluster span {
+ fill: var(--accent-cyan) !important;
+ color: var(--accent-cyan) !important;
+ font-weight: 600 !important;
+ font-size: 13px !important;
+ text-transform: none !important;
+ letter-spacing: normal !important;
+ }
+ ```
+3. **Node Typography Invariant**:
+ ```css
+ .mermaid svg .node .label,
+ .mermaid svg .node text,
+ .mermaid svg .node span,
+ .theater-content-surface svg .node .label,
+ .theater-content-surface svg .node text,
+ .theater-content-surface svg .node span {
+ fill: var(--text-main) !important;
+ color: var(--text-main) !important;
+ font-weight: 500 !important;
+ font-size: 14px !important;
+ }
+ ```
+4. **Font-Ready Synchronization**:
+ Always await font loading before invoking `window.mermaid.render()`:
+ ```javascript
+ if (document.fonts && document.fonts.ready) {
+ await document.fonts.ready;
+ }
+ ```
+5. **Raw Diagram Source Preservation**:
+ Store `data-mermaid-src="{escaped_mermaid}"` on every `` at compile time in `scripts/build-docs.py`. This ensures re-renders never attempt to parse previously hydrated SVG innerHTML.
+
+---
+
+## π 2D Interactive Canvas Zoom & Pan Standard (Card & Theater Mode)
+
+Both in-card viewports (`.canvas-viewport`) and full-screen Theater Mode (`#theater-modal`) adhere to a **unified matrix transform order**:
+
+### Transform Order Standard:
+```javascript
+surface.style.transform = `translate(${panX}px, ${panY}px) scale(${zoom})`;
+```
+- **Why `translate(X, Y) scale(Z)`**: Translating first means pan offsets are measured in screen pixels ($1:1$ drag sensitivity). Inverting to `scale(...) translate(...)` scales pan vectors by the zoom factor, resulting in erratic jumps during high zoom.
+- **Transform Origin**: Always `transform-origin: center center;` on `.canvas-content-surface` and `.theater-content-surface`.
+- **Drag Handling**: Suppress drag-panning when clicking interactive elements (`button`, `text`, `foreignObject`, `span`) to allow seamless text selection.
+- **Double-Click Launch**: Double-clicking anywhere on a `.canvas-viewport` automatically triggers Theater Mode.
+
+### Fullscreen Theater Mode Workbench (``):
+1. **Dynamic Fit Calculation**:
+ ```javascript
+ function calculateFitScale(svgEl) {
+ const availW = Math.max(300, (theaterViewport.clientWidth || window.innerWidth) - 64);
+ const availH = Math.max(200, (theaterViewport.clientHeight || window.innerHeight) - 64);
+ return Math.max(0.15, Math.min(Math.min(availW / vbW, availH / vbH), 3.5));
+ }
+ ```
+2. **Futuristic Capsule Close Button**: Glassmorphic capsule pill with SVG cross icon and `ESC `.
+3. **Anti-Dismissal Rule**: Clicking or releasing drags on the viewport surface NEVER dismisses the modal. Only explicit Close button clicks or `Escape` keypress dismisses.
+4. **Scroll Restoration**: Exact `window.scrollY` saved prior to open and restored instantly upon close.
+
+---
+
+## βοΈ Interactive Draggable Sidebar Resizer & Collapsible Rail Standard
+
+### Operational Invariants:
+1. **Collapsible Distraction-Free Reading**:
+ - Closed via `#sidebar-close-btn` inside sidebar or `#sidebar-dock-toggle` in header.
+ - When collapsed, `body.sidebar-collapsed` shifts `.sidebar` by `margin-left: calc(-1 * var(--sidebar-width)); opacity: 0; visibility: hidden;` and hides `.sidebar-resizer`.
+ - Floating reopen tab `#floating-sidebar-toggle` appears on the left edge (`top: calc(var(--topbar-height) + 14px); left: 14px;`).
+ - Global keyboard shortcuts: `βB`, `Ctrl+B`, or `[` toggle the rail instantly.
+ - State persisted in `localStorage.setItem('dp_sidebar_collapsed', 'true' / 'false')`.
+2. **Bounds Clamping**: Resizing strictly clamped between `MIN_WIDTH = 240px` and `MAX_WIDTH = 560px`.
+3. **Dragging Performance**: During drag, `body.resizing-sidebar` sets `cursor: col-resize !important; user-select: none !important;`.
+4. **Persistence**: Width choice is saved to `localStorage.setItem('dp_sidebar_width', width)`.
+5. **Double-Click Reset**: Double-clicking resets `--sidebar-width` to default `330px`.
+6. **Zero-Truncation Invariant**: Never clip navigation titles with single-line ellipses (`white-space: normal; word-break: break-word; flex-shrink: 0`).
+
+---
+
+## π± Commute Gadget Mobile Navigation Architecture
+
+1. On viewports $\le 1024\text{px}$, sidebar transitions into an off-canvas slide-out drawer (`width: min(86vw, 360px)`).
+2. **Stacking Context Invariant**: `#mobile-drawer-backdrop` (`z-index: 1100`) must be placed inside `.layout-container` right before `.sidebar` (`z-index: 1200`).
+3. **Sticky Scroll Invariant**: **Never use `overflow-x: hidden` on `html` or `body`**. Always use `overflow-x: clip;` to prevent breaking `position: sticky`.
+4. Wrap all `` elements in `` with horizontal touch scrolling and explicit min-width (`min-width: 520px`).
+
+---
+
+## π― Universal Delegated In-Page Navigation
+
+All in-page anchors (`a[href^="#"]`) use delegated event interception in `app.js`:
+1. Intercepts click and cancels native jump.
+2. Checks if target element or any ancestor is collapsed (`.pattern-chapter.is-collapsed` or closed `
`).
+3. Automatically uncollapses containing chapters, opens ``, and updates toggle buttons.
+4. Forces synchronous layout flush (`targetEl.getBoundingClientRect()`).
+5. Smoothly scrolls with exact 72px cushion:
+ ```javascript
+ const y = targetEl.getBoundingClientRect().top + window.pageYOffset - 72;
+ window.scrollTo({ top: y, behavior: 'smooth' });
+ ```
+6. Applies a temporary flash focus highlight (`flash-focus`) for 1800ms. Zero treasure hunting!
+
+---
+
+## β‘ Sub-10ms "Expand All" SLA
+
+When opening all 28 chapters simultaneously:
+- **Root-Cause Pitfall**: Synchronous execution of diagram render calls inside accordion `toggle` events freezes the CPU for seconds.
+- **The Protocol**: Guard accordion `toggle` listeners with `STATE.isBatchExpanding`:
+ ```javascript
+ STATE.isBatchExpanding = true;
+ document.querySelectorAll('.pattern-chapter').forEach(c => c.classList.remove('is-collapsed'));
+ document.querySelectorAll('.theory-details, .example-card').forEach(d => { d.open = true; });
+ setTimeout(() => {
+ STATE.isBatchExpanding = false;
+ renderVisibleDiagrams();
+ }, 50);
+ ```
+
+---
+
+## π Curated Web Audio Haptic System (`HapticAudio`)
+
+Tactile acoustic feedback synthesized purely via Web Audio API oscillators:
+
+| Interaction | Waveform | Frequency Ramp | Duration | Sensation |
+|---|---|---|---|---|
+| **Expand Chapter** | Sine | 540Hz β 880Hz | 38ms | Mechanical switch opening |
+| **Collapse Chapter** | Sine | 780Hz β 420Hz | 38ms | Snappy latch folding |
+| **Sidebar Drag / Toggle**| Triangle | 440Hz β 760Hz | 50ms | Smooth sliding panel reveal |
+| **Copy Code** | Arpeggiated Sine | C6 (1046Hz) + E6 (1318Hz) | 90ms | Celebratory success chime |
+| **Theme Change** | Triangle | 600Hz β 1200Hz | 60ms | Cosmic palette shift |
+| **Theater Launch** | Harmonic Sine | 440Hz β 880Hz | 70ms | Cinematic workbench focus |
+| **Search Open (βK)** | High-transient Sine | 1180Hz β 1480Hz | 40ms | Holographic HUD ping |
+
+---
+
+## π§ͺ 15-Gate Headless Automated Verification Suite
+
+Run before every commit or push:
+```bash
+make docs-test
+```
+
+1. **Core Assets Presence**: `index.html`, `style.css`, `app.js`, `catalog/manifest.json`.
+2. **Catalog Completeness & Search Index**: 28 chapters, 38 Python code implementations indexed.
+3. **Mermaid Label Escaping**: No unescaped `<` or `>` inside node labels.
+4. **CSS SVG Sizing Invariants**: No `width: auto !important` on `.mermaid svg`.
+5. **KaTeX Integration**: Delimiters, styles, and auto-render execution.
+6. **Draggable Sidebar Resizer**: Bounds clamping, `col-resize`, and `localStorage` persistence.
+7. **Mobile Drawer & Anti-Clobbering**: Sticky-safe `overflow-x: clip;` and z-index hierarchy.
+8. **Table & Touch Containment**: `.table-wrapper` with touch scrolling and `min-width: 520px`.
+9. **Relative Path Invariants**: All asset links use relative addressing (`./`) for `/DesignPatterns/` GitHub Pages.
+10. **Static Bundle Footprint**: Bundle size strictly $<25\text{MB}$.
+11. **Mermaid Diagram ID Uniqueness & Isolation**: 78+ unique IDs, isolated rendering, zero legacy footer links.
+12. **Unicode Monospace Box-Drawing Alignment**: 100% of ASCII and Unicode box tables and cards aligned.
+13. **Collapsible Details & Zero Raw HTML Block Escaping**: 100% semantic `` with valid summary and body.
+14. **Monospace Semantic Badging**: Framework and pattern badges valid and rendered.
+15. **Hyperlink Integrity & Local Path Prevention**: Zero `file://` or `/Users/` paths; zero raw `.md` or `.py` file links; zero external GitHub jumps for internal files; 100% internal fragment anchor resolution.
+
+---
+
+## π οΈ Canonical Developer Commands
+
+| Command | Purpose |
+|---|---|
+| `make help` | Interactive targets menu |
+| `make docs-build` | Compiles 28 chapters and generates hydrated static site in `_site/` |
+| `make docs-serve` | Serves documentation locally on `http://localhost:4000/` |
+| `make docs-test` | Runs the full 15-gate headless verification suite |
+| `make test-boxes` | Audits ASCII and Unicode box-drawing alignment |
+| `make format-boxes` | Realigns and formats all ASCII/Unicode boxes across the repository in place |
+| `make test` | Runs AST syntax compilation across all 38 Python implementations |
+| `make lint` | Runs Ruff linter + box alignment check |
+| `make ci` | Runs full CI audit suite locally (test + lint + docs-test) |
+| `make clean` | Cleans `_site/` and pycache artifacts |
+
+---
+
+## π GitHub Actions CI/CD Architecture
+
+- **`ci.yml`**: Triggers on `push` (`main`, `feature/**`) and `pull_request` (`main`). Runs canonical `make test`, `make lint`, and `make docs-test`.
+- **`docs-publish.yml`**: Triggers on `push` to `main`. Runs `make docs-build`, `make docs-test`, and automatically deploys `_site` to GitHub Pages (`https://vadde.github.io/DesignPatterns/`).
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 014d78b..a10927f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,7 +2,7 @@ name: DesignPatterns Quality & Security Gate
on:
push:
- branches: [main]
+ branches: [main, "feature/**"]
pull_request:
branches: [main]
workflow_dispatch:
@@ -13,7 +13,7 @@ concurrency:
jobs:
syntax-and-compilation:
- name: Python Architecture Compilation Check
+ name: Python Architecture Compilation & Lint
runs-on: ubuntu-latest
strategy:
matrix:
@@ -26,15 +26,31 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- - name: Compile all Python files
+ - name: Install Linting Tools
run: |
- python -m compileall -q .
- echo "β
All design pattern implementations compiled successfully without SyntaxErrors."
+ python -m pip install --upgrade pip
+ pip install ruff
- - name: Basic Syntax & Import Linter
+ - name: Run Canonical Architecture Tests & Linter
run: |
- pip install ruff
- ruff check . --select=E9,F63,F7,F82 --output-format=github
+ make test
+ make lint
+
+ docs-verification:
+ name: 15-Gate Living Docs Audit
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up Python 3.12
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Run 15-Gate Headless Verification Suite
+ run: |
+ chmod +x scripts/*.sh scripts/*.py
+ make docs-test
security-scan:
name: Gitleaks Secret Audit
diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml
new file mode 100644
index 0000000..1fe7018
--- /dev/null
+++ b/.github/workflows/docs-publish.yml
@@ -0,0 +1,51 @@
+name: Docs Publish & Deploy
+
+on:
+ push:
+ branches: [main]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ build-and-verify:
+ name: Build & Verify Living Docs
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Set up Python 3.12
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Build & Run 15-Gate Headless Verification Suite
+ run: |
+ chmod +x scripts/*.sh scripts/*.py
+ make docs-build
+ make docs-test
+
+ - name: Upload Pages Artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: _site
+
+ deploy:
+ name: Deploy to GitHub Pages
+ needs: build-and-verify
+ runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - name: Deploy to Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
index 605909d..9dadc97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,8 @@ pnpm-debug.log*
.nuxt/
dist/
build/
+_site/
+.playwright-mcp/
# --- Python & Environments (if scripts are run locally) ---
__pycache__/
diff --git a/00 - Foundations/theory.md b/00 - Foundations/theory.md
index 9272cb1..a9f441b 100644
--- a/00 - Foundations/theory.md
+++ b/00 - Foundations/theory.md
@@ -246,7 +246,7 @@ classDiagram
When you plug in a lamp, you don't wire it directly to the power plant. You plug it into a **wall outlet** (the abstraction). The lamp doesn't know or care if the electricity comes from solar, wind, or coal. And the power plant doesn't know or care if it's powering a lamp, a fridge, or a TV.
#### The Rule
-Don't import concrete classes directly. Depend on interfaces/protocols. This is the foundation of **Dependency Injection** (Chapter 24).
+Don't import concrete classes directly. Depend on interfaces/protocols. This is the foundation of **Dependency Injection** (Chapter 25).
#### Architecture: Before vs After
@@ -260,17 +260,17 @@ flowchart TB
subgraph "β
With DIP"
D["OrderService"] -->|"depends on"| E["Database (Protocol)"]
D -->|"depends on"| F["EmailSender (Protocol)"]
- E <|.. G["MySQLDatabase"]
- E <|.. H["PostgresDatabase"]
- F <|.. I["SMTPEmailSender"]
- F <|.. J["SendGridSender"]
+ E -.-> G["MySQLDatabase"]
+ E -.-> H["PostgresDatabase"]
+ F -.-> I["SMTPEmailSender"]
+ F -.-> J["SendGridSender"]
end
```
#### Which Patterns Embody DIP?
| Pattern | How It Uses DIP |
|---------|----------------|
-| **Dependency Injection** (Ch 24) | THE pattern for DIP |
+| **Dependency Injection** (Ch 25) | THE pattern for DIP |
| **Abstract Factory** (Ch 03) | Client depends on factory interface, not concrete factories |
| **Bridge** (Ch 07) | Abstraction depends on implementor interface |
| **Repository** (Ch 23) | Business logic depends on repository interface, not DB |
diff --git a/01 - Singleton (Creational)/theory.md b/01 - Singleton (Creational)/theory.md
index 604b815..bc4aee8 100644
--- a/01 - Singleton (Creational)/theory.md
+++ b/01 - Singleton (Creational)/theory.md
@@ -33,7 +33,7 @@ That's a Singleton: **one instance, shared by everyone**.
**Anti-signals (when NOT to use this pattern):**
- You need multiple instances with different configs β use **Factory Method** (Ch 02)
-- You want to pass dependencies explicitly β use **Dependency Injection** (Ch 24)
+- You want to pass dependencies explicitly β use **Dependency Injection** (Ch 25)
- You just need shared data, not a shared object β use a module-level variable
- Testing requires isolated instances β Singleton makes mocking painful
@@ -296,7 +296,7 @@ graph LR
S --> FW["11 Flyweight (flyweight factory is singleton)"]
S --> FA["10 Facade (facade often singleton)"]
ST["20 Strategy"] -.->|"Often confused"| S
- DI["24 Dependency Injection"] -.->|"Better alternative"| S
+ DI["25 Dependency Injection"] -.->|"Better alternative"| S
style DI fill:#51cf66,color:#fff
```
@@ -362,7 +362,7 @@ graph LR
4. No! The subclass and parent share `cls._instance` if using a simple `__new__` override. The first one created wins. Use a metaclass with a per-class dict to fix this.
-5. **No!** Singleton guarantees ONE instance. You need THREE. Use **Factory Method** (Ch 02) or **Dependency Injection** (Ch 24) to create and manage multiple configured instances.
+5. **No!** Singleton guarantees ONE instance. You need THREE. Use **Factory Method** (Ch 02) or **Dependency Injection** (Ch 25) to create and manage multiple configured instances.
6. Borg shares **state** (same `__dict__`) but creates **different objects** (`id()` differs). Singleton shares the **object itself** (same `id()`). Borg is useful when identity doesn't matter but shared state does.
diff --git a/02 - Factory Method (Creational)/theory.md b/02 - Factory Method (Creational)/theory.md
index 776247d..06d9f39 100644
--- a/02 - Factory Method (Creational)/theory.md
+++ b/02 - Factory Method (Creational)/theory.md
@@ -287,7 +287,7 @@ graph LR
FM["02 Factory Method"] --> AF["03 Abstract Factory (FM is a simplified AF)"]
FM --> TM["21 Template Method (FM is often called inside template method)"]
FM --> PR["05 Prototype (alternative: clone instead of construct)"]
- FM --> DI["24 Dependency Injection (DI generalizes the factory idea)"]
+ FM --> DI["25 Dependency Injection (DI generalizes the factory idea)"]
S["01 Singleton"] -.->|"Factory can be a singleton"| FM
```
diff --git a/13 - Chain of Responsibility (Behavioral)/theory.md b/13 - Chain of Responsibility (Behavioral)/theory.md
index 9ee41e8..b579268 100644
--- a/13 - Chain of Responsibility (Behavioral)/theory.md
+++ b/13 - Chain of Responsibility (Behavioral)/theory.md
@@ -121,8 +121,8 @@ flowchart LR
subgraph "GoF Classic (Stop at First Handler)"
R1["Request"] --> H1["Auth"]
H1 -->|"Not my job"| H2["Cache"]
- H2 -->|"I can do this!"| End["Return Response"]
- End -.x H3["Database (Ignored)"]
+ H2 -->|"I can do this!"| RespEnd["Return Response"]
+ RespEnd -. "never reached" .-> H3["Database (Ignored)"]
end
subgraph "Modern Middleware (Pass Through All)"
diff --git a/26 - Event Sourcing & CQRS (Architectural)/theory.md b/26 - Event Sourcing & CQRS (Architectural)/theory.md
index 1f3f101..44d6878 100644
--- a/26 - Event Sourcing & CQRS (Architectural)/theory.md
+++ b/26 - Event Sourcing & CQRS (Architectural)/theory.md
@@ -64,8 +64,8 @@ flowchart TB
ES -.->|Async Publish Event| RDB
- C -->|Send Command (POST)| Cmd
- C -->|Ask Query (GET)| Qry
+ C -->|"Send Command (POST)"| Cmd
+ C -->|"Ask Query (GET)"| Qry
```
---
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..70e0bb7
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,82 @@
+# ==============================================================================
+# Design Patterns Autonomous Command Deck Makefile
+# Unified automation for building, testing, linting, and serving
+# ==============================================================================
+
+.DEFAULT_GOAL := help
+SHELL := /usr/bin/env bash
+
+# Terminal Colors
+CYAN := \033[0;36m
+GREEN := \033[0;32m
+YELLOW := \033[1;33m
+RED := \033[0;31m
+NC := \033[0m
+
+.PHONY: help docs-build docs-serve docs-test test-boxes format-boxes test-links test-details test-badges test lint ci clean
+
+help: ## Show this interactive help menu
+ @printf "\n$(CYAN)ποΈ Design Patterns Architecture Bible β Autonomous Command Deck$(NC)\n\n"
+ @printf "Usage:\n make $(CYAN)$(NC)\n\nTargets:\n"
+ @awk 'BEGIN {FS = ":.*##"; printf ""} /^[a-zA-Z_-]+:.*?##/ { printf " $(CYAN)%-18s$(NC) %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
+ @printf "\n"
+
+docs-build: ## Compile 28 chapters catalog and package static site into _site/
+ @printf "$(CYAN)π Compiling Design Patterns Living Documentation into _site/...$(NC)\n"
+ @bash scripts/build-docs.sh
+
+docs-serve: docs-build ## Serve living documentation portal on http://localhost:4000
+ @printf "$(CYAN)π Serving Design Patterns Living Documentation on http://localhost:4000...$(NC)\n"
+ @if command -v python3 >/dev/null; then \
+ python3 -m http.server 4000 --directory _site; \
+ elif command -v npx >/dev/null; then \
+ npx -y serve _site -p 4000; \
+ else \
+ echo "$(RED)β Neither python3 nor npx found to serve static documentation.$(NC)"; \
+ exit 1; \
+ fi
+
+docs-test: ## Run 15-gate automated headless verification suite
+ @bash scripts/test-docs.sh
+
+test-boxes: ## Audit ASCII and Unicode box-drawing tables and cards alignment
+ @printf "$(CYAN)π Auditing ASCII/Unicode box-drawing alignment...$(NC)\n"
+ @python3 scripts/audit_ascii_boxes.py --check
+
+format-boxes: ## Realign and format all ASCII/Unicode boxes across the repository in place
+ @printf "$(CYAN)β¨ Formatting and realigning all ASCII/Unicode boxes...$(NC)\n"
+ @python3 scripts/audit_ascii_boxes.py --fix
+
+test-links: ## Audit universal hyperlink integrity, SPA containment, and zero local path leaks
+ @printf "$(CYAN)π Auditing hyperlink integrity & zero local path leaks...$(NC)\n"
+ @python3 scripts/audit_links_and_anchors.py
+
+test-details: ## Audit collapsible details and raw HTML block invariants
+ @printf "$(CYAN)π Auditing collapsible details and raw HTML block invariants...$(NC)\n"
+ @python3 scripts/audit_collapsible_elements.py
+
+test-badges: ## Audit monospace semantic badges and implementation labels
+ @printf "$(CYAN)π·οΈ Auditing monospace semantic badges...$(NC)\n"
+ @python3 scripts/audit_monospace_badging.py
+
+test: test-boxes ## Run Python AST syntax and compilation checks across all patterns
+ @printf "$(CYAN)π§ͺ Compiling all Python design pattern implementations...$(NC)\n"
+ @python3 -m compileall -q .
+ @printf "$(GREEN)β
All Python files compiled successfully without SyntaxErrors.$(NC)\n"
+
+lint: test-boxes ## Lint codebase with ruff and validate box alignment
+ @printf "$(CYAN)π Running ruff linter...$(NC)\n"
+ @if command -v ruff >/dev/null; then \
+ ruff check . --select=E9,F63,F7,F82; \
+ else \
+ printf "$(YELLOW)β οΈ ruff not installed in local environment, skipping.$(NC)\n"; \
+ fi
+
+ci: test lint docs-test ## Run full continuous integration audit suite locally
+ @printf "\n$(GREEN)π Full CI audit suite passed locally with 100%% compliance!$(NC)\n\n"
+
+clean: ## Clean build output directory and pycache
+ @printf "$(CYAN)π§Ή Cleaning build artifacts...$(NC)\n"
+ @rm -rf _site/
+ @find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
+ @printf "$(GREEN)β
Clean complete.$(NC)\n"
diff --git a/README.md b/README.md
index 45c0b2b..a80c982 100644
--- a/README.md
+++ b/README.md
@@ -57,9 +57,10 @@ This repository is a comprehensive, notebook-style guide to software design patt
*Beyond GoF β patterns that shape real-world systems at scale.*
- [23 - Repository Pattern](./23%20-%20Repository%20Pattern%20%28Architectural%29/)
-- [24 - Dependency Injection](./24%20-%20Dependency%20Injection%20%28Architectural%29/)
-- [25 - Event Sourcing & CQRS](./25%20-%20Event%20Sourcing%20%26%20CQRS%20%28Architectural%29/)
-- [26 - Patterns in the Wild (Capstone)](./26%20-%20Patterns%20in%20the%20Wild%20%28Capstone%29/)
+- [24 - Unit of Work](./24%20-%20Unit%20of%20Work%20%28Architectural%29/)
+- [25 - Dependency Injection](./25%20-%20Dependency%20Injection%20%28Architectural%29/)
+- [26 - Event Sourcing & CQRS](./26%20-%20Event%20Sourcing%20%26%20CQRS%20%28Architectural%29/)
+- [27 - Patterns in the Wild (Capstone)](./27%20-%20Patterns%20in%20the%20Wild%20%28Capstone%29/)
---
@@ -92,8 +93,9 @@ This repository is a comprehensive, notebook-style guide to software design patt
| Define a skeleton algorithm with customizable steps | Template Method | 21 |
| Add operations to objects without modifying them | Visitor | 22 |
| Abstract data persistence layer | Repository | 23 |
-| Decouple construction from usage of dependencies | Dependency Injection | 24 |
-| Track state changes as a sequence of events | Event Sourcing & CQRS | 25 |
+| Coordinate business transactions across repositories | Unit of Work | 24 |
+| Decouple construction from usage of dependencies | Dependency Injection | 25 |
+| Track state changes as a sequence of events | Event Sourcing & CQRS | 26 |
---
@@ -134,8 +136,9 @@ graph TB
subgraph "Architectural"
RP["23 Repository"]
- DI["24 Dependency Injection"]
- ES["25 Event Sourcing"]
+ UOW["24 Unit of Work"]
+ DI["25 Dependency Injection"]
+ ES["26 Event Sourcing"]
end
FM --> AF
@@ -161,6 +164,7 @@ graph TB
VI --> IT
RP --> FM
+ RP --> UOW
DI --> STR
DI --> FM
ES --> OBS
@@ -175,7 +179,7 @@ graph TB
2. **Go chapter-by-chapter** for a structured learning path, or **jump directly** to a pattern you need
3. **Each chapter has a `theory.md`** β read this first for the conceptual deep-dive
4. **Then explore `example_*.py` files** β runnable Python 3.14 code you can execute immediately
-5. **End with [Chapter 26 β Capstone](./26%20-%20Patterns%20in%20the%20Wild%20%28Capstone%29/)** for the decision matrix, anti-patterns, and interview playbook
+5. **End with [Chapter 27 β Capstone](./27%20-%20Patterns%20in%20the%20Wild%20%28Capstone%29/)** for the decision matrix, anti-patterns, and interview playbook
---
diff --git a/_internal/instructions.md b/_internal/instructions.md
index f54881f..eeb96e4 100644
--- a/_internal/instructions.md
+++ b/_internal/instructions.md
@@ -90,7 +90,7 @@ You MUST follow the **ReAct** (Reasoning + Acting) loop augmented with **Reflexi
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-β ReAct + Reflexion β
+β ReAct + Reflexion β
β β
β 1. THINK β Reason about the current task. β
β What do I know? What's missing? β
diff --git a/docs/site/app.js b/docs/site/app.js
new file mode 100755
index 0000000..36a2a52
--- /dev/null
+++ b/docs/site/app.js
@@ -0,0 +1,1701 @@
+/**
+ * ==============================================================================
+ * vadde/DesignPatterns β Year 2500 Command Deck Runtime (ES2022)
+ * Pure vanilla JavaScript with zero third-party framework runtime weight.
+ * Features:
+ * - Directional Web Audio API Haptic Acoustic Engine (HapticAudio)
+ * - 4-Theme Engine (Liquid Glass, Aero Mica, Holo 2050, Matrix Obsidian)
+ * - Draggable Sidebar Resizer Standard (240px - 560px with double-click reset)
+ * - Distraction-Free Collapsible Reading Rail (βB / [)
+ * - Commute Gadget Mobile Navigation Drawer
+ * - Sub-Millisecond Theater Mode Workbench (Zoom In/Out, 100%, Fit, Panning)
+ * - Universal Delegated In-Page Navigation & Flash-Focus Pulse
+ * - Sub-10ms Expand All SLA with isBatchExpanding Guard
+ * - Global Fuzzy Search Modal HUD (βK)
+ * - Interactive Pattern Finder & Decision Matrix
+ * ==============================================================================
+ */
+
+(function () {
+ 'use strict';
+
+ // Global UI State
+ const STATE = {
+ theme: localStorage.getItem('dp_theme') || 'liquid',
+ sidebarWidth: parseInt(localStorage.getItem('dp_sidebar_width'), 10) || 330,
+ isSidebarCollapsed: localStorage.getItem('dp_sidebar_collapsed') === 'true',
+ audioEnabled: localStorage.getItem('dp_audio_enabled') !== 'false',
+ isFocusMode: true,
+ isProgrammaticScroll: false,
+ programmaticScrollTimer: null,
+ isBatchExpanding: false,
+ manifest: null,
+ renderedDiagrams: new Set(),
+ theater: {
+ activeDiagramId: null,
+ scale: 1.0,
+ panX: 0,
+ panY: 0,
+ isPanning: false,
+ startX: 0,
+ startY: 0,
+ cachedVbW: 800,
+ cachedVbH: 600,
+ savedScrollY: 0
+ }
+ };
+
+ // ---------------------------------------------------------------------------
+ // 1. DIRECTIONAL WEB AUDIO API HAPTIC ENGINE (HapticAudio)
+ // ---------------------------------------------------------------------------
+ const HapticAudio = {
+ ctx: null,
+
+ getContext() {
+ if (!this.ctx) {
+ const AudioCtx = window.AudioContext || window.webkitAudioContext;
+ if (AudioCtx) {
+ this.ctx = new AudioCtx();
+ }
+ }
+ if (this.ctx && this.ctx.state === 'suspended') {
+ this.ctx.resume();
+ }
+ return this.ctx;
+ },
+
+ canPlay() {
+ return STATE.audioEnabled && !STATE.isBatchExpanding;
+ },
+
+ _lastAudioTime: 0,
+ throttle(intervalMs = 18) {
+ const now = performance.now();
+ if (now - this._lastAudioTime < intervalMs) return true;
+ this._lastAudioTime = now;
+ return false;
+ },
+
+ tap() {
+ if (!this.canPlay() || this.throttle(18)) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'triangle';
+ osc.frequency.setValueAtTime(920, now);
+ osc.frequency.exponentialRampToValueAtTime(560, now + 0.022);
+ gain.gain.setValueAtTime(0.038, now);
+ gain.gain.exponentialRampToValueAtTime(0.0005, now + 0.022);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.025);
+ } catch (e) {}
+ },
+
+ sidebarOpen() {
+ if (!this.canPlay()) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'triangle';
+ osc.frequency.setValueAtTime(440, now);
+ osc.frequency.exponentialRampToValueAtTime(760, now + 0.055);
+ gain.gain.setValueAtTime(0.05, now);
+ gain.gain.exponentialRampToValueAtTime(0.0005, now + 0.055);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.06);
+ } catch (e) {}
+ },
+
+ sidebarClose() {
+ if (!this.canPlay()) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(680, now);
+ osc.frequency.exponentialRampToValueAtTime(320, now + 0.045);
+ gain.gain.setValueAtTime(0.045, now);
+ gain.gain.exponentialRampToValueAtTime(0.0005, now + 0.045);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.05);
+ } catch (e) {}
+ },
+
+ // 1. Expand Chapter
+ expand() {
+ if (!this.canPlay()) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(540, now);
+ osc.frequency.exponentialRampToValueAtTime(880, now + 0.038);
+ gain.gain.setValueAtTime(0.06, now);
+ gain.gain.exponentialRampToValueAtTime(0.001, now + 0.038);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.038);
+ } catch (e) {}
+ },
+
+ // 2. Collapse Chapter
+ collapse() {
+ if (!this.canPlay()) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(780, now);
+ osc.frequency.exponentialRampToValueAtTime(420, now + 0.038);
+ gain.gain.setValueAtTime(0.05, now);
+ gain.gain.exponentialRampToValueAtTime(0.001, now + 0.038);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.038);
+ } catch (e) {}
+ },
+
+ // 3. Sidebar Rail Slide
+ sidebarToggle() {
+ if (!this.canPlay()) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'triangle';
+ osc.frequency.setValueAtTime(440, now);
+ osc.frequency.exponentialRampToValueAtTime(760, now + 0.05);
+ gain.gain.setValueAtTime(0.07, now);
+ gain.gain.exponentialRampToValueAtTime(0.001, now + 0.05);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.05);
+ } catch (e) {}
+ },
+
+ // 4. Celebratory Code Copy Chime (C6 + E6)
+ copySuccess() {
+ if (!STATE.audioEnabled) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ [1046.50, 1318.51].forEach((freq, idx) => {
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ const start = now + idx * 0.04;
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(freq, start);
+ gain.gain.setValueAtTime(0.07, start);
+ gain.gain.exponentialRampToValueAtTime(0.001, start + 0.09);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(start);
+ osc.stop(start + 0.09);
+ });
+ } catch (e) {}
+ },
+
+ // 5. Theme Palette Shift
+ themeChange() {
+ if (!this.canPlay()) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'triangle';
+ osc.frequency.setValueAtTime(600, now);
+ osc.frequency.exponentialRampToValueAtTime(1200, now + 0.06);
+ gain.gain.setValueAtTime(0.08, now);
+ gain.gain.exponentialRampToValueAtTime(0.001, now + 0.06);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.06);
+ } catch (e) {}
+ },
+
+ // 6. Theater Launch
+ theaterOpen() {
+ if (!this.canPlay()) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(440, now);
+ osc.frequency.exponentialRampToValueAtTime(880, now + 0.07);
+ gain.gain.setValueAtTime(0.08, now);
+ gain.gain.exponentialRampToValueAtTime(0.001, now + 0.07);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.07);
+ } catch (e) {}
+ },
+
+ // 7. Search HUD Ping
+ searchOpen() {
+ if (!this.canPlay()) return;
+ try {
+ const ctx = this.getContext();
+ if (!ctx) return;
+ const now = ctx.currentTime;
+ const osc = ctx.createOscillator();
+ const gain = ctx.createGain();
+ osc.type = 'sine';
+ osc.frequency.setValueAtTime(1180, now);
+ osc.frequency.exponentialRampToValueAtTime(1480, now + 0.04);
+ gain.gain.setValueAtTime(0.06, now);
+ gain.gain.exponentialRampToValueAtTime(0.001, now + 0.04);
+ osc.connect(gain);
+ gain.connect(ctx.destination);
+ osc.start(now);
+ osc.stop(now + 0.04);
+ } catch (e) {}
+ }
+ };
+
+ // ---------------------------------------------------------------------------
+ // 2. THEME ENGINE
+ // ---------------------------------------------------------------------------
+ function initThemeEngine() {
+ applyTheme(STATE.theme);
+
+ document.querySelectorAll('.theme-pill-btn').forEach(btn => {
+ btn.addEventListener('click', () => {
+ applyTheme(btn.dataset.themeSet);
+ HapticAudio.themeChange();
+ });
+ });
+
+ document.addEventListener('keydown', e => {
+ if (e.key.toLowerCase() === 't' && !isInputFocused(e)) {
+ e.preventDefault();
+ const themes = ['liquid', 'mica', 'holo', 'matrix'];
+ const currentIdx = themes.indexOf(STATE.theme);
+ const nextTheme = themes[(currentIdx + 1) % themes.length];
+ applyTheme(nextTheme);
+ HapticAudio.themeChange();
+ }
+ });
+ }
+
+ function applyTheme(themeName) {
+ STATE.theme = themeName;
+ document.documentElement.setAttribute('data-theme', themeName);
+ localStorage.setItem('dp_theme', themeName);
+
+ document.querySelectorAll('.theme-pill-btn').forEach(btn => {
+ btn.classList.toggle('active', btn.dataset.themeSet === themeName);
+ });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 3. AMBIENT HALO ENGINE
+ // ---------------------------------------------------------------------------
+ function initHaloEngine() {
+ const orb = document.getElementById('halo-orb');
+ if (!orb) return;
+
+ window.addEventListener('pointermove', e => {
+ document.documentElement.style.setProperty('--mx', `${e.clientX}px`);
+ document.documentElement.style.setProperty('--my', `${e.clientY}px`);
+ }, { passive: true });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 4. INTERACTIVE DRAGGABLE SIDEBAR RESIZER STANDARD
+ // ---------------------------------------------------------------------------
+ function initSidebarResizer() {
+ const resizer = document.getElementById('sidebar-resizer');
+ const sidebar = document.getElementById('main-sidebar');
+ if (!resizer || !sidebar) return;
+
+ const MIN_WIDTH = 240;
+ const MAX_WIDTH = 560;
+ const DEFAULT_WIDTH = 330;
+
+ // Apply saved width
+ const savedWidth = Math.min(Math.max(STATE.sidebarWidth, MIN_WIDTH), MAX_WIDTH);
+ document.documentElement.style.setProperty('--sidebar-width', `${savedWidth}px`);
+
+ let isDragging = false;
+
+ resizer.addEventListener('mousedown', e => {
+ if (e.button !== 0) return;
+ isDragging = true;
+ document.body.classList.add('resizing-sidebar');
+ e.preventDefault();
+ });
+
+ window.addEventListener('mousemove', e => {
+ if (!isDragging) return;
+ const newWidth = Math.min(Math.max(e.clientX, MIN_WIDTH), MAX_WIDTH);
+ document.documentElement.style.setProperty('--sidebar-width', `${newWidth}px`);
+ STATE.sidebarWidth = newWidth;
+ });
+
+ window.addEventListener('mouseup', () => {
+ if (isDragging) {
+ isDragging = false;
+ document.body.classList.remove('resizing-sidebar');
+ localStorage.setItem('dp_sidebar_width', STATE.sidebarWidth);
+ }
+ });
+
+ // Double-click reset to default width
+ resizer.addEventListener('dblclick', () => {
+ document.documentElement.style.setProperty('--sidebar-width', `${DEFAULT_WIDTH}px`);
+ STATE.sidebarWidth = DEFAULT_WIDTH;
+ localStorage.setItem('dp_sidebar_width', DEFAULT_WIDTH);
+ HapticAudio.sidebarToggle();
+ });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 5. COLLAPSIBLE SIDEBAR RAIL (βB / [)
+ // ---------------------------------------------------------------------------
+ function initDesktopSidebarToggle() {
+ const dockBtn = document.getElementById('sidebar-dock-toggle');
+ const closeBtn = document.getElementById('sidebar-close-btn');
+ const floatBtn = document.getElementById('floating-sidebar-toggle');
+
+ if (STATE.isSidebarCollapsed) {
+ document.body.classList.add('sidebar-collapsed');
+ }
+
+ function toggleRail() {
+ const isCollapsed = document.body.classList.toggle('sidebar-collapsed');
+ STATE.isSidebarCollapsed = isCollapsed;
+ localStorage.setItem('dp_sidebar_collapsed', isCollapsed ? 'true' : 'false');
+ HapticAudio.sidebarToggle();
+ }
+
+ if (dockBtn) dockBtn.addEventListener('click', toggleRail);
+ if (closeBtn) closeBtn.addEventListener('click', toggleRail);
+ if (floatBtn) floatBtn.addEventListener('click', toggleRail);
+
+ document.addEventListener('keydown', e => {
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'b') {
+ e.preventDefault();
+ toggleRail();
+ } else if (e.key === '[' && !isInputFocused(e)) {
+ e.preventDefault();
+ toggleRail();
+ }
+ });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 6. COMMUTE GADGET MOBILE DRAWER
+ // ---------------------------------------------------------------------------
+ function initMobileDrawer() {
+ const toggleBtn = document.getElementById('mobile-nav-toggle');
+ const backdrop = document.getElementById('mobile-drawer-backdrop');
+ if (!toggleBtn || !backdrop) return;
+
+ toggleBtn.addEventListener('click', () => {
+ document.body.classList.toggle('mobile-drawer-open');
+ HapticAudio.sidebarToggle();
+ });
+
+ backdrop.addEventListener('click', () => {
+ document.body.classList.remove('mobile-drawer-open');
+ HapticAudio.sidebarToggle();
+ });
+
+ window.addEventListener('resize', () => {
+ if (window.innerWidth > 1024 && document.body.classList.contains('mobile-drawer-open')) {
+ document.body.classList.remove('mobile-drawer-open');
+ }
+ }, { passive: true });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 7. PRECISION NAVIGATION & CHAPTER EXPANSION
+ // ---------------------------------------------------------------------------
+ function triggerDiagramRenders(container) {
+ if (STATE.isBatchExpanding) return;
+ setTimeout(() => {
+ renderVisibleDiagrams(container);
+ }, 16);
+ }
+
+ function ensureChapterExpanded(targetEl, shouldScroll = false) {
+ if (!targetEl) return;
+ if (shouldScroll) {
+ navigateToTarget(targetEl);
+ return;
+ }
+ const chapter = targetEl.closest('.pattern-chapter');
+ if (chapter) {
+ chapter.classList.remove('is-collapsed');
+ const toggleBtn = chapter.querySelector('.chapter-toggle-btn');
+ if (toggleBtn) toggleBtn.innerText = 'Collapse';
+ triggerDiagramRenders(chapter);
+ }
+ if (targetEl.tagName === 'DETAILS') {
+ targetEl.open = true;
+ triggerDiagramRenders(targetEl);
+ } else {
+ const parentDetails = targetEl.closest('details');
+ if (parentDetails) {
+ parentDetails.open = true;
+ triggerDiagramRenders(parentDetails);
+ }
+ }
+ }
+
+ function navigateToTarget(targetEl) {
+ if (!targetEl) return;
+
+ STATE.isProgrammaticScroll = true;
+ clearTimeout(STATE.programmaticScrollTimer);
+
+ // 1. Uncollapse the containing chapter
+ const chapter = targetEl.closest('.pattern-chapter') || (targetEl.classList.contains('pattern-chapter') ? targetEl : null);
+ if (chapter) {
+ if (STATE.isFocusMode) {
+ document.querySelectorAll('.pattern-chapter').forEach(c => {
+ if (c !== chapter) {
+ c.classList.add('is-collapsed');
+ const btn = c.querySelector('.chapter-toggle-btn');
+ if (btn) btn.innerText = 'Expand';
+ }
+ });
+ }
+ chapter.classList.remove('is-collapsed');
+ const toggleBtn = chapter.querySelector('.chapter-toggle-btn');
+ if (toggleBtn) toggleBtn.innerText = 'Collapse';
+
+ // Synchronize Left Navigation tree
+ const targetId = chapter.id;
+ const sidebarGroup = document.getElementById(`nav-group-${targetId}`);
+ if (sidebarGroup) {
+ document.querySelectorAll('.nav-tree-group').forEach(g => {
+ if (g === sidebarGroup) {
+ g.classList.add('expanded');
+ } else if (STATE.isFocusMode) {
+ g.classList.remove('expanded');
+ }
+ });
+ document.querySelectorAll('.nav-tree-header').forEach(h => {
+ const g = h.closest('.nav-tree-group');
+ if (g === sidebarGroup) {
+ h.classList.add('active-branch');
+ } else {
+ h.classList.remove('active-branch');
+ }
+ });
+ sidebarGroup.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
+ }
+
+ triggerDiagramRenders(chapter);
+ }
+
+ // 2. If target is inside a , open it!
+ if (targetEl.tagName === 'DETAILS') {
+ targetEl.open = true;
+ triggerDiagramRenders(targetEl);
+ } else {
+ const parentDetails = targetEl.closest('details');
+ if (parentDetails) {
+ parentDetails.open = true;
+ triggerDiagramRenders(parentDetails);
+ }
+ }
+
+ // Highlight active link in sidebar
+ document.querySelectorAll('.nav-tree-link').forEach(link => {
+ const href = link.getAttribute('href');
+ if (href === `#${targetEl.id}` || (chapter && href === `#${chapter.id}`)) {
+ link.classList.add('active');
+ } else {
+ link.classList.remove('active');
+ }
+ });
+
+ // 3. Force synchronous layout reflow so the browser finalizes all coordinates
+ void document.body.offsetHeight;
+
+ // 4. Calculate offset with 72px cushion
+ const rect = targetEl.getBoundingClientRect();
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
+ const targetY = rect.top + scrollTop - 72;
+
+ window.scrollTo({
+ top: Math.max(0, targetY),
+ behavior: 'smooth'
+ });
+
+ // 5. Flash-focus pulse animation
+ targetEl.classList.remove('flash-focus');
+ void targetEl.offsetWidth;
+ targetEl.classList.add('flash-focus');
+ setTimeout(() => targetEl.classList.remove('flash-focus'), 1800);
+
+ // 6. Close mobile drawer if open
+ if (window.innerWidth <= 1024 && document.body.classList.contains('mobile-drawer-open')) {
+ document.body.classList.remove('mobile-drawer-open');
+ }
+
+ // Reset programmatic scroll guard after scrolling finishes
+ STATE.programmaticScrollTimer = setTimeout(() => {
+ STATE.isProgrammaticScroll = false;
+ }, 800);
+ }
+
+ function handleInitialDeepLink() {
+ const hash = window.location.hash;
+ if (hash && hash.length > 1) {
+ try {
+ const targetEl = document.querySelector(hash);
+ if (targetEl) {
+ ensureChapterExpanded(targetEl, true);
+ return;
+ }
+ } catch (e) {}
+ }
+ // Expand Chapter 00 Foundations by default on initial arrival so content is immediately visible
+ const firstChapter = document.querySelector('.pattern-chapter');
+ if (firstChapter) {
+ firstChapter.classList.remove('is-collapsed');
+ const toggleBtn = firstChapter.querySelector('.chapter-toggle-btn');
+ if (toggleBtn) toggleBtn.innerText = 'Collapse';
+ const firstGroup = document.querySelector('.nav-tree-group');
+ if (firstGroup) firstGroup.classList.add('expanded');
+ triggerDiagramRenders(firstChapter);
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // 8. CHAPTER ACCORDIONS, FOCUS MODE & BATCH EXPAND SLA (1:1 DSA STANDARD)
+ // ---------------------------------------------------------------------------
+ function initCollapsibleChapters() {
+ const expandAllBtns = document.querySelectorAll('#btn-expand-all, .btn-expand-all, [data-action="expand-all"]');
+ const collapseAllBtns = document.querySelectorAll('#btn-collapse-all, .btn-collapse-all, [data-action="collapse-all"]');
+ const focusModeBtns = document.querySelectorAll('#btn-focus-mode, .btn-focus-mode, [data-action="focus-mode"]');
+ const sidebarExpandBtn = document.getElementById('sidebar-expand-all');
+ const sidebarCollapseBtn = document.getElementById('sidebar-collapse-all');
+
+ function setActiveReadingBtn(action) {
+ expandAllBtns.forEach(b => b.classList.toggle('active', action === 'expand-all'));
+ collapseAllBtns.forEach(b => b.classList.toggle('active', action === 'collapse-all'));
+ focusModeBtns.forEach(b => b.classList.toggle('active', action === 'focus-mode'));
+ }
+
+ // Click handler for Chapter Header Bar
+ document.querySelectorAll('.chapter-header-bar, .chapter-card-header').forEach(header => {
+ header.addEventListener('click', (e) => {
+ // Ignore clicks on inner copy buttons or links
+ if (e.target.closest('.copy-btn, a')) return;
+
+ const chapter = header.closest('.pattern-chapter');
+ if (!chapter) return;
+
+ const isCollapsed = chapter.classList.contains('is-collapsed');
+ if (isCollapsed) {
+ // Expanding
+ if (STATE.isFocusMode) {
+ document.querySelectorAll('.pattern-chapter').forEach(c => {
+ if (c !== chapter) {
+ c.classList.add('is-collapsed');
+ const btn = c.querySelector('.chapter-toggle-btn');
+ if (btn) btn.innerText = 'Expand';
+ }
+ });
+ }
+ chapter.classList.remove('is-collapsed');
+ const toggleBtn = chapter.querySelector('.chapter-toggle-btn');
+ if (toggleBtn) toggleBtn.innerText = 'Collapse';
+
+ // Sync with sidebar tree
+ const targetId = chapter.id;
+ const sidebarGroup = document.getElementById(`nav-group-${targetId}`);
+ if (sidebarGroup) {
+ if (STATE.isFocusMode) {
+ document.querySelectorAll('.nav-tree-group').forEach(g => {
+ if (g !== sidebarGroup) g.classList.remove('expanded');
+ });
+ }
+ sidebarGroup.classList.add('expanded');
+ }
+
+ triggerDiagramRenders(chapter);
+ HapticAudio.expand();
+ } else {
+ // Collapsing
+ chapter.classList.add('is-collapsed');
+ const toggleBtn = chapter.querySelector('.chapter-toggle-btn');
+ if (toggleBtn) toggleBtn.innerText = 'Expand';
+ HapticAudio.collapse();
+ }
+ });
+ });
+
+ // Expand All Chapters & Details (High performance: zero synchronous diagram render freeze)
+ expandAllBtns.forEach(btn => {
+ btn.addEventListener('click', () => {
+ STATE.isFocusMode = false;
+ STATE.isBatchExpanding = true;
+ setActiveReadingBtn('expand-all');
+ document.querySelectorAll('.pattern-chapter').forEach(c => {
+ c.classList.remove('is-collapsed');
+ const tBtn = c.querySelector('.chapter-toggle-btn');
+ if (tBtn) tBtn.innerText = 'Collapse';
+ });
+ document.querySelectorAll('.problem-card, .theory-details, .md-details').forEach(d => {
+ d.open = true;
+ });
+ setTimeout(() => {
+ STATE.isBatchExpanding = false;
+ renderVisibleDiagrams();
+ }, 50);
+ HapticAudio.expand();
+ });
+ });
+
+ // Collapse All Chapters & Details
+ collapseAllBtns.forEach(btn => {
+ btn.addEventListener('click', () => {
+ STATE.isFocusMode = false;
+ setActiveReadingBtn('collapse-all');
+ document.querySelectorAll('.pattern-chapter').forEach(c => {
+ c.classList.add('is-collapsed');
+ const tBtn = c.querySelector('.chapter-toggle-btn');
+ if (tBtn) tBtn.innerText = 'Expand';
+ });
+ document.querySelectorAll('.problem-card, .md-details').forEach(d => {
+ d.open = false;
+ });
+ document.querySelectorAll('.nav-tree-group').forEach(g => g.classList.remove('expanded'));
+ document.querySelectorAll('.nav-tree-header').forEach(h => h.classList.remove('active-branch'));
+ document.querySelectorAll('.nav-tree-link').forEach(l => l.classList.remove('active'));
+ HapticAudio.collapse();
+ });
+ });
+
+ // Focus Mode Toggle / Activate
+ focusModeBtns.forEach(btn => {
+ btn.addEventListener('click', () => {
+ STATE.isFocusMode = true;
+ setActiveReadingBtn('focus-mode');
+ // Collapse all except first open chapter
+ const chapters = Array.from(document.querySelectorAll('.pattern-chapter'));
+ let foundOpen = false;
+ chapters.forEach(c => {
+ if (!foundOpen && !c.classList.contains('is-collapsed')) {
+ foundOpen = true;
+ } else {
+ c.classList.add('is-collapsed');
+ const tBtn = c.querySelector('.chapter-toggle-btn');
+ if (tBtn) tBtn.innerText = 'Expand';
+ }
+ });
+ if (!foundOpen && chapters.length > 0) {
+ chapters[0].classList.remove('is-collapsed');
+ const tBtn = chapters[0].querySelector('.chapter-toggle-btn');
+ if (tBtn) tBtn.innerText = 'Collapse';
+ triggerDiagramRenders(chapters[0]);
+ }
+ HapticAudio.tap();
+ });
+ });
+
+ // Sidebar Expand / Collapse All
+ if (sidebarExpandBtn) {
+ sidebarExpandBtn.addEventListener('click', () => {
+ document.querySelectorAll('.nav-tree-group').forEach(g => g.classList.add('expanded'));
+ HapticAudio.expand();
+ });
+ }
+
+ if (sidebarCollapseBtn) {
+ sidebarCollapseBtn.addEventListener('click', () => {
+ document.querySelectorAll('.nav-tree-group').forEach(g => g.classList.remove('expanded'));
+ HapticAudio.collapse();
+ });
+ }
+
+ // Main content: Markdown Details clicks for audio consistency
+ document.addEventListener('click', e => {
+ const summary = e.target.closest('.md-summary, summary');
+ if (!summary) return;
+ const details = summary.closest('details');
+ if (!details || STATE.isBatchExpanding) return;
+
+ if (details.open) {
+ HapticAudio.collapse();
+ } else {
+ HapticAudio.expand();
+ }
+ });
+
+ // Handle deep links on load
+ handleInitialDeepLink();
+ }
+
+ // ---------------------------------------------------------------------------
+ // 9. SIDEBAR TREE NAVIGATION & FILTER ENGINE
+ // ---------------------------------------------------------------------------
+ function initSidebarFilters() {
+ const filterInput = document.getElementById('sidebar-filter-input');
+ const treeGroups = document.querySelectorAll('.nav-tree-group');
+ const tierChips = document.querySelectorAll('.tier-chip');
+
+ let activeTier = 'all';
+
+ function applyFilters() {
+ const query = filterInput ? filterInput.value.trim().toLowerCase() : '';
+ treeGroups.forEach(group => {
+ const titleEl = group.querySelector('.tree-title-text');
+ const titleText = titleEl ? titleEl.innerText.toLowerCase() : '';
+ const tier = group.dataset.tier || '';
+
+ const matchesQuery = !query || titleText.includes(query);
+ const matchesTier = activeTier === 'all' || tier === activeTier;
+
+ if (matchesQuery && matchesTier) {
+ group.style.display = '';
+ } else {
+ group.style.display = 'none';
+ }
+ });
+ }
+
+ if (filterInput) {
+ filterInput.addEventListener('input', applyFilters);
+ }
+
+ tierChips.forEach(chip => {
+ chip.addEventListener('click', () => {
+ const t = chip.dataset.tierFilter;
+ tierChips.forEach(c => c.classList.remove('active'));
+ chip.classList.add('active');
+ activeTier = t;
+ applyFilters();
+ HapticAudio.tap();
+ });
+ });
+
+ // Clicking group headers in sidebar
+ document.querySelectorAll('.nav-tree-header').forEach(header => {
+ header.addEventListener('click', () => {
+ const group = header.closest('.nav-tree-group');
+ if (!group) return;
+ const willExpand = !group.classList.contains('expanded');
+
+ if (STATE.isFocusMode && willExpand) {
+ document.querySelectorAll('.nav-tree-group').forEach(g => {
+ if (g !== group) g.classList.remove('expanded');
+ });
+ }
+ group.classList.toggle('expanded', willExpand);
+
+ // Bi-directional synchrony: expand corresponding chapter in content!
+ const targetId = header.getAttribute('data-target');
+ if (targetId) {
+ const targetSection = document.querySelector(targetId);
+ if (targetSection && willExpand) {
+ ensureChapterExpanded(targetSection, true);
+ }
+ }
+ if (willExpand) {
+ HapticAudio.expand();
+ } else {
+ HapticAudio.collapse();
+ }
+ });
+ });
+
+ // Universal precision navigation for in-page anchors across the entire portal
+ document.addEventListener('click', e => {
+ const link = e.target.closest('a[href^="#"]');
+ if (!link) return;
+ const href = link.getAttribute('href');
+ if (href && href !== '#' && href.length > 1) {
+ const targetEl = document.querySelector(href);
+ if (targetEl) {
+ e.preventDefault();
+ navigateToTarget(targetEl);
+ if (history.pushState) {
+ history.pushState(null, null, href);
+ }
+ HapticAudio.tap();
+ }
+ }
+ });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 10. SCROLLSPY
+ // ---------------------------------------------------------------------------
+ function initScrollSpy() {
+ const chapters = Array.from(document.querySelectorAll('.pattern-chapter'));
+ const navLinks = Array.from(document.querySelectorAll('.nav-tree-link'));
+ const navGroups = Array.from(document.querySelectorAll('.nav-tree-group'));
+ const navHeaders = Array.from(document.querySelectorAll('.nav-tree-header'));
+ if (!chapters.length) return;
+
+ let currentActiveChapterId = null;
+ let ticking = false;
+
+ function onScrollUpdate() {
+ ticking = false;
+ if (STATE.isProgrammaticScroll) return;
+
+ const scrollY = window.scrollY || window.pageYOffset;
+ const headerHeight = 72; // 64px header + 8px cushion
+
+ // If at top of page, clear active classes
+ if (scrollY < 220) {
+ if (currentActiveChapterId !== null) {
+ currentActiveChapterId = null;
+ navGroups.forEach(g => g.classList.remove('expanded'));
+ navHeaders.forEach(h => h.classList.remove('active-branch'));
+ navLinks.forEach(l => l.classList.remove('active'));
+ }
+ return;
+ }
+
+ // Find the chapter currently active on screen
+ let activeChapter = null;
+ for (let i = chapters.length - 1; i >= 0; i--) {
+ const ch = chapters[i];
+ const rect = ch.getBoundingClientRect();
+ if (rect.top <= headerHeight + 60) {
+ activeChapter = ch;
+ break;
+ }
+ }
+ if (!activeChapter && chapters.length > 0) {
+ activeChapter = chapters[0];
+ }
+
+ if (activeChapter && activeChapter.id !== currentActiveChapterId) {
+ currentActiveChapterId = activeChapter.id;
+ const targetGroup = document.getElementById(`nav-group-${currentActiveChapterId}`);
+
+ navGroups.forEach(g => {
+ if (g === targetGroup) {
+ g.classList.add('expanded');
+ } else if (STATE.isFocusMode) {
+ g.classList.remove('expanded');
+ }
+ });
+
+ navHeaders.forEach(h => {
+ const g = h.closest('.nav-tree-group');
+ h.classList.toggle('active-branch', g === targetGroup);
+ });
+
+ navLinks.forEach(l => {
+ const href = l.getAttribute('href');
+ l.classList.toggle('active', href === `#${currentActiveChapterId}`);
+ });
+
+ if (targetGroup) {
+ targetGroup.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
+ }
+ }
+ }
+
+ window.addEventListener('scroll', () => {
+ if (!ticking) {
+ window.requestAnimationFrame(onScrollUpdate);
+ ticking = true;
+ }
+ }, { passive: true });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 10. ZOOMABLE MERMAID CANVAS ENGINE & TOP-LAYER THEATER MODAL (DSA 1:1)
+ // ---------------------------------------------------------------------------
+ function initZoomableCanvases() {
+ const theaterModal = document.getElementById('theater-modal');
+ const theaterTitle = document.getElementById('theater-title');
+ const theaterSurface = document.getElementById('theater-surface');
+ const theaterViewport = document.getElementById('theater-viewport');
+ const closeTheaterBtn = document.getElementById('theater-close-btn');
+ const theaterZoomIn = document.getElementById('theater-zoom-in');
+ const theaterZoomOut = document.getElementById('theater-zoom-out');
+ const theaterZoomReset = document.getElementById('theater-zoom-reset');
+ const theaterZoomFit = document.getElementById('theater-zoom-fit');
+ const theaterZoomBadge = document.getElementById('theater-zoom-badge');
+
+ let activeTheaterZoom = 1.0;
+ let activeTheaterPanX = 0;
+ let activeTheaterPanY = 0;
+ let isTheaterPanning = false;
+ let theaterStartX = 0;
+ let theaterStartY = 0;
+ let savedScrollY = 0;
+ let activeSourceContainer = null;
+ let cachedVbW = 800;
+ let cachedVbH = 500;
+
+ function applyTheaterTransform() {
+ if (!theaterSurface) return;
+ theaterSurface.style.transform = `translate(${activeTheaterPanX}px, ${activeTheaterPanY}px) scale(${activeTheaterZoom})`;
+ if (theaterZoomBadge) theaterZoomBadge.innerText = `${Math.round(activeTheaterZoom * 100)}%`;
+ }
+
+ function calculateFitScale(svgEl) {
+ if (!theaterViewport) return 1.0;
+ let vbW = cachedVbW;
+ let vbH = cachedVbH;
+ if (!vbW || !vbH) {
+ if (svgEl) {
+ const vb = svgEl.getAttribute('viewBox');
+ if (vb) {
+ const parts = vb.trim().split(/[\s,]+/).map(Number);
+ if (parts.length >= 4 && parts[2] > 0 && parts[3] > 0) {
+ vbW = parts[2];
+ vbH = parts[3];
+ }
+ }
+ }
+ }
+ vbW = vbW || 800;
+ vbH = vbH || 500;
+ const availW = Math.max(300, (theaterViewport.clientWidth || window.innerWidth) - 64);
+ const availH = Math.max(200, (theaterViewport.clientHeight || window.innerHeight) - 64);
+ const fitW = availW / vbW;
+ const fitH = availH / vbH;
+ const scale = Math.min(fitW, fitH);
+ return Math.max(0.15, Math.min(scale, 3.5));
+ }
+
+ async function openTheater(title, sourceContainer) {
+ if (!theaterModal || !theaterSurface || !sourceContainer) return;
+
+ // 1. Save scroll position precisely BEFORE opening
+ savedScrollY = window.scrollY || window.pageYOffset;
+ activeSourceContainer = sourceContainer;
+
+ // Clean emoji duplication in header
+ const emojiMatch = title.match(/^(\p{Extended_Pictographic}+|\S+)\s*(.*)$/u);
+ if (emojiMatch && emojiMatch[2]) {
+ const iconEl = theaterModal.querySelector('.theater-icon');
+ if (iconEl) iconEl.innerText = emojiMatch[1];
+ if (theaterTitle) theaterTitle.innerText = emojiMatch[2];
+ } else {
+ if (theaterTitle) theaterTitle.innerText = title;
+ }
+ theaterSurface.innerHTML = '';
+
+ // 2. Clone ONLY the SVG element directly (no or wrapper clutter!)
+ let originalSvg = sourceContainer.querySelector('.mermaid svg');
+ if (!originalSvg) {
+ const pre = sourceContainer.querySelector('.mermaid');
+ if (pre && window.mermaid) {
+ try {
+ await renderMermaidElement(pre);
+ originalSvg = pre.querySelector('svg') || sourceContainer.querySelector('.mermaid svg');
+ } catch (e) {
+ console.warn('Theater mode on-demand render failed:', e);
+ }
+ }
+ }
+
+ if (originalSvg) {
+ const cleanSvg = originalSvg.cloneNode(true);
+ cleanSvg.removeAttribute('style');
+
+ let vbW = 0, vbH = 0;
+ const vb = cleanSvg.getAttribute('viewBox');
+ if (vb) {
+ const parts = vb.trim().split(/[\s,]+/).map(Number);
+ if (parts.length >= 4 && parts[2] > 0 && parts[3] > 0) {
+ vbW = parts[2];
+ vbH = parts[3];
+ }
+ }
+ if (vbW && vbH) {
+ cachedVbW = vbW;
+ cachedVbH = vbH;
+ cleanSvg.style.width = vbW + 'px';
+ cleanSvg.style.height = vbH + 'px';
+ } else {
+ cachedVbW = 800;
+ cachedVbH = 500;
+ cleanSvg.style.width = '100%';
+ cleanSvg.style.height = 'auto';
+ }
+ cleanSvg.style.maxWidth = 'none';
+ cleanSvg.style.maxHeight = 'none';
+ theaterSurface.appendChild(cleanSvg);
+ } else {
+ const surf = sourceContainer.querySelector('.canvas-content-surface');
+ if (surf) theaterSurface.innerHTML = surf.innerHTML;
+ }
+
+ // 3. Open modal and freeze background
+ theaterModal.showModal();
+ document.body.classList.add('theater-open');
+
+ // 4. Fit to Viewport by default: make use of screen boundaries
+ const renderedSvg = theaterSurface.querySelector('svg');
+ activeTheaterZoom = calculateFitScale(renderedSvg);
+ activeTheaterPanX = 0;
+ activeTheaterPanY = 0;
+ applyTheaterTransform();
+
+ HapticAudio.theaterOpen();
+ }
+
+ function closeTheater() {
+ if (!theaterModal || !theaterModal.open) return;
+ theaterModal.close();
+ document.body.classList.remove('theater-open');
+ if (theaterSurface) theaterSurface.innerHTML = '';
+
+ // 5. Restore user's exact scroll position instantly (zero treasure hunt!)
+ window.scrollTo({ top: savedScrollY, behavior: 'instant' });
+
+ // 6. Highlight original container
+ if (activeSourceContainer) {
+ const container = activeSourceContainer;
+ requestAnimationFrame(() => {
+ container.classList.add('flash-focus');
+ setTimeout(() => container?.classList.remove('flash-focus'), 1800);
+ });
+ }
+
+ HapticAudio.collapse();
+ }
+
+ // Explicit dismiss ONLY: clicking close button (β) or pressing Esc key
+ if (closeTheaterBtn) closeTheaterBtn.addEventListener('click', closeTheater);
+ if (theaterModal) {
+ theaterModal.addEventListener('cancel', e => {
+ e.preventDefault();
+ closeTheater();
+ });
+ theaterModal.addEventListener('close', closeTheater);
+ }
+
+ if (theaterZoomIn) {
+ theaterZoomIn.addEventListener('click', () => {
+ activeTheaterZoom = Math.min(5.0, Number((activeTheaterZoom + 0.25).toFixed(2)));
+ applyTheaterTransform();
+ HapticAudio.tap();
+ });
+ }
+
+ if (theaterZoomOut) {
+ theaterZoomOut.addEventListener('click', () => {
+ activeTheaterZoom = Math.max(0.15, Number((activeTheaterZoom - 0.25).toFixed(2)));
+ applyTheaterTransform();
+ HapticAudio.tap();
+ });
+ }
+
+ if (theaterZoomReset) {
+ theaterZoomReset.addEventListener('click', () => {
+ activeTheaterZoom = 1.0;
+ activeTheaterPanX = 0;
+ activeTheaterPanY = 0;
+ applyTheaterTransform();
+ HapticAudio.tap();
+ });
+ }
+
+ if (theaterZoomFit) {
+ theaterZoomFit.addEventListener('click', () => {
+ const svg = theaterSurface.querySelector('svg');
+ if (svg) {
+ activeTheaterZoom = calculateFitScale(svg);
+ activeTheaterPanX = 0;
+ activeTheaterPanY = 0;
+ applyTheaterTransform();
+ HapticAudio.tap();
+ }
+ });
+ }
+
+ // Theater draggable panning
+ if (theaterViewport) {
+ theaterViewport.addEventListener('pointerdown', e => {
+ if (e.target.closest('button') || e.target.closest('text') || e.target.closest('foreignObject') || e.target.closest('span')) return;
+ isTheaterPanning = true;
+ theaterStartX = e.clientX - activeTheaterPanX;
+ theaterStartY = e.clientY - activeTheaterPanY;
+ theaterViewport.setPointerCapture(e.pointerId);
+ });
+
+ theaterViewport.addEventListener('pointermove', e => {
+ if (!isTheaterPanning) return;
+ activeTheaterPanX = e.clientX - theaterStartX;
+ activeTheaterPanY = e.clientY - theaterStartY;
+ applyTheaterTransform();
+ });
+
+ function stopTheaterPan(e) {
+ if (!isTheaterPanning) return;
+ isTheaterPanning = false;
+ try { theaterViewport.releasePointerCapture(e.pointerId); } catch (_) {}
+ }
+
+ theaterViewport.addEventListener('pointerup', stopTheaterPan);
+ theaterViewport.addEventListener('pointercancel', stopTheaterPan);
+
+ // Mouse wheel zoom in theater
+ theaterViewport.addEventListener('wheel', e => {
+ e.preventDefault();
+ const delta = e.deltaY < 0 ? 0.12 : -0.12;
+ activeTheaterZoom = Math.min(4.0, Math.max(0.2, activeTheaterZoom + delta));
+ applyTheaterTransform();
+ }, { passive: false });
+ }
+
+ // Global keyboard shortcuts for Theater
+ window.addEventListener('keydown', e => {
+ if (!theaterModal || !theaterModal.open) return;
+ if (e.key === '+' || e.key === '=') {
+ activeTheaterZoom = Math.min(5.0, Number((activeTheaterZoom + 0.25).toFixed(2)));
+ applyTheaterTransform();
+ } else if (e.key === '-' || e.key === '_') {
+ activeTheaterZoom = Math.max(0.15, Number((activeTheaterZoom - 0.25).toFixed(2)));
+ applyTheaterTransform();
+ } else if (e.key === '0') {
+ activeTheaterZoom = 1.0;
+ activeTheaterPanX = 0;
+ activeTheaterPanY = 0;
+ applyTheaterTransform();
+ } else if (e.key === 'f' || e.key === 'F') {
+ const svg = theaterSurface.querySelector('svg');
+ if (svg) {
+ activeTheaterZoom = calculateFitScale(svg);
+ activeTheaterPanX = 0;
+ activeTheaterPanY = 0;
+ applyTheaterTransform();
+ }
+ }
+ });
+
+ // In-card zoomable canvases
+ document.querySelectorAll('.canvas-container').forEach(container => {
+ const viewport = container.querySelector('.canvas-viewport');
+ const surface = container.querySelector('.canvas-content-surface');
+ const badge = container.querySelector('.zoom-level-badge');
+ const zoomInBtn = container.querySelector('.zoom-in-btn');
+ const zoomOutBtn = container.querySelector('.zoom-out-btn');
+ const resetBtn = container.querySelector('.zoom-reset-btn');
+ const fullscreenBtn = container.querySelector('.fullscreen-btn');
+ const typeTag = container.querySelector('.canvas-type-tag')?.innerText || 'Architecture View';
+
+ if (!viewport || !surface) return;
+
+ let zoom = 1.0;
+ let panX = 0;
+ let panY = 0;
+ let isPanning = false;
+ let startX = 0;
+ let startY = 0;
+
+ function updateCardTransform() {
+ surface.style.transform = `translate(${panX}px, ${panY}px) scale(${zoom})`;
+ if (badge) badge.innerText = `${Math.round(zoom * 100)}%`;
+ }
+
+ if (zoomInBtn) {
+ zoomInBtn.addEventListener('click', () => {
+ zoom = Math.min(3.0, Number((zoom + 0.15).toFixed(2)));
+ updateCardTransform();
+ HapticAudio.tap();
+ });
+ }
+
+ if (zoomOutBtn) {
+ zoomOutBtn.addEventListener('click', () => {
+ zoom = Math.max(0.4, Number((zoom - 0.15).toFixed(2)));
+ updateCardTransform();
+ HapticAudio.tap();
+ });
+ }
+
+ if (resetBtn) {
+ resetBtn.addEventListener('click', () => {
+ zoom = 1.0;
+ panX = 0;
+ panY = 0;
+ updateCardTransform();
+ HapticAudio.tap();
+ });
+ }
+
+ if (fullscreenBtn) {
+ fullscreenBtn.addEventListener('click', async () => {
+ let svgEl = container.querySelector('.mermaid svg');
+ if (!svgEl) {
+ const pre = container.querySelector('.mermaid:not([data-processed="true"])');
+ if (pre && window.mermaid) {
+ await renderMermaidElement(pre);
+ }
+ }
+ openTheater(typeTag, container);
+ });
+ }
+
+ viewport.addEventListener('pointerdown', e => {
+ if (e.target.closest('button') || e.target.closest('text') || e.target.closest('foreignObject') || e.target.closest('span')) return;
+ isPanning = true;
+ startX = e.clientX - panX;
+ startY = e.clientY - panY;
+ viewport.setPointerCapture(e.pointerId);
+ });
+
+ viewport.addEventListener('pointermove', e => {
+ if (!isPanning) return;
+ panX = e.clientX - startX;
+ panY = e.clientY - startY;
+ updateCardTransform();
+ });
+
+ function stopPan(e) {
+ if (!isPanning) return;
+ isPanning = false;
+ try { viewport.releasePointerCapture(e.pointerId); } catch (_) {}
+ }
+
+ viewport.addEventListener('pointerup', stopPan);
+ viewport.addEventListener('pointercancel', stopPan);
+
+ viewport.addEventListener('dblclick', e => {
+ if (e.target.closest('button')) return;
+ if (fullscreenBtn) fullscreenBtn.click();
+ });
+ });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 10b. ISOLATED MERMAID RENDERING & LAZY ENGINE
+ // ---------------------------------------------------------------------------
+ let mermaidCounter = 0;
+
+ async function renderMermaidElement(el) {
+ if (!window.mermaid || !el) return;
+ if (el.dataset.processed === "true" || el.dataset.processed === "rendering") return;
+
+ if (!el.id) {
+ el.id = 'mermaid-dyn-' + (++mermaidCounter);
+ }
+
+ const code = el.getAttribute('data-mermaid-src') || el.textContent.trim();
+ if (!code) return;
+ if (!el.getAttribute('data-mermaid-src')) {
+ el.setAttribute('data-mermaid-src', code);
+ }
+
+ if (document.fonts && document.fonts.ready) {
+ await document.fonts.ready;
+ }
+
+ el.dataset.processed = "rendering";
+ try {
+ const renderId = 'svg-' + el.id.replace(/[^a-zA-Z0-9_-]/g, '_') + '-' + Math.random().toString(36).substr(2, 6);
+ const { svg, bindFunctions } = await window.mermaid.render(renderId, code);
+ el.innerHTML = svg;
+ if (bindFunctions) bindFunctions(el);
+
+ // Safari & Cross-Browser Sizing Normalization:
+ // Inject explicit intrinsic width, height, and aspect-ratio from viewBox
+ const svgEl = el.querySelector('svg');
+ if (svgEl) {
+ const vb = svgEl.getAttribute('viewBox');
+ if (vb) {
+ const parts = vb.trim().split(/[\s,]+/).map(Number);
+ if (parts.length >= 4 && parts[2] > 0 && parts[3] > 0) {
+ svgEl.setAttribute('width', parts[2]);
+ svgEl.setAttribute('height', parts[3]);
+ svgEl.style.aspectRatio = `${parts[2]} / ${parts[3]}`;
+ }
+ }
+ }
+
+ el.dataset.processed = "true";
+ STATE.renderedDiagrams.add(el.id);
+ } catch (e) {
+ console.warn('Mermaid render failure on element:', el.id, e);
+ el.dataset.processed = "error";
+ document.querySelectorAll('[id^="dmermaid"]').forEach(n => n.remove());
+ }
+ }
+
+ function renderVisibleDiagrams(container = document) {
+ if (!window.mermaid || !container) return;
+ const targets = container.querySelectorAll('.mermaid:not([data-processed="true"]):not([data-processed="rendering"])');
+ if (!targets.length) return;
+ targets.forEach(el => {
+ renderMermaidElement(el);
+ });
+ }
+
+ function triggerDiagramRenders(container) {
+ renderVisibleDiagrams(container);
+ }
+
+ function initLazyRenderers() {
+ const heroMermaid = document.getElementById('mermaid-diagram-hero');
+ if (heroMermaid) {
+ renderMermaidElement(heroMermaid);
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // 11. ONE-CLICK CODE COPY
+ // ---------------------------------------------------------------------------
+ function initCopyButtons() {
+ document.addEventListener('click', async e => {
+ const copyBtn = e.target.closest('.copy-btn');
+ if (!copyBtn) return;
+
+ const container = copyBtn.closest('.code-container, .example-card');
+ if (!container) return;
+
+ const codeEl = container.querySelector('code');
+ if (!codeEl) return;
+
+ try {
+ await navigator.clipboard.writeText(codeEl.textContent);
+ copyBtn.textContent = 'Copied!';
+ copyBtn.classList.add('copied');
+ HapticAudio.copySuccess();
+
+ setTimeout(() => {
+ copyBtn.textContent = 'Copy';
+ copyBtn.classList.remove('copied');
+ }, 2000);
+ } catch (err) {
+ console.error('Copy failed:', err);
+ }
+ });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 12. GLOBAL FUZZY SEARCH MODAL HUD (βK)
+ // ---------------------------------------------------------------------------
+ async function initSearchHUD() {
+ const triggerBtn = document.getElementById('hud-search-trigger');
+ const modal = document.getElementById('search-modal');
+ const input = document.getElementById('search-dialog-input');
+ const resultsContainer = document.getElementById('search-results-list');
+ const filterPills = document.querySelectorAll('.search-pill');
+
+ if (!modal || !input) return;
+
+ // Load manifest if not loaded
+ async function ensureManifest() {
+ if (STATE.manifest) return STATE.manifest;
+ try {
+ const res = await fetch('./catalog/manifest.json');
+ STATE.manifest = await res.json();
+ } catch (err) {
+ console.warn('Could not load catalog manifest:', err);
+ }
+ return STATE.manifest;
+ }
+
+ function openSearch() {
+ ensureManifest();
+ modal.showModal();
+ input.value = '';
+ input.focus();
+ HapticAudio.searchOpen();
+ renderSearchResults('');
+ }
+
+ function closeSearch() {
+ if (modal.open) {
+ modal.close();
+ }
+ }
+
+ if (triggerBtn) triggerBtn.addEventListener('click', openSearch);
+
+ modal.addEventListener('click', e => {
+ if (e.target === modal) closeSearch();
+ });
+
+ document.addEventListener('keydown', e => {
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
+ e.preventDefault();
+ if (modal.open) closeSearch();
+ else openSearch();
+ }
+ });
+
+ let currentFilter = 'all';
+ filterPills.forEach(pill => {
+ pill.addEventListener('click', () => {
+ filterPills.forEach(p => p.classList.remove('active'));
+ pill.classList.add('active');
+ currentFilter = pill.dataset.searchFilter;
+ renderSearchResults(input.value);
+ });
+ });
+
+ input.addEventListener('input', () => {
+ renderSearchResults(input.value);
+ });
+
+ function renderSearchResults(query) {
+ if (!STATE.manifest) return;
+ const q = query.toLowerCase().trim();
+ if (!q) {
+ resultsContainer.innerHTML = 'Type a pattern name, framework (FastAPI, Django, SQLAlchemy), or intent...
';
+ return;
+ }
+
+ const matches = [];
+
+ // Search patterns
+ STATE.manifest.patterns.forEach(p => {
+ if (currentFilter !== 'all' && p.tier !== currentFilter) return;
+ const score = (
+ (p.title.toLowerCase().includes(q) ? 10 : 0) +
+ (p.num.includes(q) ? 10 : 0) +
+ (p.gof_intent && p.gof_intent.toLowerCase().includes(q) ? 5 : 0) +
+ (p.summary_5yo && p.summary_5yo.toLowerCase().includes(q) ? 3 : 0)
+ );
+ if (score > 0) {
+ matches.push({
+ type: 'Pattern',
+ title: `${p.num} - ${p.title}`,
+ href: `#${p.slug}`,
+ badge: p.tier,
+ snippet: p.gof_intent || p.summary_5yo,
+ score
+ });
+ }
+ });
+
+ // Search examples / code
+ STATE.manifest.examples.forEach(ex => {
+ if (currentFilter !== 'all' && ex.tier !== currentFilter) return;
+ const score = (
+ (ex.title.toLowerCase().includes(q) ? 8 : 0) +
+ (ex.framework.toLowerCase().includes(q) ? 6 : 0) +
+ (ex.filename.toLowerCase().includes(q) ? 5 : 0) +
+ (ex.scenario && ex.scenario.toLowerCase().includes(q) ? 4 : 0) +
+ (ex.key_insight && ex.key_insight.toLowerCase().includes(q) ? 4 : 0)
+ );
+ if (score > 0) {
+ matches.push({
+ type: 'Implementation',
+ title: `${ex.chapter_num} ${ex.chapter_title}: ${ex.title}`,
+ href: `#example-${ex.chapter_slug}-${ex.filename.replace(/\.py$/, '')}`,
+ badge: ex.framework,
+ snippet: ex.scenario || ex.key_insight || `${ex.lines} lines of runnable Python code`,
+ score
+ });
+ }
+ });
+
+ matches.sort((a, b) => b.score - a.score);
+
+ if (!matches.length) {
+ resultsContainer.innerHTML = `No matching patterns or code found for "${q}".
`;
+ return;
+ }
+
+ resultsContainer.innerHTML = matches.slice(0, 15).map(m => `
+
+
+ ${m.title}
+ ${m.badge}
+
+ ${m.snippet || ''}
+
+ `).join('');
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // 13. INTERACTIVE PATTERN FINDER & DECISION MATRIX
+ // ---------------------------------------------------------------------------
+ async function initDecisionMatrix() {
+ const toggleBtn = document.getElementById('quick-finder-toggle-btn');
+ const hud = document.getElementById('pattern-finder-hud');
+ const closeBtn = document.getElementById('finder-close-btn');
+ const grid = document.getElementById('finder-matrix-grid');
+ const frameworkPills = document.querySelectorAll('.framework-pill');
+
+ if (!toggleBtn || !hud || !grid) return;
+
+ const MATRIX_DATA = [
+ { problem: "Need exactly one instance globally (config, DB connection pool)", pattern: "01 Singleton", slug: "chapter-01-singleton", tier: "Creational", fw: ["pure python", "django"] },
+ { problem: "Create objects without specifying exact concrete class", pattern: "02 Factory Method", slug: "chapter-02-factory-method", tier: "Creational", fw: ["pure python", "fastapi"] },
+ { problem: "Create matching families of related or dependent objects", pattern: "03 Abstract Factory", slug: "chapter-03-abstract-factory", tier: "Creational", fw: ["pure python", "sqlalchemy"] },
+ { problem: "Construct complex objects step-by-step with fluent API", pattern: "04 Builder", slug: "chapter-04-builder", tier: "Creational", fw: ["pure python"] },
+ { problem: "Clone existing objects instead of creating from scratch", pattern: "05 Prototype", slug: "chapter-05-prototype", tier: "Creational", fw: ["pure python"] },
+ { problem: "Make incompatible interfaces work together smoothly", pattern: "06 Adapter", slug: "chapter-06-adapter", tier: "Structural", fw: ["pure python"] },
+ { problem: "Vary abstraction AND implementation independently", pattern: "07 Bridge", slug: "chapter-07-bridge", tier: "Structural", fw: ["pure python"] },
+ { problem: "Treat individual objects and tree compositions uniformly", pattern: "08 Composite", slug: "chapter-08-composite", tier: "Structural", fw: ["pure python"] },
+ { problem: "Add behavior to objects dynamically without subclassing", pattern: "09 Decorator", slug: "chapter-09-decorator", tier: "Structural", fw: ["pure python", "fastapi"] },
+ { problem: "Simplify a complex subsystem with a clean high-level facade", pattern: "10 Facade", slug: "chapter-10-facade", tier: "Structural", fw: ["pure python"] },
+ { problem: "Share immutable state to support vast numbers of fine objects", pattern: "11 Flyweight", slug: "chapter-11-flyweight", tier: "Structural", fw: ["pure python"] },
+ { problem: "Control, cache, or lazily protect access to an object", pattern: "12 Proxy", slug: "chapter-12-proxy", tier: "Structural", fw: ["pure python", "django"] },
+ { problem: "Pass a request along an extensible chain of handlers", pattern: "13 Chain of Resp.", slug: "chapter-13-chain-of-responsibility", tier: "Behavioral", fw: ["pure python", "fastapi"] },
+ { problem: "Encapsulate a request as an object (undo, queue, redo)", pattern: "14 Command", slug: "chapter-14-command", tier: "Behavioral", fw: ["pure python", "celery"] },
+ { problem: "Access elements sequentially without exposing collection internals", pattern: "15 Iterator", slug: "chapter-15-iterator", tier: "Behavioral", fw: ["pure python"] },
+ { problem: "Reduce chaotic many-to-many dependencies between objects", pattern: "16 Mediator", slug: "chapter-16-mediator", tier: "Behavioral", fw: ["pure python"] },
+ { problem: "Save and restore object state snapshots without breaking encapsulation", pattern: "17 Memento", slug: "chapter-17-memento", tier: "Behavioral", fw: ["pure python"] },
+ { problem: "Notify multiple objects about state changes automatically", pattern: "18 Observer", slug: "chapter-18-observer", tier: "Behavioral", fw: ["pure python", "celery"] },
+ { problem: "Alter object behavior dynamically when its internal state changes", pattern: "19 State", slug: "chapter-19-state", tier: "Behavioral", fw: ["pure python"] },
+ { problem: "Swap interchangeable algorithms or policies at runtime", pattern: "20 Strategy", slug: "chapter-20-strategy", tier: "Behavioral", fw: ["pure python", "fastapi"] },
+ { problem: "Define algorithm skeleton in base class; let subclasses customize steps", pattern: "21 Template Method", slug: "chapter-21-template-method", tier: "Behavioral", fw: ["pure python", "django"] },
+ { problem: "Add operations to complex object structures without modifying them", pattern: "22 Visitor", slug: "chapter-22-visitor", tier: "Behavioral", fw: ["pure python"] },
+ { problem: "Abstract data persistence layer behind collection-like domain interface", pattern: "23 Repository Pattern", slug: "chapter-23-repository-pattern", tier: "Architectural", fw: ["sqlalchemy", "fastapi"] },
+ { problem: "Coordinate business transactions and commit atomic changes across repos", pattern: "24 Unit of Work", slug: "chapter-24-unit-of-work", tier: "Architectural", fw: ["sqlalchemy"] },
+ { problem: "Decouple dependency creation from dependency consumption", pattern: "25 Dependency Injection", slug: "chapter-25-dependency-injection", tier: "Architectural", fw: ["fastapi", "pure python"] },
+ { problem: "Track domain state changes as an immutable append-only event log", pattern: "26 Event Sourcing & CQRS", slug: "chapter-26-event-sourcing-cqrs", tier: "Architectural", fw: ["pure python", "celery"] }
+ ];
+
+ function renderMatrix(fwFilter = 'all') {
+ const filtered = MATRIX_DATA.filter(item => {
+ if (fwFilter === 'all') return true;
+ return item.fw.includes(fwFilter);
+ });
+
+ grid.innerHTML = filtered.map(item => `
+
+
+ ${item.problem}
+
+ `).join('');
+ }
+
+ renderMatrix('all');
+
+ toggleBtn.addEventListener('click', () => {
+ const isVisible = hud.style.display !== 'none';
+ hud.style.display = isVisible ? 'none' : 'block';
+ HapticAudio.themeChange();
+ });
+
+ if (closeBtn) {
+ closeBtn.addEventListener('click', () => {
+ hud.style.display = 'none';
+ HapticAudio.collapse();
+ });
+ }
+
+ frameworkPills.forEach(pill => {
+ pill.addEventListener('click', () => {
+ frameworkPills.forEach(p => p.classList.remove('active'));
+ pill.classList.add('active');
+ renderMatrix(pill.dataset.framework);
+ HapticAudio.sidebarToggle();
+ });
+ });
+
+ document.addEventListener('keydown', e => {
+ if (e.key.toLowerCase() === 'f' && !isInputFocused(e)) {
+ e.preventDefault();
+ const isVisible = hud.style.display !== 'none';
+ hud.style.display = isVisible ? 'none' : 'block';
+ HapticAudio.themeChange();
+ }
+ });
+ }
+
+ // ---------------------------------------------------------------------------
+ // 14. HELPER UTILITIES
+ // ---------------------------------------------------------------------------
+ function isInputFocused(e) {
+ const active = document.activeElement;
+ return active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable);
+ }
+
+ // ---------------------------------------------------------------------------
+ // 15. INITIALIZATION SEQUENCE (DUAL-MODE READYSTATE RESILIENT - 1:1 DSA)
+ // ---------------------------------------------------------------------------
+ function initAll() {
+ initThemeEngine();
+ initHaloEngine();
+ initSidebarResizer();
+ initDesktopSidebarToggle();
+ initMobileDrawer();
+ initCollapsibleChapters();
+ initSidebarFilters();
+ initScrollSpy();
+ initZoomableCanvases();
+ initLazyRenderers();
+ initCopyButtons();
+ initSearchHUD();
+ initDecisionMatrix();
+
+ // KaTeX mathematical auto-rendering
+ if (window.renderMathInElement) {
+ window.renderMathInElement(document.body, {
+ delimiters: [
+ { left: '$$', right: '$$', display: true },
+ { left: '$', right: '$', display: false }
+ ],
+ throwOnError: false
+ });
+ }
+
+ // Audio toggle button
+ const audioBtn = document.getElementById('audio-toggle-btn');
+ if (audioBtn) {
+ audioBtn.textContent = STATE.audioEnabled ? 'π' : 'π';
+ audioBtn.addEventListener('click', () => {
+ STATE.audioEnabled = !STATE.audioEnabled;
+ localStorage.setItem('dp_audio_enabled', STATE.audioEnabled ? 'true' : 'false');
+ audioBtn.textContent = STATE.audioEnabled ? 'π' : 'π';
+ if (STATE.audioEnabled) HapticAudio.themeChange();
+ });
+ }
+
+ // Proactively render visible diagrams (e.g. Master Relationships hero)
+ setTimeout(() => {
+ renderVisibleDiagrams();
+ }, 100);
+
+ console.log('%c Ξ© DESIGN PATTERNS BIBLE β Activated ', 'background:#00f2fe;color:#03020a;font-weight:bold;padding:4px 8px;border-radius:4px;');
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', initAll);
+ } else {
+ initAll();
+ }
+
+})();
diff --git a/docs/site/assets/aero-mica-theme-verified.png b/docs/site/assets/aero-mica-theme-verified.png
new file mode 100755
index 0000000..2f82450
Binary files /dev/null and b/docs/site/assets/aero-mica-theme-verified.png differ
diff --git a/docs/site/assets/decision-matrix-hud-verified.png b/docs/site/assets/decision-matrix-hud-verified.png
new file mode 100755
index 0000000..90ff168
Binary files /dev/null and b/docs/site/assets/decision-matrix-hud-verified.png differ
diff --git a/docs/site/assets/hero-command-deck-verified.png b/docs/site/assets/hero-command-deck-verified.png
new file mode 100755
index 0000000..79ce8b3
Binary files /dev/null and b/docs/site/assets/hero-command-deck-verified.png differ
diff --git a/docs/site/assets/theater-mode-workbench-verified.png b/docs/site/assets/theater-mode-workbench-verified.png
new file mode 100755
index 0000000..8ad3812
Binary files /dev/null and b/docs/site/assets/theater-mode-workbench-verified.png differ
diff --git a/docs/site/assets/verification-diagram-3-fixed.png b/docs/site/assets/verification-diagram-3-fixed.png
new file mode 100644
index 0000000..0772105
Binary files /dev/null and b/docs/site/assets/verification-diagram-3-fixed.png differ
diff --git a/docs/site/assets/verification-diagram-3-mica.png b/docs/site/assets/verification-diagram-3-mica.png
new file mode 100644
index 0000000..8f258fc
Binary files /dev/null and b/docs/site/assets/verification-diagram-3-mica.png differ
diff --git a/docs/site/assets/verification-diagram-6-fixed.png b/docs/site/assets/verification-diagram-6-fixed.png
new file mode 100644
index 0000000..74ac43d
Binary files /dev/null and b/docs/site/assets/verification-diagram-6-fixed.png differ
diff --git a/docs/site/assets/verification-hero-diagram-fixed.png b/docs/site/assets/verification-hero-diagram-fixed.png
new file mode 100644
index 0000000..46bc1e9
Binary files /dev/null and b/docs/site/assets/verification-hero-diagram-fixed.png differ
diff --git a/docs/site/assets/verification-hero-diagram-zoom130.png b/docs/site/assets/verification-hero-diagram-zoom130.png
new file mode 100644
index 0000000..ff702aa
Binary files /dev/null and b/docs/site/assets/verification-hero-diagram-zoom130.png differ
diff --git a/docs/site/assets/verification-holo-theme.png b/docs/site/assets/verification-holo-theme.png
new file mode 100644
index 0000000..c455a18
Binary files /dev/null and b/docs/site/assets/verification-holo-theme.png differ
diff --git a/docs/site/assets/verification-liquid-sidebar-tree.png b/docs/site/assets/verification-liquid-sidebar-tree.png
new file mode 100644
index 0000000..7c30fbb
Binary files /dev/null and b/docs/site/assets/verification-liquid-sidebar-tree.png differ
diff --git a/docs/site/assets/verification-theater-mode-hero.png b/docs/site/assets/verification-theater-mode-hero.png
new file mode 100644
index 0000000..2735734
Binary files /dev/null and b/docs/site/assets/verification-theater-mode-hero.png differ
diff --git a/docs/site/assets/verification_full.png b/docs/site/assets/verification_full.png
new file mode 100644
index 0000000..4e1d083
Binary files /dev/null and b/docs/site/assets/verification_full.png differ
diff --git a/docs/site/assets/verification_hero_clean.png b/docs/site/assets/verification_hero_clean.png
new file mode 100644
index 0000000..e6ca28a
Binary files /dev/null and b/docs/site/assets/verification_hero_clean.png differ
diff --git a/docs/site/assets/verification_liquid_theater.png b/docs/site/assets/verification_liquid_theater.png
new file mode 100644
index 0000000..1d83911
Binary files /dev/null and b/docs/site/assets/verification_liquid_theater.png differ
diff --git a/docs/site/assets/verification_mica_theater.png b/docs/site/assets/verification_mica_theater.png
new file mode 100644
index 0000000..2af1e91
Binary files /dev/null and b/docs/site/assets/verification_mica_theater.png differ
diff --git a/docs/site/assets/verification_theater.png b/docs/site/assets/verification_theater.png
new file mode 100644
index 0000000..3614440
Binary files /dev/null and b/docs/site/assets/verification_theater.png differ
diff --git a/docs/site/assets/verification_theater_mindmap.png b/docs/site/assets/verification_theater_mindmap.png
new file mode 100644
index 0000000..150f60e
Binary files /dev/null and b/docs/site/assets/verification_theater_mindmap.png differ
diff --git a/docs/site/index.html b/docs/site/index.html
new file mode 100755
index 0000000..67a6bff
--- /dev/null
+++ b/docs/site/index.html
@@ -0,0 +1,404 @@
+
+
+
+
+
+ Design Patterns β The Definitive Python 3.14 Reference & Command Deck
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ π VISION 2500 COMMAND DECK
+ PYTHON 3.14 READY
+ ZERO TOOLCHAIN
+
+
+
The Definitive Software Design Patterns Compendium
+
+ Explore 28 deep architectural chapters, 5 foundational tiers, and 38 runnable Python 3.14 implementations with real-world sightings from Django , FastAPI , SQLAlchemy , and Celery . Built with sub-millisecond diagram workbenches, crystal glass aesthetics, and haptic acoustic feedback.
+
+
+
+
+ π― Pattern Decision Matrix (F)
+
+
+
+
+
+
+
+
+
Filter by Framework:
+
+ All Frameworks
+ Pure Python
+ FastAPI
+ Django
+ SQLAlchemy
+ Celery
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+graph TB
+ subgraph Creational["π¨ Creational"]
+ S["01 Singleton"]
+ FM["02 Factory Method"]
+ AF["03 Abstract Factory"]
+ B["04 Builder"]
+ P["05 Prototype"]
+ end
+
+ subgraph Structural["π§± Structural"]
+ AD["06 Adapter"]
+ BR["07 Bridge"]
+ CO["08 Composite"]
+ DE["09 Decorator"]
+ FA["10 Facade"]
+ FW["11 Flyweight"]
+ PR["12 Proxy"]
+ end
+
+ subgraph Behavioral["π¬ Behavioral"]
+ COR["13 Chain of Resp."]
+ CMD["14 Command"]
+ IT["15 Iterator"]
+ MED["16 Mediator"]
+ MEM["17 Memento"]
+ OBS["18 Observer"]
+ ST["19 State"]
+ STR["20 Strategy"]
+ TM["21 Template Method"]
+ VI["22 Visitor"]
+ end
+
+ subgraph Architectural["π Architectural"]
+ RP["23 Repository"]
+ UOW["24 Unit of Work"]
+ DI["25 Dependency Injection"]
+ ES["26 Event Sourcing"]
+ end
+
+ FM --> AF
+ AF --> FM
+ B --> S
+ AF --> B
+ P --> S
+
+ AD --> BR
+ DE --> CO
+ PR --> DE
+ FA --> AD
+ FW --> FA
+
+ COR --> CO
+ CMD --> MEM
+ IT --> CO
+ MED --> OBS
+ OBS --> MED
+ ST --> STR
+ STR --> TM
+ VI --> CO
+ VI --> IT
+
+ RP --> FM
+ RP --> UOW
+ DI --> STR
+ DI --> FM
+ ES --> OBS
+ ES --> CMD
+
+
+
+
Systemic pattern relationship graph & cross-tier architectural dependencies
+
+
+
+
+
+
+ β Expand All
+ π― Focus Mode
+ β Collapse All
+
+
+ Click chapter headers to toggle accordion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ESC
+
+
+ All
+ Foundations
+ Creational
+ Structural
+ Behavioral
+ Architectural
+
+
+
Type a keyword, GoF pattern, framework (FastAPI, Django, SQLAlchemy), or design intent...
+
+
+
+
+
+
+
+
diff --git a/docs/site/style.css b/docs/site/style.css
new file mode 100755
index 0000000..224940a
--- /dev/null
+++ b/docs/site/style.css
@@ -0,0 +1,2636 @@
+/* ==============================================================================
+ vadde/DesignPatterns β Year 2500 Cosmic Liquid-Glass & Aero Mica Design System
+ ============================================================================== */
+
+@import url('https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@500;600;700&family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&family=Orbitron:wght@600;800;900&family=Outfit:wght@600;700;800;900&family=Rajdhani:wght@600;700&display=swap');
+
+/* ------------------------------------------------------------------------------
+ 1. COLOR PALETTES & THEME ENGINE
+ ------------------------------------------------------------------------------ */
+
+:root,
+[data-theme="liquid"] {
+ --bg-deep: #050813;
+ --bg-subtle: #0a0f24;
+ --bg-card: rgba(13, 20, 39, 0.65);
+ --bg-card-hover: rgba(18, 28, 56, 0.75);
+ --bg-card-border: rgba(255, 255, 255, 0.08);
+ --bg-card-border-glow: rgba(0, 242, 254, 0.35);
+
+ --accent-cyan: #00f2fe;
+ --accent-violet: #a855f7;
+ --accent-emerald: #10b981;
+ --accent-amber: #f59e0b;
+ --accent-rose: #f43f5e;
+ --accent-blue: #38bdf8;
+
+ --text-main: #f1f5f9;
+ --text-muted: #94a3b8;
+ --text-dim: #64748b;
+ --text-highlight: #ffffff;
+
+ --halo-glow-1: rgba(0, 242, 254, 0.12);
+ --halo-glow-2: rgba(168, 85, 247, 0.08);
+
+ --topbar-bg: rgba(5, 8, 19, 0.75);
+ --sidebar-bg: rgba(7, 12, 28, 0.82);
+ --code-bg: rgba(3, 5, 12, 0.85);
+
+ --scrollbar-thumb: rgba(255, 255, 255, 0.16);
+ --scrollbar-thumb-hover: rgba(0, 242, 254, 0.5);
+}
+
+/* THEME 2: FLUENT AERO MICA (Crisp Light Frosted Paper) */
+[data-theme="mica"] {
+ --bg-deep: #f6f4ee;
+ --bg-subtle: #eae6db;
+ --bg-card: rgba(255, 255, 255, 0.82);
+ --bg-card-hover: rgba(255, 255, 255, 0.95);
+ --bg-card-border: rgba(30, 41, 59, 0.12);
+ --bg-card-border-glow: rgba(2, 132, 199, 0.45);
+
+ --accent-cyan: #0284c7;
+ --accent-violet: #7c3aed;
+ --accent-emerald: #059669;
+ --accent-amber: #d97706;
+ --accent-rose: #e11d48;
+ --accent-blue: #0284c7;
+
+ --text-main: #0f172a;
+ --text-muted: #334155;
+ --text-dim: #64748b;
+ --text-highlight: #020617;
+
+ --halo-glow-1: rgba(2, 132, 199, 0.08);
+ --halo-glow-2: rgba(124, 58, 237, 0.06);
+
+ --topbar-bg: rgba(246, 244, 238, 0.82);
+ --sidebar-bg: rgba(250, 249, 246, 0.9);
+ --code-bg: rgba(255, 255, 255, 0.95);
+
+ --scrollbar-thumb: rgba(30, 41, 59, 0.2);
+ --scrollbar-thumb-hover: rgba(2, 132, 199, 0.5);
+}
+
+/* THEME 3: HOLO 2050 (Cyberpunk Terminal HUD) */
+[data-theme="holo"] {
+ --bg-deep: #03020a;
+ --bg-subtle: #08061a;
+ --bg-card: rgba(12, 10, 28, 0.75);
+ --bg-card-hover: rgba(20, 16, 44, 0.88);
+ --bg-card-border: rgba(77, 225, 255, 0.22);
+ --bg-card-border-glow: #ffaa00;
+ --glass-blur: blur(20px) saturate(220%);
+
+ --accent-cyan: #4de1ff;
+ --accent-violet: #ff4de1;
+ --accent-emerald: #b2ff4d;
+ --accent-amber: #ffaa00;
+ --accent-rose: #ff2a6d;
+ --accent-blue: #05d9e8;
+
+ --text-main: #d8f4ff;
+ --text-muted: #9ac8dd;
+ --text-dim: #628ea4;
+ --text-highlight: #ffffff;
+
+ --halo-glow-1: rgba(77, 225, 255, 0.18);
+ --halo-glow-2: rgba(255, 77, 225, 0.14);
+
+ --topbar-bg: rgba(3, 2, 10, 0.85);
+ --sidebar-bg: rgba(8, 6, 26, 0.88);
+ --code-bg: rgba(5, 4, 18, 0.95);
+ --code-border: rgba(77, 225, 255, 0.18);
+ --badge-bg: rgba(255, 170, 0, 0.14);
+ --badge-text: #ffaa00;
+
+ --scrollbar-thumb: rgba(77, 225, 255, 0.25);
+ --scrollbar-thumb-hover: #ffaa00;
+}
+
+/* THEME 4: MATRIX OBSIDIAN (Pure OLED Deep Emerald) */
+[data-theme="matrix"] {
+ --bg-deep: #000000;
+ --bg-subtle: #030a04;
+ --bg-card: rgba(5, 18, 8, 0.65);
+ --bg-card-hover: rgba(8, 28, 12, 0.75);
+ --bg-card-border: rgba(0, 255, 102, 0.12);
+ --bg-card-border-glow: rgba(0, 255, 102, 0.4);
+
+ --accent-cyan: #00ff66;
+ --accent-violet: #10b981;
+ --accent-emerald: #00ff66;
+ --accent-amber: #84cc16;
+ --accent-rose: #ef4444;
+ --accent-blue: #22c55e;
+
+ --text-main: #dcfce7;
+ --text-muted: #86efac;
+ --text-dim: #15803d;
+ --text-highlight: #ffffff;
+
+ --halo-glow-1: rgba(0, 255, 102, 0.1);
+ --halo-glow-2: rgba(16, 185, 129, 0.06);
+
+ --topbar-bg: rgba(0, 0, 0, 0.88);
+ --sidebar-bg: rgba(2, 8, 3, 0.92);
+ --code-bg: rgba(1, 10, 3, 0.9);
+
+ --scrollbar-thumb: rgba(0, 255, 102, 0.2);
+ --scrollbar-thumb-hover: rgba(0, 255, 102, 0.55);
+}
+
+/* Base Dimensions & Typography */
+:root {
+ --font-display: 'Outfit', 'Rajdhani', -apple-system, sans-serif;
+ --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ --font-mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, Consolas, monospace;
+ --font-hud: 'Orbitron', 'Chakra Petch', sans-serif;
+ --sidebar-width: 340px;
+ --topbar-height: 64px;
+ --radius-sm: 8px;
+ --radius-md: 14px;
+ --radius-lg: 20px;
+ --radius-full: 9999px;
+ --shadow-glass: 0 16px 40px -10px rgba(0, 0, 0, 0.5), 0 0 1px 1px rgba(255, 255, 255, 0.08) inset;
+ --t-fast: 160ms;
+ --t-normal: 240ms;
+}
+
+/* ------------------------------------------------------------------------------
+ 2. GLOBAL RESET & STICKY-SAFE ROOT RULES
+ ------------------------------------------------------------------------------ */
+
+*, *::before, *::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+/* MANDATORY STICKY SCROLL INVARIANT:
+ Never use 'overflow-x: hidden' on html or body.
+ Always use 'overflow-x: clip' so that position: sticky is never broken! */
+html,
+body {
+ overflow-x: clip;
+ width: 100%;
+ min-height: 100vh;
+ background-color: var(--bg-deep);
+ color: var(--text-main);
+ font-family: var(--font-sans);
+ font-size: 15px;
+ line-height: 1.6;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+/* Custom Scrollbars */
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+::-webkit-scrollbar-track {
+ background: transparent;
+}
+::-webkit-scrollbar-thumb {
+ background: var(--scrollbar-thumb);
+ border-radius: var(--radius-full);
+}
+::-webkit-scrollbar-thumb:hover {
+ background: var(--scrollbar-thumb-hover);
+}
+
+/* ------------------------------------------------------------------------------
+ 3. AMBIENT HALO LIGHTING ENGINE
+ ------------------------------------------------------------------------------ */
+
+.canvas-ambient-halo {
+ position: fixed;
+ inset: 0;
+ pointer-events: none;
+ z-index: 0;
+ overflow: hidden;
+}
+
+.halo-orb-pointer {
+ position: absolute;
+ top: var(--my, 20%);
+ left: var(--mx, 30%);
+ width: 500px;
+ height: 500px;
+ transform: translate(-50%, -50%);
+ border-radius: 50%;
+ background: radial-gradient(circle, var(--halo-glow-1) 0%, transparent 70%);
+ filter: blur(50px);
+ will-change: top, left;
+ transition: opacity 0.3s ease;
+}
+
+.halo-orb-aurora {
+ position: absolute;
+ top: -10%;
+ right: -5%;
+ width: 600px;
+ height: 600px;
+ border-radius: 50%;
+ background: radial-gradient(circle, var(--halo-glow-2) 0%, transparent 75%);
+ filter: blur(80px);
+ animation: auroraFloat 18s ease-in-out infinite alternate;
+}
+
+@keyframes auroraFloat {
+ 0% { transform: translate(0, 0) scale(1); }
+ 50% { transform: translate(-40px, 30px) scale(1.08); }
+ 100% { transform: translate(30px, -20px) scale(0.95); }
+}
+
+/* ------------------------------------------------------------------------------
+ 4. TOPBAR & HEADER DECK
+ ------------------------------------------------------------------------------ */
+
+.header-glass {
+ position: sticky;
+ top: 0;
+ z-index: 1000;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: var(--topbar-height);
+ padding: 0 20px;
+ background: var(--topbar-bg);
+ backdrop-filter: blur(20px) saturate(180%);
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
+ border-bottom: 1px solid var(--bg-card-border);
+ gap: 16px;
+}
+
+.header-left-cluster {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.mobile-nav-toggle {
+ display: none;
+ background: transparent;
+ border: none;
+ color: var(--text-main);
+ font-size: 20px;
+ cursor: pointer;
+ padding: 6px 10px;
+ border-radius: var(--radius-sm);
+}
+
+.sidebar-dock-toggle {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 34px;
+ height: 34px;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-sm);
+ color: var(--text-muted);
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+.sidebar-dock-toggle:hover {
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--accent-cyan);
+ border-color: var(--accent-cyan);
+}
+
+.brand-badge {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ text-decoration: none;
+ color: inherit;
+}
+.brand-logo-icon {
+ font-size: 22px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.brand-text-group {
+ display: flex;
+ flex-direction: column;
+}
+.brand-title {
+ font-size: 0.95rem;
+ font-weight: 800;
+ letter-spacing: 0.06em;
+ background: linear-gradient(135deg, #ffffff 40%, var(--accent-cyan) 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+.brand-subtitle {
+ font-size: 0.68rem;
+ color: var(--text-dim);
+ font-weight: 500;
+ letter-spacing: 0.02em;
+}
+
+.header-telemetry-cluster {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+.telemetry-chip {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ padding: 4px 10px;
+ background: rgba(255, 255, 255, 0.03);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-full);
+ font-size: 0.72rem;
+ color: var(--text-muted);
+ letter-spacing: 0.04em;
+}
+.telemetry-chip strong {
+ color: var(--accent-cyan);
+ font-family: var(--font-mono);
+}
+.pulse-dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: var(--accent-emerald);
+ box-shadow: 0 0 8px var(--accent-emerald);
+ animation: pulse 2s infinite;
+}
+@keyframes pulse {
+ 0%, 100% { opacity: 1; transform: scale(1); }
+ 50% { opacity: 0.4; transform: scale(0.85); }
+}
+
+.header-controls-cluster {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+.hud-search-btn {
+ display: inline-flex;
+ align-items: center;
+ gap: 12px;
+ padding: 6px 14px;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-full);
+ color: var(--text-muted);
+ font-size: 0.8rem;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+.hud-search-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+ border-color: var(--accent-cyan);
+ color: var(--text-main);
+}
+.kbd-shortcut {
+ padding: 2px 6px;
+ background: rgba(255, 255, 255, 0.08);
+ border-radius: 4px;
+ font-family: var(--font-mono);
+ font-size: 0.7rem;
+}
+
+.theme-picker-group {
+ display: inline-flex;
+ padding: 3px;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-full);
+ gap: 2px;
+}
+.theme-pill-btn {
+ padding: 4px 10px;
+ background: transparent;
+ border: none;
+ border-radius: var(--radius-full);
+ color: var(--text-dim);
+ font-size: 0.72rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+.theme-pill-btn:hover {
+ color: var(--text-main);
+}
+.theme-pill-btn.active {
+ background: var(--accent-cyan);
+ color: #040714;
+ box-shadow: 0 0 10px var(--accent-cyan);
+}
+
+.hud-tool-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 34px;
+ height: 34px;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-sm);
+ color: var(--text-muted);
+ text-decoration: none;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+.hud-tool-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--accent-cyan);
+ border-color: var(--accent-cyan);
+}
+
+/* ------------------------------------------------------------------------------
+ 5. LAYOUT ARCHITECTURE & SIDEBAR RESIZER
+ ------------------------------------------------------------------------------ */
+
+.layout-container {
+ display: flex;
+ position: relative;
+ min-height: calc(100vh - var(--topbar-height));
+ width: 100%;
+ overflow-x: clip; /* Sticky safe! */
+}
+
+.floating-sidebar-toggle {
+ display: none;
+ position: fixed;
+ top: calc(var(--topbar-height) + 14px);
+ left: 14px;
+ z-index: 990;
+ width: 32px;
+ height: 32px;
+ background: var(--bg-card);
+ backdrop-filter: blur(16px);
+ border: 1px solid var(--accent-cyan);
+ border-radius: var(--radius-sm);
+ color: var(--accent-cyan);
+ cursor: pointer;
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
+}
+body.sidebar-collapsed .floating-sidebar-toggle {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.sidebar {
+ width: var(--sidebar-width);
+ min-width: 240px;
+ max-width: 560px;
+ height: calc(100vh - var(--topbar-height));
+ position: sticky;
+ top: var(--topbar-height);
+ background: var(--sidebar-bg);
+ backdrop-filter: blur(20px) saturate(180%);
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
+ border-right: 1px solid var(--bg-card-border);
+ display: flex;
+ flex-direction: column;
+ z-index: 100;
+ transition: margin-left 0.25s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s ease;
+ flex-shrink: 0;
+}
+
+body.sidebar-collapsed .sidebar {
+ margin-left: calc(-1 * var(--sidebar-width));
+ opacity: 0;
+ visibility: hidden;
+ pointer-events: none;
+}
+
+body.sidebar-collapsed #sidebar-resizer {
+ display: none;
+}
+
+.sidebar-search-row {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 14px 16px;
+ border-bottom: 1px solid var(--bg-card-border);
+}
+.sidebar-search-box {
+ flex: 1;
+}
+.sidebar-search-input {
+ width: 100%;
+ padding: 8px 12px;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-sm);
+ color: var(--text-main);
+ font-family: var(--font-sans);
+ font-size: 0.82rem;
+ outline: none;
+ transition: border-color var(--t-fast) ease;
+}
+.sidebar-search-input:focus {
+ border-color: var(--accent-cyan);
+}
+.sidebar-close-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 30px;
+ height: 30px;
+ background: transparent;
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-sm);
+ color: var(--text-dim);
+ cursor: pointer;
+}
+.sidebar-close-btn:hover {
+ color: var(--text-main);
+ border-color: var(--accent-cyan);
+}
+
+.tier-filter-chips {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+ padding: 10px 16px;
+ border-bottom: 1px solid var(--bg-card-border);
+}
+.tier-chip {
+ padding: 3px 8px;
+ background: rgba(255, 255, 255, 0.03);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-full);
+ color: var(--text-dim);
+ font-size: 0.7rem;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+.tier-chip:hover {
+ color: var(--text-main);
+}
+.tier-chip.active {
+ background: rgba(0, 242, 254, 0.15);
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+
+/* Tree Controls Bar */
+.tree-controls-bar {
+ display: flex;
+ gap: 6px;
+ padding: 8px 12px;
+ background: rgba(0, 0, 0, 0.15);
+ border-bottom: 1px solid var(--bg-card-border);
+}
+
+.mini-tool-btn {
+ flex: 1;
+ padding: 5px 8px;
+ font-family: var(--font-mono);
+ font-size: 0.72rem;
+ font-weight: 600;
+ color: var(--text-muted);
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-sm);
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+ text-align: center;
+}
+
+.mini-tool-btn:hover {
+ color: var(--text-main);
+ background: rgba(255, 255, 255, 0.1);
+ border-color: var(--accent-cyan);
+}
+
+.sidebar-nav-tree {
+ flex: 1;
+ min-height: 0;
+ overflow-y: auto;
+ overflow-x: hidden;
+ padding: 10px 8px;
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+}
+
+/* Nav Tree Groups (DSA 1:1 Standard) */
+.nav-tree-group {
+ display: flex;
+ flex-direction: column;
+ flex-shrink: 0 !important;
+ min-height: fit-content !important;
+ border-radius: var(--radius-sm);
+ margin-bottom: 4px;
+}
+
+.nav-tree-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 8px 10px;
+ min-height: 38px;
+ border-radius: var(--radius-sm);
+ background: transparent;
+ cursor: pointer;
+ user-select: none;
+ gap: 8px;
+ transition: background-color var(--t-fast) ease;
+}
+
+.nav-tree-header:hover {
+ background: rgba(255, 255, 255, 0.05);
+}
+
+.nav-tree-header.active-branch {
+ border-left: 2px solid var(--accent-cyan);
+ background: rgba(0, 242, 254, 0.06);
+}
+
+.tree-title-group {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex: 1;
+ min-width: 0;
+}
+
+.tree-chevron {
+ font-size: 0.72rem;
+ color: var(--text-dim);
+ transition: transform 0.22s var(--ease-spring), color 0.2s ease;
+ transform: rotate(0deg);
+ flex-shrink: 0;
+}
+
+.nav-tree-group.expanded .tree-chevron {
+ transform: rotate(90deg);
+ color: var(--accent-cyan);
+}
+
+.tree-icon {
+ font-size: 0.95rem;
+ flex-shrink: 0;
+}
+
+.tree-title-text {
+ font-family: var(--font-body);
+ font-size: 0.84rem;
+ font-weight: 500;
+ color: var(--text-main);
+ white-space: normal;
+ word-break: break-word;
+ line-height: 1.35;
+}
+
+/* Distinct Nav Pill Badges */
+.nav-pill {
+ font-family: var(--font-mono);
+ font-size: 0.65rem;
+ font-weight: 700;
+ letter-spacing: 0.04em;
+ padding: 2px 7px;
+ border-radius: var(--radius-full);
+ background: rgba(255, 255, 255, 0.06);
+ color: var(--text-dim);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ flex-shrink: 0;
+ text-transform: uppercase;
+ transition: all var(--t-fast) ease;
+}
+
+.nav-pill.pill-creational {
+ color: #ffb84d;
+ background: rgba(255, 184, 77, 0.12);
+ border-color: rgba(255, 184, 77, 0.3);
+}
+
+.nav-pill.pill-structural {
+ color: #38bdf8;
+ background: rgba(56, 189, 248, 0.12);
+ border-color: rgba(56, 189, 248, 0.3);
+}
+
+.nav-pill.pill-behavioral {
+ color: #c084fc;
+ background: rgba(192, 132, 252, 0.12);
+ border-color: rgba(192, 132, 252, 0.3);
+}
+
+.nav-pill.pill-architectural {
+ color: #fb7185;
+ background: rgba(251, 113, 133, 0.12);
+ border-color: rgba(251, 113, 133, 0.3);
+}
+
+.nav-pill.pill-foundations {
+ color: #34d399;
+ background: rgba(52, 211, 153, 0.12);
+ border-color: rgba(52, 211, 153, 0.3);
+}
+
+.nav-pill.pill-capstone {
+ color: #60a5fa;
+ background: rgba(96, 165, 250, 0.12);
+ border-color: rgba(96, 165, 250, 0.3);
+}
+
+/* Nav Tree Children Links */
+.nav-tree-children {
+ display: none;
+ flex-direction: column;
+ padding-left: 20px;
+ margin-top: 2px;
+ margin-bottom: 4px;
+ border-left: 1px dashed var(--bg-card-border);
+ margin-left: 14px;
+}
+
+.nav-tree-group.expanded .nav-tree-children {
+ display: flex;
+}
+
+.nav-tree-link {
+ display: block;
+ padding: 5px 8px;
+ font-family: var(--font-body);
+ font-size: 0.78rem;
+ color: var(--text-muted);
+ text-decoration: none;
+ border-radius: 4px;
+ white-space: normal;
+ word-break: break-word;
+ line-height: 1.35;
+ transition: all var(--t-fast) ease;
+}
+
+.nav-tree-link:hover {
+ color: var(--text-main);
+ background: rgba(255, 255, 255, 0.05);
+}
+
+.nav-tree-link.active {
+ color: var(--accent-cyan);
+ font-weight: 600;
+ background: var(--badge-bg);
+}
+
+.sidebar-nav-item {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 8px 12px;
+ border-radius: var(--radius-sm);
+ color: var(--text-muted);
+ text-decoration: none;
+ font-size: 0.82rem;
+ transition: all var(--t-fast) ease;
+ white-space: normal;
+ word-break: break-word;
+}
+.sidebar-nav-item:hover {
+ background: rgba(255, 255, 255, 0.05);
+ color: var(--text-main);
+}
+.sidebar-nav-item.active {
+ background: rgba(0, 242, 254, 0.12);
+ color: var(--accent-cyan);
+ font-weight: 600;
+ border-left: 2px solid var(--accent-cyan);
+}
+.nav-item-num {
+ font-family: var(--font-mono);
+ font-size: 0.72rem;
+ color: var(--text-dim);
+ flex-shrink: 0;
+}
+.nav-item-title {
+ flex: 1;
+}
+.nav-item-badge {
+ font-size: 0.65rem;
+ padding: 2px 6px;
+ background: rgba(255, 255, 255, 0.04);
+ border-radius: 4px;
+ color: var(--text-dim);
+ text-transform: uppercase;
+ letter-spacing: 0.04em;
+}
+
+/* Sidebar Resizer Separator */
+.sidebar-resizer {
+ width: 6px;
+ background: transparent;
+ cursor: col-resize;
+ position: relative;
+ z-index: 150;
+ transition: background var(--t-fast) ease;
+ flex-shrink: 0;
+}
+.sidebar-resizer:hover,
+body.resizing-sidebar .sidebar-resizer {
+ background: var(--accent-cyan);
+ box-shadow: 0 0 10px var(--accent-cyan);
+}
+body.resizing-sidebar {
+ cursor: col-resize !important;
+ user-select: none !important;
+}
+
+/* ------------------------------------------------------------------------------
+ 6. CONTENT AREA & HERO COMMAND DECK
+ ------------------------------------------------------------------------------ */
+
+.content-area {
+ flex: 1;
+ min-width: 0; /* Critical flex overflow containment */
+ padding: 24px 32px 100px;
+ position: relative;
+ z-index: 10;
+}
+
+.hero-command-deck {
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+ margin-bottom: 40px;
+}
+
+.hero-glass-card {
+ padding: 32px;
+ background: var(--bg-card);
+ backdrop-filter: blur(24px) saturate(190%);
+ -webkit-backdrop-filter: blur(24px) saturate(190%);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-glass);
+ position: relative;
+ overflow: hidden;
+}
+.hero-glass-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: linear-gradient(90deg, transparent, var(--accent-cyan), var(--accent-violet), transparent);
+}
+
+.hero-badge-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ margin-bottom: 16px;
+}
+.hero-pill-badge {
+ padding: 4px 12px;
+ border-radius: var(--radius-full);
+ font-size: 0.72rem;
+ font-weight: 700;
+ letter-spacing: 0.06em;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid var(--bg-card-border);
+ color: var(--text-muted);
+}
+.hero-pill-badge.badge-accent {
+ background: rgba(0, 242, 254, 0.12);
+ border-color: rgba(0, 242, 254, 0.4);
+ color: var(--accent-cyan);
+}
+.hero-pill-badge.badge-emerald {
+ background: rgba(16, 185, 129, 0.12);
+ border-color: rgba(16, 185, 129, 0.4);
+ color: var(--accent-emerald);
+}
+
+.hero-headline {
+ font-size: 2.2rem;
+ font-weight: 800;
+ line-height: 1.25;
+ margin-bottom: 14px;
+ background: linear-gradient(135deg, #ffffff 40%, var(--accent-cyan) 85%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+.hero-description {
+ font-size: 1.05rem;
+ color: var(--text-muted);
+ max-width: 860px;
+ line-height: 1.65;
+ margin-bottom: 24px;
+}
+
+.hero-action-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+.hero-btn {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ padding: 10px 20px;
+ border-radius: var(--radius-sm);
+ font-size: 0.88rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+.hero-btn.primary {
+ background: linear-gradient(135deg, var(--accent-cyan), var(--accent-blue));
+ border: none;
+ color: #040714;
+ box-shadow: 0 4px 20px rgba(0, 242, 254, 0.35);
+}
+.hero-btn.primary:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 6px 26px rgba(0, 242, 254, 0.5);
+}
+.hero-btn.secondary {
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid var(--bg-card-border);
+ color: var(--text-main);
+}
+.hero-btn.secondary:hover {
+ background: rgba(255, 255, 255, 0.1);
+ border-color: var(--accent-cyan);
+}
+
+/* Pattern Finder & Decision Matrix HUD */
+.pattern-finder-hud {
+ margin-top: 24px;
+ padding: 24px;
+ background: rgba(4, 7, 18, 0.85);
+ border: 1px solid var(--accent-cyan);
+ border-radius: var(--radius-md);
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
+}
+.finder-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 16px;
+}
+.finder-title-group {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+.finder-icon {
+ font-size: 26px;
+}
+.finder-title {
+ font-size: 1.15rem;
+ font-weight: 700;
+ color: var(--accent-cyan);
+}
+.finder-subtitle {
+ font-size: 0.82rem;
+ color: var(--text-muted);
+}
+.finder-close-btn {
+ background: transparent;
+ border: none;
+ color: var(--text-muted);
+ font-size: 18px;
+ cursor: pointer;
+}
+.finder-close-btn:hover {
+ color: var(--text-main);
+}
+.finder-filter-bar {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ margin-bottom: 16px;
+ flex-wrap: wrap;
+}
+.filter-label {
+ font-size: 0.8rem;
+ color: var(--text-dim);
+}
+.framework-filter-group {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+}
+.framework-pill {
+ padding: 4px 10px;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-full);
+ color: var(--text-muted);
+ font-size: 0.75rem;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+.framework-pill.active {
+ background: rgba(0, 242, 254, 0.2);
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+.finder-matrix-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+ gap: 12px;
+ max-height: 400px;
+ overflow-y: auto;
+}
+.finder-card {
+ padding: 12px 16px;
+ background: rgba(255, 255, 255, 0.03);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-sm);
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ text-decoration: none;
+ color: inherit;
+ transition: all var(--t-fast) ease;
+}
+.finder-card:hover {
+ border-color: var(--accent-cyan);
+ background: rgba(0, 242, 254, 0.06);
+ transform: translateY(-2px);
+}
+.finder-card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+.finder-card-title {
+ font-size: 0.88rem;
+ font-weight: 700;
+ color: var(--text-main);
+}
+.finder-card-tier {
+ font-size: 0.68rem;
+ padding: 2px 6px;
+ border-radius: 4px;
+ background: rgba(255, 255, 255, 0.05);
+ color: var(--text-dim);
+}
+.finder-card-problem {
+ font-size: 0.78rem;
+ color: var(--text-muted);
+ line-height: 1.4;
+}
+
+/* Master Diagram Card */
+.hero-diagram-card {
+ padding: 24px;
+ background: var(--bg-card);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-glass);
+}
+.diagram-card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 16px;
+}
+.diagram-title-cluster {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+.diagram-heading {
+ font-size: 0.95rem;
+ font-weight: 700;
+}
+
+/* ------------------------------------------------------------------------------
+ 7. CHAPTER ACCORDION CARDS & MODERN CSS CONTENT-VISIBILITY
+ ------------------------------------------------------------------------------ */
+
+/* Reading Controls Toolbar (Expand / Collapse & Focus Accordion - 1:1 DSA Standard) */
+.reading-controls-bar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 20px;
+ border-radius: var(--radius-md);
+ background: var(--bg-card);
+ backdrop-filter: var(--glass-blur);
+ -webkit-backdrop-filter: var(--glass-blur);
+ border: 1px solid var(--bg-card-border);
+ box-shadow: var(--shadow-sm);
+ margin-bottom: 24px;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.mode-toggles-cluster {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.mode-btn {
+ padding: 6px 14px;
+ border-radius: var(--radius-sm);
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--bg-card-border);
+ color: var(--text-muted);
+ font-family: var(--font-body);
+ font-size: 0.82rem;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.mode-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+ color: var(--text-main);
+ border-color: var(--bg-card-border-glow);
+}
+
+.mode-btn.active {
+ background: rgba(0, 242, 254, 0.14);
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+ font-weight: 600;
+ box-shadow: 0 0 12px rgba(0, 242, 254, 0.3);
+}
+
+[data-theme="mica"] .mode-btn.active {
+ background: rgba(14, 165, 233, 0.16);
+ border-color: var(--accent-blue);
+ color: var(--accent-blue);
+ box-shadow: 0 0 10px rgba(14, 165, 233, 0.25);
+}
+
+[data-theme="holo"] .mode-btn.active {
+ background: rgba(255, 170, 0, 0.18);
+ border-color: var(--accent-amber);
+ color: var(--accent-amber);
+ box-shadow: 0 0 10px rgba(255, 170, 0, 0.35);
+}
+
+[data-theme="matrix"] .mode-btn.active {
+ background: rgba(0, 255, 102, 0.15);
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+ box-shadow: 0 0 10px rgba(0, 255, 102, 0.3);
+}
+
+.chapters-container {
+ display: flex;
+ flex-direction: column;
+ gap: 28px;
+}
+
+/* Modern CSS defer-rendering for off-screen cards */
+.pattern-chapter {
+ content-visibility: auto;
+ contain-intrinsic-size: auto none auto 600px;
+ background: var(--bg-card);
+ backdrop-filter: blur(20px) saturate(180%);
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-glass);
+ overflow: hidden;
+ transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease;
+}
+.pattern-chapter:first-of-type {
+ content-visibility: visible;
+}
+.pattern-chapter:hover {
+ border-color: var(--bg-card-border-glow);
+}
+
+.chapter-header-bar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 22px 28px;
+ cursor: pointer;
+ user-select: none;
+ background: rgba(255, 255, 255, 0.02);
+ border-bottom: 1px solid transparent;
+ transition: background-color var(--t-fast) ease;
+ gap: 16px;
+}
+
+.pattern-chapter:not(.is-collapsed) .chapter-header-bar {
+ border-bottom-color: var(--bg-card-border);
+ background: rgba(0, 0, 0, 0.2);
+}
+
+.chapter-header-bar:hover {
+ background: rgba(255, 255, 255, 0.05);
+}
+
+.chapter-header-left {
+ display: flex;
+ align-items: center;
+ gap: 14px;
+ flex: 1;
+ min-width: 0;
+}
+
+.chapter-title {
+ font-family: var(--font-display);
+ font-weight: 800;
+ font-size: clamp(1.15rem, 2.5vw, 1.45rem);
+ letter-spacing: -0.01em;
+ color: var(--text-main);
+ margin: 0;
+}
+
+.chapter-header-right {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex-shrink: 0;
+}
+
+.chapter-toggle-btn {
+ padding: 5px 12px;
+ border-radius: var(--radius-sm);
+ background: rgba(255, 255, 255, 0.06);
+ border: 1px solid var(--bg-card-border);
+ color: var(--text-muted);
+ font-family: var(--font-mono);
+ font-size: 0.72rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ pointer-events: none; /* Inherits click from header */
+ transition: all var(--t-fast) ease;
+}
+
+.chapter-header-bar:hover .chapter-toggle-btn {
+ color: var(--accent-cyan);
+ border-color: var(--accent-cyan);
+}
+
+/* Chevrons */
+.chapter-chevron,
+.problem-chevron,
+.tree-chevron {
+ display: inline-block;
+ font-size: 0.75rem;
+ color: var(--text-dim);
+ transition: transform 0.22s var(--ease-spring), color 0.2s ease;
+ transform: rotate(0deg);
+ flex-shrink: 0;
+}
+
+/* Rotate down βΌ when open */
+.pattern-chapter:not(.is-collapsed) .chapter-chevron {
+ transform: rotate(90deg);
+ color: var(--accent-cyan);
+}
+
+/* Collapsible Content Body */
+.chapter-content-body {
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+ padding: 28px;
+}
+
+.pattern-chapter.is-collapsed .chapter-content-body {
+ display: none !important;
+}
+
+/* Hero Tag Badges */
+.hero-tag {
+ font-family: var(--font-mono);
+ font-size: 0.72rem;
+ font-weight: 700;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ padding: 4px 10px;
+ border-radius: var(--radius-full);
+ border: 1px solid transparent;
+}
+
+.hero-tag.tag-creational {
+ color: #ffb84d;
+ background: rgba(255, 184, 77, 0.12);
+ border-color: rgba(255, 184, 77, 0.3);
+}
+.hero-tag.tag-structural {
+ color: #38bdf8;
+ background: rgba(56, 189, 248, 0.12);
+ border-color: rgba(56, 189, 248, 0.3);
+}
+.hero-tag.tag-behavioral {
+ color: #c084fc;
+ background: rgba(192, 132, 252, 0.12);
+ border-color: rgba(192, 132, 252, 0.3);
+}
+.hero-tag.tag-architectural {
+ color: #fb7185;
+ background: rgba(251, 113, 133, 0.12);
+ border-color: rgba(251, 113, 133, 0.3);
+}
+.hero-tag.tag-foundations {
+ color: #34d399;
+ background: rgba(52, 211, 153, 0.12);
+ border-color: rgba(52, 211, 153, 0.3);
+}
+.hero-tag.tag-capstone {
+ color: #60a5fa;
+ background: rgba(96, 165, 250, 0.12);
+ border-color: rgba(96, 165, 250, 0.3);
+}
+
+/* Legacy fallback classes */
+.chapter-card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 20px 24px;
+ cursor: pointer;
+ user-select: none;
+}
+.chapter-body {
+ padding: 28px 32px 36px;
+ display: block;
+}
+.pattern-chapter.is-collapsed .chapter-body {
+ display: none !important;
+}
+
+/* ------------------------------------------------------------------------------
+ 8. TYPOGRAPHY & MARKDOWN RENDERING
+ ------------------------------------------------------------------------------ */
+
+.md-h1 {
+ font-size: 1.8rem;
+ font-weight: 800;
+ margin-bottom: 20px;
+ color: var(--text-highlight);
+}
+.md-h2 {
+ font-size: 1.35rem;
+ font-weight: 700;
+ margin: 32px 0 16px;
+ color: var(--accent-cyan);
+ border-bottom: 1px solid var(--bg-card-border);
+ padding-bottom: 8px;
+}
+.md-h3 {
+ font-size: 1.1rem;
+ font-weight: 700;
+ margin: 24px 0 12px;
+ color: var(--text-main);
+}
+.md-h4 {
+ font-size: 0.95rem;
+ font-weight: 600;
+ margin: 16px 0 8px;
+ color: var(--text-muted);
+}
+.md-p {
+ margin-bottom: 14px;
+ line-height: 1.65;
+ color: var(--text-main);
+}
+.md-ul, .md-ol {
+ margin: 12px 0 18px 24px;
+ color: var(--text-main);
+}
+.md-ul li, .md-ol li {
+ margin-bottom: 6px;
+ line-height: 1.6;
+}
+.md-blockquote {
+ border-left: 3px solid var(--accent-cyan);
+ padding: 12px 18px;
+ margin: 16px 0;
+ background: rgba(0, 242, 254, 0.05);
+ border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
+ color: var(--text-main);
+ font-style: italic;
+}
+.md-hr {
+ border: none;
+ height: 1px;
+ background: var(--bg-card-border);
+ margin: 32px 0;
+}
+.inline-code {
+ font-family: var(--font-mono);
+ font-size: 0.85em;
+ padding: 2px 6px;
+ background: rgba(255, 255, 255, 0.08);
+ border-radius: 4px;
+ color: var(--accent-cyan);
+}
+.md-link {
+ color: var(--accent-cyan);
+ text-decoration: none;
+ border-bottom: 1px dashed rgba(0, 242, 254, 0.4);
+ transition: all var(--t-fast) ease;
+}
+.md-link:hover {
+ color: #ffffff;
+ border-bottom-color: var(--accent-cyan);
+}
+
+/* ------------------------------------------------------------------------------
+ 9. TABLES & TOUCH CONTAINMENT INVARIANTS
+ ------------------------------------------------------------------------------ */
+
+.table-wrapper {
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ margin: 18px 0;
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-sm);
+ background: rgba(0, 0, 0, 0.2);
+}
+.md-table {
+ width: 100%;
+ border-collapse: collapse;
+ min-width: 520px; /* Invariant: Touch containment */
+ font-size: 0.84rem;
+}
+.md-table th {
+ background: rgba(255, 255, 255, 0.04);
+ padding: 10px 14px;
+ text-align: left;
+ font-weight: 600;
+ color: var(--accent-cyan);
+ border-bottom: 1px solid var(--bg-card-border);
+}
+.md-table td {
+ padding: 10px 14px;
+ border-bottom: 1px solid var(--bg-card-border);
+ color: var(--text-main);
+}
+.md-table tr:last-child td {
+ border-bottom: none;
+}
+.md-table tr:hover td {
+ background: rgba(255, 255, 255, 0.02);
+}
+
+/* ------------------------------------------------------------------------------
+ 10. COLLAPSIBLE DETAILS (.md-details & .md-summary)
+ ------------------------------------------------------------------------------ */
+
+.md-details {
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-md);
+ margin: 16px 0;
+ background: rgba(0, 0, 0, 0.25);
+ overflow: hidden;
+ transition: border-color var(--t-fast) ease;
+}
+.md-details[open] {
+ border-color: var(--accent-cyan);
+}
+.md-summary {
+ padding: 12px 18px;
+ cursor: pointer;
+ font-weight: 600;
+ color: var(--accent-cyan);
+ user-select: none;
+ background: rgba(255, 255, 255, 0.02);
+ transition: background var(--t-fast) ease;
+}
+.md-summary:hover {
+ background: rgba(0, 242, 254, 0.08);
+}
+.md-details-body {
+ padding: 18px;
+ border-top: 1px solid var(--bg-card-border);
+}
+
+/* ------------------------------------------------------------------------------
+ 11. MERMAID DIAGRAMS & SAFARI WEBKIT SIZING INVARIANTS
+ ------------------------------------------------------------------------------ */
+
+.canvas-container {
+ display: flex;
+ flex-direction: column;
+ border-radius: var(--radius-lg);
+ background: var(--bg-card);
+ backdrop-filter: var(--glass-blur);
+ -webkit-backdrop-filter: var(--glass-blur);
+ border: 1px solid var(--bg-card-border);
+ box-shadow: var(--shadow-sm);
+ overflow: hidden;
+ margin: 20px 0;
+}
+
+.canvas-header-bar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 20px;
+ background: rgba(0, 0, 0, 0.2);
+ border-bottom: 1px solid var(--bg-card-border);
+ gap: 12px;
+}
+
+.canvas-type-tag {
+ font-family: var(--font-mono);
+ font-size: 0.75rem;
+ color: var(--text-muted);
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.canvas-controls-group {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.canvas-tool-btn {
+ padding: 4px 10px;
+ border-radius: var(--radius-sm);
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid var(--bg-card-border);
+ color: var(--text-main);
+ font-family: var(--font-mono);
+ font-size: 0.8rem;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+
+.canvas-tool-btn:hover {
+ background: rgba(255, 255, 255, 0.12);
+ border-color: var(--accent-cyan);
+}
+
+.zoom-level-badge {
+ font-family: var(--font-mono);
+ font-size: 0.75rem;
+ color: var(--accent-cyan);
+ min-width: 44px;
+ text-align: center;
+}
+
+.canvas-viewport {
+ overflow: auto;
+ padding: 28px 20px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 240px;
+ max-height: 640px;
+ cursor: grab;
+ user-select: none;
+}
+
+.canvas-viewport:active {
+ cursor: grabbing;
+}
+
+.canvas-content-surface {
+ transform-origin: center center;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ margin: auto;
+ will-change: transform;
+}
+
+.canvas-content-surface svg {
+ display: block;
+ max-width: 100%;
+ height: auto !important;
+}
+
+.canvas-caption {
+ padding: 8px 16px;
+ background: rgba(0, 0, 0, 0.15);
+ border-top: 1px solid var(--bg-card-border);
+ font-size: 0.72rem;
+ font-family: var(--font-mono);
+ color: var(--text-dim);
+ text-align: center;
+}
+
+/* Legacy alias support */
+.mermaid-workbench {
+ margin: 20px 0;
+ border-radius: var(--radius-lg);
+ background: var(--bg-card);
+ border: 1px solid var(--bg-card-border);
+ overflow: hidden;
+}
+.mermaid-controls {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 10px 18px;
+ background: rgba(0, 0, 0, 0.2);
+ border-bottom: 1px solid var(--bg-card-border);
+}
+.mermaid-container {
+ padding: 20px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 120px;
+ overflow-x: auto;
+}
+
+/* MANDATORY SAFARI WEBKIT FLEX-SVG SIZING INVARIANT:
+ Never use 'width: auto !important' on .mermaid svg inside flex containers. */
+.mermaid svg {
+ display: block !important;
+ width: 100% !important;
+ max-width: 100% !important;
+ height: auto !important;
+ max-height: 580px !important;
+ object-fit: contain;
+ margin: 0 auto;
+}
+
+/* ------------------------------------------------------------------------------
+ 11b. MERMAID HIGH-CONTRAST THEMING & ZERO-TRUNCATION ENGINE
+ ------------------------------------------------------------------------------ */
+.mermaid,
+.mermaid svg,
+.theater-content-surface,
+.theater-content-surface svg {
+ color: var(--text-main);
+ font-family: var(--font-body);
+}
+
+/* Dynamic Box Sizing & Universal Text Overflow Containment */
+.mermaid svg text,
+.mermaid svg tspan,
+.theater-content-surface svg text,
+.theater-content-surface svg tspan {
+ font-family: var(--font-body) !important;
+ overflow: visible !important;
+}
+
+.mermaid svg foreignObject,
+.theater-content-surface svg foreignObject {
+ overflow: visible !important;
+}
+
+.mermaid svg foreignObject div,
+.theater-content-surface svg foreignObject div {
+ display: inline-block !important;
+ text-align: center !important;
+ box-sizing: border-box !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ line-height: normal !important;
+}
+
+/* Flowchart & Architecture Nodes */
+.mermaid svg .node rect,
+.mermaid svg .node circle,
+.mermaid svg .node ellipse,
+.mermaid svg .node polygon,
+.mermaid svg .node path,
+.theater-content-surface svg .node rect,
+.theater-content-surface svg .node circle,
+.theater-content-surface svg .node ellipse,
+.theater-content-surface svg .node polygon,
+.theater-content-surface svg .node path {
+ stroke-width: 1.5px !important;
+ rx: 8px !important;
+ ry: 8px !important;
+ transition: all var(--t-fast) ease;
+}
+
+/* Flowchart Node Text */
+.mermaid svg .node .label,
+.mermaid svg .node text,
+.mermaid svg .node span,
+.theater-content-surface svg .node .label,
+.theater-content-surface svg .node text,
+.theater-content-surface svg .node span {
+ fill: var(--text-main) !important;
+ color: var(--text-main) !important;
+ font-weight: 500 !important;
+ font-size: 14px !important;
+}
+
+/* Subgraph Clusters (Component Boundaries) */
+.mermaid svg .cluster rect,
+.theater-content-surface svg .cluster rect {
+ fill: rgba(10, 16, 32, 0.65) !important;
+ stroke: rgba(255, 255, 255, 0.15) !important;
+ stroke-width: 1px !important;
+ stroke-dasharray: 4 4;
+ rx: 12px !important;
+}
+
+.mermaid svg .cluster text,
+.mermaid svg .cluster span,
+.theater-content-surface svg .cluster text,
+.theater-content-surface svg .cluster span {
+ fill: var(--accent-cyan) !important;
+ color: var(--accent-cyan) !important;
+ font-weight: 600 !important;
+ font-size: 13px !important;
+ text-transform: none !important;
+ letter-spacing: normal !important;
+}
+
+/* Edge Labels & Connectors */
+.mermaid svg .edgeLabel,
+.theater-content-surface svg .edgeLabel {
+ background-color: var(--bg-card) !important;
+ border-radius: var(--radius-sm);
+}
+
+.mermaid svg .edgeLabel rect,
+.theater-content-surface svg .edgeLabel rect {
+ fill: var(--bg-deep) !important;
+ opacity: 0.9;
+ rx: 4px;
+}
+
+.mermaid svg .edgeLabel text,
+.mermaid svg .edgeLabel span,
+.theater-content-surface svg .edgeLabel text,
+.theater-content-surface svg .edgeLabel span {
+ fill: var(--text-muted) !important;
+ color: var(--text-muted) !important;
+ font-size: 0.78rem !important;
+ font-family: var(--font-mono) !important;
+}
+
+.mermaid svg .flowchart-link,
+.mermaid svg path.path,
+.theater-content-surface svg .flowchart-link,
+.theater-content-surface svg path.path {
+ stroke: rgba(148, 163, 184, 0.6) !important;
+ stroke-width: 1.5px !important;
+}
+
+/* UML Class Diagrams */
+.mermaid svg g.classGroup rect,
+.theater-content-surface svg g.classGroup rect {
+ fill: var(--bg-card) !important;
+ stroke: var(--bg-card-border-glow) !important;
+ stroke-width: 1.5px !important;
+ rx: 6px;
+}
+
+.mermaid svg g.classGroup text,
+.theater-content-surface svg g.classGroup text {
+ fill: var(--text-main) !important;
+ color: var(--text-main) !important;
+ font-size: 0.82rem !important;
+}
+
+/* Mindmap Theming (Eliminates Black-on-Black Contrast Failure) */
+.mermaid svg .mindmap-node text,
+.mermaid svg .mindmap-node tspan,
+.theater-content-surface svg .mindmap-node text,
+.theater-content-surface svg .mindmap-node tspan {
+ fill: #ffffff !important;
+ color: #ffffff !important;
+ font-weight: 600 !important;
+ font-size: 0.88rem !important;
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8) !important;
+}
+
+/* Mindmap Root Node */
+.mermaid svg .mindmap-node.section-root rect,
+.mermaid svg .mindmap-node.section-root circle,
+.theater-content-surface svg .mindmap-node.section-root rect,
+.theater-content-surface svg .mindmap-node.section-root circle {
+ fill: #0ea5e9 !important;
+ stroke: #38bdf8 !important;
+ stroke-width: 2.5px !important;
+}
+
+/* Mindmap Section Nodes (Vibrant Jewels with White Text) */
+.mermaid svg .mindmap-node.section-0 rect,
+.mermaid svg .mindmap-node.section-0 path,
+.theater-content-surface svg .mindmap-node.section-0 rect,
+.theater-content-surface svg .mindmap-node.section-0 path {
+ fill: #0284c7 !important;
+ stroke: #38bdf8 !important;
+}
+
+.mermaid svg .mindmap-node.section-1 rect,
+.mermaid svg .mindmap-node.section-1 path,
+.theater-content-surface svg .mindmap-node.section-1 rect,
+.theater-content-surface svg .mindmap-node.section-1 path {
+ fill: #7c3aed !important;
+ stroke: #a855f7 !important;
+}
+
+.mermaid svg .mindmap-node.section-2 rect,
+.mermaid svg .mindmap-node.section-2 path,
+.theater-content-surface svg .mindmap-node.section-2 rect,
+.theater-content-surface svg .mindmap-node.section-2 path {
+ fill: #059669 !important;
+ stroke: #34d399 !important;
+}
+
+.mermaid svg .mindmap-node.section-3 rect,
+.mermaid svg .mindmap-node.section-3 path,
+.theater-content-surface svg .mindmap-node.section-3 rect,
+.theater-content-surface svg .mindmap-node.section-3 path {
+ fill: #d97706 !important;
+ stroke: #fbbf24 !important;
+}
+
+.mermaid svg .mindmap-node.section-4 rect,
+.mermaid svg .mindmap-node.section-4 path,
+.theater-content-surface svg .mindmap-node.section-4 rect,
+.theater-content-surface svg .mindmap-node.section-4 path {
+ fill: #e11d48 !important;
+ stroke: #fb7185 !important;
+}
+
+/* Mindmap Edges */
+.mermaid svg path.section-edge-0, .theater-content-surface svg path.section-edge-0 { stroke: #38bdf8 !important; stroke-width: 2px !important; }
+.mermaid svg path.section-edge-1, .theater-content-surface svg path.section-edge-1 { stroke: #a855f7 !important; stroke-width: 2px !important; }
+.mermaid svg path.section-edge-2, .theater-content-surface svg path.section-edge-2 { stroke: #34d399 !important; stroke-width: 2px !important; }
+.mermaid svg path.section-edge-3, .theater-content-surface svg path.section-edge-3 { stroke: #fbbf24 !important; stroke-width: 2px !important; }
+.mermaid svg path.section-edge-4, .theater-content-surface svg path.section-edge-4 { stroke: #fb7185 !important; stroke-width: 2px !important; }
+
+/* THEME OVERRIDES FOR AERO MICA (HIGH CONTRAST ON BRIGHT FROSTED SURFACE) */
+[data-theme="mica"] .mermaid svg .node rect,
+[data-theme="mica"] .mermaid svg .node circle,
+[data-theme="mica"] .mermaid svg .node polygon,
+[data-theme="mica"] .mermaid svg .node path,
+[data-theme="mica"] .theater-content-surface svg .node rect,
+[data-theme="mica"] .theater-content-surface svg .node circle,
+[data-theme="mica"] .theater-content-surface svg .node polygon,
+[data-theme="mica"] .theater-content-surface svg .node path {
+ fill: #ffffff !important;
+ stroke: rgba(14, 165, 233, 0.45) !important;
+}
+
+[data-theme="mica"] .mermaid svg .node .label,
+[data-theme="mica"] .mermaid svg .node text,
+[data-theme="mica"] .mermaid svg .node span,
+[data-theme="mica"] .theater-content-surface svg .node .label,
+[data-theme="mica"] .theater-content-surface svg .node text,
+[data-theme="mica"] .theater-content-surface svg .node span {
+ fill: #0f172a !important;
+ color: #0f172a !important;
+}
+
+[data-theme="mica"] .mermaid svg .cluster rect,
+[data-theme="mica"] .theater-content-surface svg .cluster rect {
+ fill: rgba(241, 245, 249, 0.85) !important;
+ stroke: rgba(15, 23, 42, 0.22) !important;
+}
+
+[data-theme="mica"] .mermaid svg .cluster text,
+[data-theme="mica"] .mermaid svg .cluster span,
+[data-theme="mica"] .theater-content-surface svg .cluster text,
+[data-theme="mica"] .theater-content-surface svg .cluster span {
+ fill: #0284c7 !important;
+ color: #0284c7 !important;
+}
+
+[data-theme="mica"] .mermaid svg g.classGroup rect,
+[data-theme="mica"] .theater-content-surface svg g.classGroup rect {
+ fill: #ffffff !important;
+ stroke: rgba(14, 165, 233, 0.45) !important;
+}
+
+[data-theme="mica"] .mermaid svg g.classGroup text,
+[data-theme="mica"] .theater-content-surface svg g.classGroup text {
+ fill: #0f172a !important;
+ color: #0f172a !important;
+}
+
+/* Mica Mindmap Theming (Pastel Jewel Cards with High-Contrast Dark Text) */
+[data-theme="mica"] .mermaid svg .mindmap-node.section-root rect,
+[data-theme="mica"] .mermaid svg .mindmap-node.section-root circle,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-root rect,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-root circle {
+ fill: #e0f2fe !important;
+ stroke: #0284c7 !important;
+}
+
+[data-theme="mica"] .mermaid svg .mindmap-node.section-0 rect,
+[data-theme="mica"] .mermaid svg .mindmap-node.section-0 path,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-0 rect,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-0 path {
+ fill: #bae6fd !important;
+ stroke: #0284c7 !important;
+}
+
+[data-theme="mica"] .mermaid svg .mindmap-node.section-1 rect,
+[data-theme="mica"] .mermaid svg .mindmap-node.section-1 path,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-1 rect,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-1 path {
+ fill: #ede9fe !important;
+ stroke: #7c3aed !important;
+}
+
+[data-theme="mica"] .mermaid svg .mindmap-node.section-2 rect,
+[data-theme="mica"] .mermaid svg .mindmap-node.section-2 path,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-2 rect,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-2 path {
+ fill: #d1fae5 !important;
+ stroke: #059669 !important;
+}
+
+[data-theme="mica"] .mermaid svg .mindmap-node.section-3 rect,
+[data-theme="mica"] .mermaid svg .mindmap-node.section-3 path,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-3 rect,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-3 path {
+ fill: #fef3c7 !important;
+ stroke: #d97706 !important;
+}
+
+[data-theme="mica"] .mermaid svg .mindmap-node.section-4 rect,
+[data-theme="mica"] .mermaid svg .mindmap-node.section-4 path,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-4 rect,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node.section-4 path {
+ fill: #ffe4e6 !important;
+ stroke: #e11d48 !important;
+}
+
+[data-theme="mica"] .mermaid svg .mindmap-node text,
+[data-theme="mica"] .mermaid svg .mindmap-node tspan,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node text,
+[data-theme="mica"] .theater-content-surface svg .mindmap-node tspan {
+ fill: #0f172a !important;
+ color: #0f172a !important;
+ font-weight: 600 !important;
+ text-shadow: none !important;
+}
+
+/* THEME OVERRIDES FOR CYBERPUNK HOLO */
+[data-theme="holo"] .mermaid svg .cluster text,
+[data-theme="holo"] .theater-content-surface svg .cluster text {
+ fill: #ffaa00 !important;
+ color: #ffaa00 !important;
+}
+
+/* THEME OVERRIDES FOR OBSIDIAN MATRIX */
+[data-theme="matrix"] .mermaid svg .cluster text,
+[data-theme="matrix"] .theater-content-surface svg .cluster text {
+ fill: #00ff66 !important;
+ color: #00ff66 !important;
+}
+
+/* ------------------------------------------------------------------------------
+ 12. CODE CONTAINERS & INTERACTIVE PYTHON EXAMPLES
+ ------------------------------------------------------------------------------ */
+
+.code-container {
+ margin: 16px 0;
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-md);
+ background: var(--code-bg);
+ overflow: hidden;
+}
+.code-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 8px 14px;
+ background: rgba(255, 255, 255, 0.03);
+ border-bottom: 1px solid var(--bg-card-border);
+}
+.code-container pre,
+.example-card pre {
+ margin: 0;
+ padding: 16px;
+ overflow-x: auto;
+ font-family: var(--font-mono);
+ font-size: 0.84rem;
+ line-height: 1.55;
+ color: var(--text-main);
+}
+.code-container code,
+.example-card code {
+ font-family: inherit;
+ color: inherit;
+}
+
+.copy-btn {
+ padding: 4px 10px;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid var(--bg-card-border);
+ border-radius: 4px;
+ color: var(--text-muted);
+ font-size: 0.72rem;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+.copy-btn:hover {
+ color: var(--accent-cyan);
+ border-color: var(--accent-cyan);
+}
+.copy-btn.copied {
+ background: var(--accent-emerald);
+ color: #040714;
+ border-color: var(--accent-emerald);
+}
+
+/* Python Implementation Examples Section */
+.chapter-examples-section {
+ margin-top: 36px;
+ border-top: 1px solid var(--bg-card-border);
+ padding-top: 24px;
+ display: flex;
+ flex-direction: column;
+ gap: 18px;
+}
+.section-subheading {
+ font-size: 1.05rem;
+ font-weight: 700;
+ color: var(--accent-cyan);
+}
+
+.example-card {
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-md);
+ background: var(--code-bg);
+ overflow: hidden;
+}
+.example-card-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 18px;
+ background: rgba(255, 255, 255, 0.03);
+ border-bottom: 1px solid var(--bg-card-border);
+ flex-wrap: wrap;
+ gap: 10px;
+}
+.example-title-cluster {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+.example-filename {
+ font-family: var(--font-mono);
+ font-size: 0.8rem;
+ color: var(--text-dim);
+}
+.example-title {
+ font-size: 0.92rem;
+ font-weight: 700;
+ color: var(--text-main);
+}
+.example-meta-cluster {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+.example-lines {
+ font-size: 0.72rem;
+ color: var(--text-dim);
+ font-family: var(--font-mono);
+}
+
+.example-meta-bar {
+ padding: 10px 18px;
+ background: rgba(0, 0, 0, 0.2);
+ border-bottom: 1px solid var(--bg-card-border);
+ font-size: 0.82rem;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+.meta-scenario strong,
+.meta-insight strong {
+ color: var(--accent-cyan);
+}
+
+/* ------------------------------------------------------------------------------
+ 13. SEMANTIC BADGES (.dna-label)
+ ------------------------------------------------------------------------------ */
+
+.dna-label {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ padding: 2px 8px;
+ border-radius: 4px;
+ font-family: var(--font-mono);
+ font-size: 0.72rem;
+ font-weight: 600;
+ letter-spacing: 0.03em;
+ background: rgba(255, 255, 255, 0.05);
+ border: 1px solid var(--bg-card-border);
+}
+.dna-label-code {
+ color: var(--accent-cyan);
+ border-color: rgba(0, 242, 254, 0.3);
+ background: rgba(0, 242, 254, 0.08);
+}
+.dna-label-django {
+ color: #2ba674;
+ border-color: rgba(43, 166, 116, 0.3);
+ background: rgba(43, 166, 116, 0.08);
+}
+.dna-label-fastapi {
+ color: #05998b;
+ border-color: rgba(5, 153, 139, 0.3);
+ background: rgba(5, 153, 139, 0.08);
+}
+.dna-label-sqlalchemy {
+ color: #e25555;
+ border-color: rgba(226, 85, 85, 0.3);
+ background: rgba(226, 85, 85, 0.08);
+}
+.dna-label-celery {
+ color: #a4ce3a;
+ border-color: rgba(164, 206, 58, 0.3);
+ background: rgba(164, 206, 58, 0.08);
+}
+.dna-label-matrix {
+ color: var(--accent-amber);
+ border-color: rgba(245, 158, 11, 0.3);
+ background: rgba(245, 158, 11, 0.08);
+}
+.dna-label-tree {
+ color: var(--accent-emerald);
+ border-color: rgba(16, 185, 129, 0.3);
+ background: rgba(16, 185, 129, 0.08);
+}
+.dna-label-spec,
+.dna-label-blueprint {
+ color: var(--accent-violet);
+ border-color: rgba(168, 85, 247, 0.3);
+ background: rgba(168, 85, 247, 0.08);
+}
+
+/* ------------------------------------------------------------------------------
+ 14. FULLSCREEN THEATER MODE WORKBENCH ()
+ ------------------------------------------------------------------------------ */
+
+#theater-modal,
+.theater-modal,
+.theater-dialog {
+ position: fixed;
+ inset: 0;
+ width: 100vw;
+ height: 100vh;
+ max-width: 100vw;
+ max-height: 100vh;
+ margin: 0;
+ padding: 0;
+ border: none;
+ background: rgba(5, 8, 19, 0.96);
+ backdrop-filter: blur(28px) saturate(180%);
+ -webkit-backdrop-filter: blur(28px) saturate(180%);
+ z-index: 999999;
+ display: none;
+ flex-direction: column;
+ overscroll-behavior: contain;
+}
+
+dialog#theater-modal[open],
+dialog.theater-modal[open],
+dialog.theater-dialog[open] {
+ display: flex;
+}
+
+dialog#theater-modal::backdrop,
+dialog.theater-modal::backdrop,
+dialog.theater-dialog::backdrop {
+ background: rgba(3, 5, 12, 0.92);
+ backdrop-filter: blur(20px);
+ -webkit-backdrop-filter: blur(20px);
+ overflow: hidden;
+ overscroll-behavior: contain;
+ cursor: pointer;
+}
+
+body.theater-open {
+ overflow: hidden !important;
+}
+
+.theater-header-bar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px 28px;
+ background: rgba(10, 15, 30, 0.94);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.14);
+ gap: 16px;
+ flex-shrink: 0;
+ z-index: 10;
+}
+
+.theater-title-cluster {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.theater-icon {
+ font-size: 1.3rem;
+}
+
+.theater-title {
+ font-family: var(--font-display);
+ font-weight: 700;
+ font-size: 1.15rem;
+ color: #f8fafc !important;
+ margin: 0;
+ letter-spacing: -0.01em;
+}
+
+.theater-controls-cluster {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.theater-tool-btn {
+ padding: 6px 14px;
+ border-radius: var(--radius-sm);
+ background: rgba(30, 41, 59, 0.95);
+ border: 1px solid rgba(148, 163, 184, 0.3);
+ color: #f1f5f9;
+ font-family: var(--font-mono);
+ font-size: 0.8rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all var(--t-fast) ease;
+}
+
+.theater-tool-btn:hover {
+ background: rgba(51, 65, 85, 0.98);
+ border-color: var(--accent-cyan);
+ color: #ffffff;
+}
+
+.theater-close-btn {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ padding: 6px 14px;
+ border-radius: var(--radius-full);
+ background: rgba(244, 63, 94, 0.15) !important;
+ border: 1px solid rgba(244, 63, 94, 0.45) !important;
+ color: #fda4af !important;
+ font-family: var(--font-mono);
+ font-size: 0.82rem;
+ font-weight: 600;
+ cursor: pointer;
+ margin-left: 10px;
+ backdrop-filter: blur(8px);
+ -webkit-backdrop-filter: blur(8px);
+ transition: all var(--t-fast) cubic-bezier(0.16, 1, 0.3, 1);
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.08);
+}
+
+.theater-close-btn:hover {
+ background: rgba(244, 63, 94, 0.35) !important;
+ border-color: #fb7185 !important;
+ color: #ffffff !important;
+ box-shadow: 0 0 20px rgba(244, 63, 94, 0.55), 0 4px 14px rgba(0, 0, 0, 0.4);
+ transform: translateY(-1px);
+}
+
+.theater-close-btn:active {
+ transform: translateY(0);
+}
+
+.close-icon-svg {
+ flex-shrink: 0;
+ transition: transform 0.22s ease;
+}
+
+.theater-close-btn:hover .close-icon-svg {
+ transform: rotate(90deg);
+}
+
+.close-kbd-badge {
+ display: inline-flex;
+ align-items: center;
+ padding: 1px 5px;
+ font-size: 0.65rem;
+ font-weight: 700;
+ letter-spacing: 0.05em;
+ background: rgba(0, 0, 0, 0.35);
+ border: 1px solid rgba(244, 63, 94, 0.3);
+ border-radius: 4px;
+ color: #fecdd3;
+ line-height: 1.2;
+}
+
+[data-theme="mica"] .theater-close-btn {
+ background: rgba(225, 29, 72, 0.1) !important;
+ border-color: rgba(225, 29, 72, 0.35) !important;
+ color: #e11d48 !important;
+}
+
+[data-theme="mica"] .theater-close-btn:hover {
+ background: #e11d48 !important;
+ color: #ffffff !important;
+ border-color: #be123c !important;
+ box-shadow: 0 0 16px rgba(225, 29, 72, 0.4);
+}
+
+[data-theme="mica"] .close-kbd-badge {
+ background: rgba(255, 255, 255, 0.85);
+ color: #9f1239;
+ border-color: rgba(225, 29, 72, 0.25);
+}
+
+.theater-viewport {
+ flex: 1;
+ overflow: hidden;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ cursor: grab;
+ user-select: none;
+ -webkit-user-select: none;
+ padding: 24px;
+}
+
+.theater-viewport:active {
+ cursor: grabbing;
+}
+
+.theater-content-surface {
+ transform-origin: center center;
+ transition: none !important;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ margin: auto;
+ border-radius: var(--radius-md);
+ will-change: transform;
+}
+
+.theater-content-surface svg {
+ display: block !important;
+ max-width: none !important;
+ max-height: none !important;
+ overflow: visible !important;
+}
+
+.theater-content-surface svg text,
+.theater-content-surface svg foreignObject,
+.theater-content-surface svg span {
+ user-select: text !important;
+ -webkit-user-select: text !important;
+}
+
+/* ------------------------------------------------------------------------------
+ 15. GLOBAL SEARCH MODAL HUD ()
+ ------------------------------------------------------------------------------ */
+
+.search-modal {
+ width: 90vw;
+ max-width: 680px;
+ margin: 12vh auto auto;
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-lg);
+ background: var(--bg-deep);
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8), 0 0 1px 1px var(--bg-card-border);
+ padding: 0;
+ display: none;
+ z-index: 2100;
+ overscroll-behavior: contain;
+}
+.search-modal[open] {
+ display: block;
+}
+.search-modal::backdrop {
+ background: rgba(0, 0, 0, 0.75);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+}
+.search-card {
+ padding: 20px;
+}
+.search-input-wrapper {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 10px 16px;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-md);
+ margin-bottom: 14px;
+}
+.search-input-icon {
+ color: var(--accent-cyan);
+}
+.search-input {
+ flex: 1;
+ background: transparent;
+ border: none;
+ outline: none;
+ color: var(--text-main);
+ font-family: var(--font-sans);
+ font-size: 1rem;
+}
+.search-kbd-esc {
+ font-family: var(--font-mono);
+ font-size: 0.68rem;
+ padding: 2px 6px;
+ background: rgba(255, 255, 255, 0.08);
+ border-radius: 4px;
+ color: var(--text-dim);
+}
+
+.search-filter-pills {
+ display: flex;
+ gap: 6px;
+ margin-bottom: 16px;
+ overflow-x: auto;
+}
+.search-pill {
+ padding: 4px 10px;
+ background: rgba(255, 255, 255, 0.03);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-full);
+ color: var(--text-dim);
+ font-size: 0.74rem;
+ cursor: pointer;
+ white-space: nowrap;
+}
+.search-pill.active {
+ background: rgba(0, 242, 254, 0.15);
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+
+.search-results-list {
+ max-height: 380px;
+ overflow-y: auto;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+.search-result-item {
+ padding: 12px 16px;
+ background: rgba(255, 255, 255, 0.02);
+ border: 1px solid var(--bg-card-border);
+ border-radius: var(--radius-sm);
+ text-decoration: none;
+ color: inherit;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ transition: all var(--t-fast) ease;
+}
+.search-result-item:hover,
+.search-result-item.selected {
+ background: rgba(0, 242, 254, 0.08);
+ border-color: var(--accent-cyan);
+}
+.search-result-top {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+.search-result-title {
+ font-size: 0.9rem;
+ font-weight: 700;
+ color: var(--accent-cyan);
+}
+.search-result-badge {
+ font-size: 0.68rem;
+ padding: 2px 6px;
+ background: rgba(255, 255, 255, 0.04);
+ border-radius: 4px;
+ color: var(--text-dim);
+}
+.search-result-snippet {
+ font-size: 0.8rem;
+ color: var(--text-muted);
+}
+.search-empty-state {
+ text-align: center;
+ padding: 40px 20px;
+ color: var(--text-dim);
+ font-size: 0.88rem;
+}
+
+/* ------------------------------------------------------------------------------
+ 16. AERO MICA CONTRAST INVARIANTS (Explicit Fix for Past Contrast Trap)
+ ------------------------------------------------------------------------------ */
+
+[data-theme="mica"] .dna-skeleton-box,
+[data-theme="mica"] .code-container,
+[data-theme="mica"] .example-card {
+ background: rgba(255, 255, 255, 0.95) !important;
+ border-color: rgba(30, 41, 59, 0.18) !important;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06) !important;
+}
+
+[data-theme="mica"] .code-container pre,
+[data-theme="mica"] .code-container code,
+[data-theme="mica"] .example-card pre,
+[data-theme="mica"] .example-card code {
+ color: #0f172a !important;
+}
+
+[data-theme="mica"] .theater-tool-btn {
+ background: rgba(255, 255, 255, 0.22) !important;
+ border: 1px solid rgba(255, 255, 255, 0.55) !important;
+ color: #ffffff !important;
+ box-shadow: 0 0 10px rgba(255, 255, 255, 0.2) !important;
+}
+
+[data-theme="mica"] .hero-headline {
+ background: linear-gradient(135deg, #0f172a 40%, var(--accent-blue) 85%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+[data-theme="mica"] .md-summary {
+ background: rgba(241, 245, 249, 0.8);
+ color: #0284c7;
+}
+
+/* ------------------------------------------------------------------------------
+ 17. FLASH FOCUS & ANIMATIONS
+ ------------------------------------------------------------------------------ */
+
+@keyframes flashFocusPulse {
+ 0% { outline: 3px solid var(--accent-cyan); box-shadow: 0 0 30px var(--accent-cyan); }
+ 50% { outline: 3px solid var(--accent-violet); box-shadow: 0 0 40px var(--accent-violet); }
+ 100% { outline: 1px solid transparent; box-shadow: none; }
+}
+
+.flash-focus {
+ animation: flashFocusPulse 1.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
+}
+
+/* ------------------------------------------------------------------------------
+ 18. COMMUTE GADGET RESPONSIVE MOBILE DRAWER (<= 1024px)
+ ------------------------------------------------------------------------------ */
+
+@media (max-width: 1024px) {
+ .mobile-nav-toggle {
+ display: block;
+ }
+ .sidebar-dock-toggle {
+ display: none;
+ }
+ .floating-sidebar-toggle {
+ display: none !important;
+ }
+
+ .sidebar {
+ position: fixed;
+ top: var(--topbar-height);
+ left: 0;
+ bottom: 0;
+ height: calc(100vh - var(--topbar-height));
+ width: min(86vw, 360px);
+ z-index: 1200;
+ transform: translateX(-100%);
+ transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
+ }
+ body.mobile-drawer-open .sidebar {
+ transform: translateX(0);
+ }
+
+ .mobile-drawer-backdrop {
+ position: fixed;
+ inset: 0;
+ background: rgba(0, 0, 0, 0.65);
+ backdrop-filter: blur(8px);
+ -webkit-backdrop-filter: blur(8px);
+ z-index: 1100;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.25s ease;
+ }
+ body.mobile-drawer-open .mobile-drawer-backdrop {
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ .sidebar-resizer {
+ display: none !important;
+ }
+
+ .content-area {
+ padding: 16px 18px 80px;
+ }
+ .hero-glass-card {
+ padding: 20px;
+ }
+ .hero-headline {
+ font-size: 1.6rem;
+ }
+ .header-telemetry-cluster {
+ display: none;
+ }
+}
diff --git a/scripts/audit_ascii_boxes.py b/scripts/audit_ascii_boxes.py
new file mode 100755
index 0000000..33db3e4
--- /dev/null
+++ b/scripts/audit_ascii_boxes.py
@@ -0,0 +1,356 @@
+#!/usr/bin/env python3
+"""
+==============================================================================
+audit_ascii_boxes.py β Unicode / ASCII Box-Drawing Alignment Linter & Formatter
+==============================================================================
+Validates and automatically aligns monospace ASCII/Unicode box-drawing tables,
+cards, and diagrams across all documentation markdown files.
+
+Handles:
+- Visual display width computation per Unicode UAX #11 (East Asian Width).
+- Wide characters & emojis (e.g. π’, π, π, π―, β
, π₯) having width 2.
+- Zero-width modifiers (e.g. \uFE0F variation selector, \u200D ZWJ).
+- Single-column box cards (ββ...ββ, β...β, ββ...ββ).
+- Multi-column box tables (βββ¬ββ, β...β...β, βββΌββ€, βββ΄ββ).
+- Subgraph connectors (βββ¬ββ, βββ΄ββ).
+
+CLI Usage:
+ python3 scripts/audit_ascii_boxes.py --check # Validate in CI / pre-commit
+ python3 scripts/audit_ascii_boxes.py --fix # Auto-align in place
+ python3 scripts/audit_ascii_boxes.py path/to/file.md # Target specific file
+"""
+
+import os
+import sys
+import re
+import argparse
+import unicodedata
+from typing import List, Tuple, Optional
+
+
+def char_display_width(ch: str) -> int:
+ """Return the monospace visual display column width of a single character."""
+ # Zero-width characters (variation selectors, combining marks, format chars)
+ if ch in ('\ufe0f', '\ufe0e', '\u200d', '\u200b', '\u200c', '\u200e', '\u200f'):
+ return 0
+ cp = ord(ch)
+ if unicodedata.category(ch) in ('Mn', 'Me', 'Cf'):
+ return 0
+ # Explicit East Asian Wide or Fullwidth
+ ea = unicodedata.east_asian_width(ch)
+ if ea in ('W', 'F'):
+ return 2
+ # Standard emoji ranges that render as 2 columns in terminal & monospace browser fonts
+ if 0x1F000 <= cp <= 0x1FAFF:
+ return 2
+ # Specific common 2-column emojis in Miscellaneous & Dingbats (2600-27BF)
+ if ch in ('β
', 'β‘', 'β οΈ', 'β', 'β', 'β³', 'β', 'β°', 'β±', 'β²', 'β', 'β', 'β', 'β', 'β', 'β', 'β', 'β', 'β', 'β', 'β', 'β€', 'π', 'β', 'π'):
+ return 2
+ # Mathematical long double arrow βΉ (0x27F9)
+ if cp == 0x27F9:
+ return 2
+ return 1
+
+
+def str_display_width(s: str) -> int:
+ """Compute the total monospace visual display width of a string."""
+ return sum(char_display_width(ch) for ch in s)
+
+
+def is_box_top(line: str) -> bool:
+ s = line.strip()
+ return s.startswith('β') and s.endswith('β') and 'β' in s
+
+
+def is_box_bottom(line: str) -> bool:
+ s = line.strip()
+ return s.startswith('β') and s.endswith('β') and ('β' in s or 'β' in s)
+
+
+def is_box_middle(line: str) -> bool:
+ s = line.strip()
+ return (s.startswith('β') and s.endswith('β')) or (s.startswith('β') and s.endswith('β€'))
+
+
+def align_single_column_box(box_lines: List[str]) -> List[str]:
+ """Realign a single-column box (e.g. callout card, definition pill, pillar)."""
+ if not box_lines:
+ return box_lines
+
+ indent_len = len(box_lines[0]) - len(box_lines[0].lstrip())
+ indent_str = box_lines[0][:indent_len]
+
+ max_body_w = 0
+ for line in box_lines:
+ s = line.strip()
+ if s.startswith('β') and s.endswith('β'):
+ body = s[1:-1]
+ bw = str_display_width(body.rstrip())
+ if bw > max_body_w:
+ max_body_w = bw
+
+ # Determine target content width
+ top_stripped = box_lines[0].strip()
+ top_dashes = str_display_width(top_stripped[1:-1])
+ target_w = max(top_dashes, max_body_w + 1)
+
+ new_lines = []
+ for line in box_lines:
+ s = line.strip()
+ if s.startswith('β') and s.endswith('β'):
+ new_lines.append(indent_str + 'β' + ('β' * target_w) + 'β')
+ elif s.startswith('β') and s.endswith('β€'):
+ new_lines.append(indent_str + 'β' + ('β' * target_w) + 'β€')
+ elif s.startswith('β') and s.endswith('β'):
+ # Preserve special connectors like β΄ or β¬ if present
+ if 'β¬' in s or 'β΄' in s:
+ conn = 'β¬' if 'β¬' in s else 'β΄'
+ half = (target_w - 1) // 2
+ rem = target_w - 1 - half
+ new_lines.append(indent_str + 'β' + ('β' * half) + conn + ('β' * rem) + 'β')
+ else:
+ new_lines.append(indent_str + 'β' + ('β' * target_w) + 'β')
+ elif s.startswith('β') and s.endswith('β'):
+ body = s[1:-1]
+ body_trimmed = body.rstrip()
+ pad = target_w - str_display_width(body_trimmed)
+ if pad < 0:
+ pad = 0
+ new_lines.append(indent_str + 'β' + body_trimmed + (' ' * pad) + 'β')
+ else:
+ new_lines.append(line)
+
+ return new_lines
+
+
+def align_multi_column_box(box_lines: List[str]) -> List[str]:
+ """Realign a multi-column box table (e.g. system comparisons, triage tables)."""
+ if not box_lines:
+ return box_lines
+
+ indent_len = len(box_lines[0]) - len(box_lines[0].lstrip())
+ indent_str = box_lines[0][:indent_len]
+
+ # Find number of columns from lines with β
+ num_cols = 0
+ for line in box_lines:
+ s = line.strip()
+ if s.startswith('β') and s.endswith('β'):
+ parts = s[1:-1].split('β')
+ num_cols = max(num_cols, len(parts))
+
+ if num_cols <= 1:
+ return align_single_column_box(box_lines)
+
+ # Determine max needed width for each column
+ col_widths = [0] * num_cols
+
+ # First check existing border splits
+ for line in box_lines:
+ s = line.strip()
+ if (s.startswith('β') and 'β¬' in s) or (s.startswith('β') and 'βΌ' in s) or (s.startswith('β') and 'β΄' in s):
+ parts = re.split(r'[ββ¬βββΌβ€ββ΄β]', s)[1:-1]
+ if len(parts) == num_cols:
+ for i, p in enumerate(parts):
+ col_widths[i] = max(col_widths[i], str_display_width(p))
+
+ # Next check content cells
+ for line in box_lines:
+ s = line.strip()
+ if s.startswith('β') and s.endswith('β'):
+ parts = s[1:-1].split('β')
+ if len(parts) == num_cols:
+ for i, p in enumerate(parts):
+ w = str_display_width(p.rstrip()) + 1
+ col_widths[i] = max(col_widths[i], w)
+
+ new_lines = []
+ for line in box_lines:
+ s = line.strip()
+ if s.startswith('β') and s.endswith('β'):
+ new_lines.append(indent_str + 'β' + 'β¬'.join('β' * w for w in col_widths) + 'β')
+ elif s.startswith('β') and s.endswith('β€'):
+ new_lines.append(indent_str + 'β' + 'βΌ'.join('β' * w for w in col_widths) + 'β€')
+ elif s.startswith('β') and s.endswith('β'):
+ new_lines.append(indent_str + 'β' + 'β΄'.join('β' * w for w in col_widths) + 'β')
+ elif s.startswith('β') and s.endswith('β'):
+ parts = s[1:-1].split('β')
+ if len(parts) == num_cols:
+ new_parts = []
+ for i, p in enumerate(parts):
+ trimmed = p.rstrip()
+ pad = col_widths[i] - str_display_width(trimmed)
+ if pad < 0:
+ pad = 0
+ new_parts.append(trimmed + (' ' * pad))
+ new_lines.append(indent_str + 'β' + 'β'.join(new_parts) + 'β')
+ else:
+ new_lines.append(line)
+ else:
+ new_lines.append(line)
+
+ return new_lines
+
+
+def process_file_content(content: str, fix: bool = False) -> Tuple[str, List[dict]]:
+ """
+ Parse and optionally align all box-drawing blocks in a markdown file.
+ Returns (updated_content, list_of_box_reports).
+ """
+ lines = content.split('\n')
+ reports = []
+ new_all_lines = []
+
+ i = 0
+ n = len(lines)
+ while i < n:
+ line = lines[i]
+ s = line.strip()
+
+ # Check if line is the start of a box
+ if is_box_top(line):
+ box_start_idx = i
+ box_lines = [line]
+ j = i + 1
+ is_valid_box = False
+
+ while j < n:
+ curr = lines[j]
+ box_lines.append(curr)
+ if is_box_bottom(curr):
+ is_valid_box = True
+ break
+ elif is_box_middle(curr) or is_box_top(curr):
+ j += 1
+ else:
+ # Non-box line encountered before bottom border
+ break
+
+ if is_valid_box:
+ box_end_idx = j
+ widths = [str_display_width(bl) for bl in box_lines]
+ is_misaligned = len(set(widths)) > 1
+
+ reports.append({
+ 'start_line': box_start_idx + 1,
+ 'end_line': box_end_idx + 1,
+ 'is_misaligned': is_misaligned,
+ 'widths': widths,
+ 'box_lines': box_lines
+ })
+
+ if fix and is_misaligned:
+ # Decide single vs multi-column
+ has_col_dividers = any(('β¬' in bl or 'βΌ' in bl or 'β΄' in bl or (bl.strip().startswith('β') and bl.strip()[1:-1].count('β') > 0)) for bl in box_lines)
+ if has_col_dividers:
+ aligned = align_multi_column_box(box_lines)
+ else:
+ aligned = align_single_column_box(box_lines)
+ new_all_lines.extend(aligned)
+ else:
+ new_all_lines.extend(box_lines)
+
+ i = box_end_idx + 1
+ continue
+
+ new_all_lines.append(line)
+ i += 1
+
+ updated_content = '\n'.join(new_all_lines)
+ return updated_content, reports
+
+
+def collect_target_files(paths: Optional[List[str]] = None) -> List[str]:
+ """Gather all candidate markdown files across the repository."""
+ if paths:
+ targets = []
+ for p in paths:
+ if os.path.isfile(p):
+ targets.append(p)
+ elif os.path.isdir(p):
+ for root, dirs, files in os.walk(p):
+ if any(skip in root for skip in ('.git', '_site', 'node_modules', '.gemini')):
+ continue
+ for f in files:
+ if f.endswith('.md'):
+ targets.append(os.path.join(root, f))
+ return sorted(list(set(targets)))
+
+ root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ targets = []
+ for root, dirs, files in os.walk(root_dir):
+ if any(skip in root for skip in ('.git', '_site', 'node_modules', '.gemini')):
+ continue
+ for f in files:
+ if f.endswith('.md'):
+ targets.append(os.path.join(root, f))
+ return sorted(targets)
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Audit and format Unicode ASCII box-drawing tables & cards.")
+ parser.add_argument('paths', nargs='*', help="File or directory paths to audit")
+ parser.add_argument('--fix', action='store_true', help="Automatically format and align misaligned boxes in place")
+ parser.add_argument('--check', action='store_true', help="Validate alignment and exit with code 1 on failure")
+ args = parser.parse_args()
+
+ files = collect_target_files(args.paths if args.paths else None)
+
+ total_boxes = 0
+ misaligned_boxes = 0
+ fixed_files = 0
+
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+ print(f"β π Unicode Monospace Box-Drawing Alignment Linter & Formatter β")
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+
+ for fpath in files:
+ rel_path = os.path.relpath(fpath, os.getcwd())
+ try:
+ with open(fpath, 'r', encoding='utf-8') as fp:
+ original = fp.read()
+ except Exception:
+ continue
+
+ if 'β' not in original:
+ continue
+
+ updated, reports = process_file_content(original, fix=args.fix)
+ file_has_misalignment = False
+
+ for r in reports:
+ total_boxes += 1
+ if r['is_misaligned']:
+ misaligned_boxes += 1
+ file_has_misalignment = True
+ w_set = set(r['widths'])
+ print(f" β [{rel_path}:{r['start_line']}-{r['end_line']}] Misaligned box widths: {w_set}")
+ if not args.fix:
+ for idx, line in enumerate(r['box_lines']):
+ w = str_display_width(line)
+ print(f" L{r['start_line'] + idx:3d} (w={w:2d}): {line}")
+
+ if args.fix and file_has_misalignment:
+ with open(fpath, 'w', encoding='utf-8') as fp:
+ fp.write(updated)
+ fixed_files += 1
+ print(f" β¨ Fixed and realigned boxes in {rel_path}")
+
+ print("\n------------------------------------------------------------------")
+ print(f"Summary: Audited {total_boxes} boxes across {len(files)} files.")
+ if misaligned_boxes == 0:
+ print("β
100% of ASCII/Unicode box-drawing tables and cards are perfectly aligned!")
+ sys.exit(0)
+ else:
+ if args.fix:
+ print(f"π Realigned {misaligned_boxes} boxes across {fixed_files} files.")
+ sys.exit(0)
+ else:
+ print(f"β οΈ Found {misaligned_boxes} misaligned box blocks.")
+ if args.check:
+ sys.exit(1)
+ sys.exit(0)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/audit_collapsible_elements.py b/scripts/audit_collapsible_elements.py
new file mode 100755
index 0000000..4d9b613
--- /dev/null
+++ b/scripts/audit_collapsible_elements.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python3
+"""
+scripts/audit_collapsible_elements.py
+=============================================================================
+Universal Collapsible Element & Accordion Invariant Audit Engine.
+
+Guarantees 100% compliance across repository Markdown files and compiled
+static site HTML/CSS/JS:
+1. Markdown Source Integrity:
+ - Validates that every has a matching .
+ - Validates that every has a matching .
+2. Compiled HTML Presentation Invariants:
+ - Zero raw/escaped <details> or <summary> text leakage.
+ - Zero invalid paragraph wrappers ().
+ - 100% of markdown details are rendered into semantic .
+ - Every .md-details has a corresponding .md-summary and .md-details-body.
+3. Design System & Audio Haptics Invariants:
+ - .md-details, .md-summary, .md-details-body rules present in CSS.
+ - Mica theme styling overrides present in CSS.
+ - Audio haptic click delegation in app.js binds to .md-summary.
+=============================================================================
+"""
+
+import sys
+import re
+import glob
+from pathlib import Path
+
+ROOT_DIR = Path(__file__).resolve().parent.parent
+SITE_INDEX = ROOT_DIR / "_site" / "index.html"
+SITE_CSS = ROOT_DIR / "_site" / "style.css"
+SITE_JS = ROOT_DIR / "_site" / "app.js"
+
+RED = "\033[0;31m"
+GREEN = "\033[0;32m"
+YELLOW = "\033[1;33m"
+CYAN = "\033[0;36m"
+NC = "\033[0m"
+
+def audit_markdown_sources() -> tuple[list[str], int]:
+ """Audits all repository markdown files for balanced details/summary tags."""
+ errors = []
+ md_files = sorted(glob.glob(str(ROOT_DIR / "**/*.md"), recursive=True))
+
+ total_details = 0
+ total_summaries = 0
+
+ for f_path_str in md_files:
+ if any(skip in f_path_str for skip in ["_site", "node_modules", ".agents", "specs/"]):
+ continue
+ p = Path(f_path_str)
+ try:
+ content = p.read_text(encoding="utf-8", errors="ignore")
+ except Exception as e:
+ errors.append(f"Could not read {p}: {e}")
+ continue
+
+ open_details = len(re.findall(r']*)?>', content, re.IGNORECASE))
+ close_details = len(re.findall(r' ', content, re.IGNORECASE))
+ open_summaries = len(re.findall(r']*)?>', content, re.IGNORECASE))
+ close_summaries = len(re.findall(r' ', content, re.IGNORECASE))
+
+ if open_details != close_details:
+ errors.append(f"{p.relative_to(ROOT_DIR)}: Mismatched ({open_details}) vs ({close_details})")
+ if open_summaries != close_summaries:
+ errors.append(f"{p.relative_to(ROOT_DIR)}: Mismatched ({open_summaries}) vs ({close_summaries})")
+ if open_details != open_summaries:
+ errors.append(f"{p.relative_to(ROOT_DIR)}: count ({open_details}) does not match count ({open_summaries})")
+
+ total_details += open_details
+ total_summaries += open_summaries
+
+ return errors, total_details
+
+def audit_compiled_html() -> tuple[list[str], int]:
+ """Audits _site/index.html for raw HTML leakage and structural integrity."""
+ errors = []
+ if not SITE_INDEX.exists():
+ return [f"Compiled index.html not found at {SITE_INDEX}. Run 'make docs-build' first."], 0
+
+ html_content = SITE_INDEX.read_text(encoding="utf-8", errors="ignore")
+
+ # 1. Check for raw escaped entity leakage
+ for tag in ["<details", "<summary", "</details", "</summary"]:
+ if tag in html_content:
+ count = html_content.count(tag)
+ errors.append(f"Found {count} raw escaped '{tag}' tag(s) in compiled index.html! Content is showing unrendered.")
+
+ # 2. Check for invalid paragraph wrapping around details
+ if re.search(r'\s* is wrapped inside a paragraph!")
+ if re.search(r'
\s*
', html_content):
+ errors.append("Invalid markup: is closed by a trailing
paragraph!")
+
+ # 3. Check for rendered .md-details, .md-summary, and .md-details-body
+ md_details_count = html_content.count('class="md-details"')
+ md_summary_count = html_content.count('class="md-summary"')
+ md_body_count = html_content.count('class="md-details-body"')
+
+ if md_details_count > 0:
+ if md_details_count != md_summary_count:
+ errors.append(f"Discrepancy: {md_details_count} .md-details elements but {md_summary_count} .md-summary elements.")
+ if md_details_count != md_body_count:
+ errors.append(f"Discrepancy: {md_details_count} .md-details elements but {md_body_count} .md-details-body wrappers.")
+
+ return errors, md_details_count
+
+def audit_styling_and_haptics() -> list[str]:
+ """Audits style.css and app.js for .md-details design tokens and audio bindings."""
+ errors = []
+ if not SITE_CSS.exists():
+ errors.append(f"Compiled style.css not found at {SITE_CSS}.")
+ else:
+ css = SITE_CSS.read_text(encoding="utf-8")
+ if ".md-details" not in css:
+ errors.append("Missing .md-details styling rule in style.css.")
+ if ".md-summary" not in css:
+ errors.append("Missing .md-summary styling rule in style.css.")
+ if ".md-details-body" not in css:
+ errors.append("Missing .md-details-body styling rule in style.css.")
+ if '[data-theme="mica"] .md-summary' not in css and '[data-theme="mica"] .md-details' not in css:
+ errors.append("Missing Mica theme override for .md-details / .md-summary in style.css.")
+
+ if not SITE_JS.exists():
+ errors.append(f"Compiled app.js not found at {SITE_JS}.")
+ else:
+ js = SITE_JS.read_text(encoding="utf-8")
+ if ".md-details" not in js:
+ errors.append("Missing .md-details selector in app.js Expand/Collapse All handlers.")
+
+ return errors
+
+def main():
+ source_only = "--source-only" in sys.argv
+ print(f"{CYAN}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{NC}")
+ print(f"{CYAN}β π Auditing Collapsible Elements & Raw HTML Block Invariants β{NC}")
+ print(f"{CYAN}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ{NC}")
+
+ all_errors = []
+
+ # 1. Source Markdown Audit
+ print(" β Auditing repository Markdown sources for tag balance...")
+ md_errors, total_md_details = audit_markdown_sources()
+ if md_errors:
+ for err in md_errors:
+ print(f" {RED}β {err}{NC}")
+ all_errors.extend(md_errors)
+ else:
+ print(f" {GREEN}β
Validated {total_md_details} balanced / pairs across all Markdown files.{NC}")
+
+ if not source_only:
+ # 2. Compiled HTML Audit
+ print(" β Auditing compiled _site/index.html for raw HTML leakage...")
+ html_errors, rendered_count = audit_compiled_html()
+ if html_errors:
+ for err in html_errors:
+ print(f" {RED}β {err}{NC}")
+ all_errors.extend(html_errors)
+ else:
+ print(f" {GREEN}β
Validated {rendered_count} semantic elements with ZERO raw leakage.{NC}")
+
+ # 3. CSS & Audio Haptics Invariant Audit
+ print(" β Auditing CSS design tokens and JS bindings...")
+ asset_errors = audit_styling_and_haptics()
+ if asset_errors:
+ for err in asset_errors:
+ print(f" {RED}β {err}{NC}")
+ all_errors.extend(asset_errors)
+ else:
+ print(f" {GREEN}β
CSS design tokens and JS bindings verified.{NC}")
+
+ print("β" * 66)
+ if all_errors:
+ print(f"{RED}β FAILED: Found {len(all_errors)} collapsible element invariant violations!{NC}")
+ sys.exit(1)
+ else:
+ print(f"{GREEN}π 100% COLLAPSIBLE ELEMENT INVARIANTS PASSED DETERMINISTICALLY!{NC}")
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/audit_links_and_anchors.py b/scripts/audit_links_and_anchors.py
new file mode 100755
index 0000000..8264863
--- /dev/null
+++ b/scripts/audit_links_and_anchors.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+"""
+scripts/audit_links_and_anchors.py
+==============================================================================
+Gate 15: Universal Hyperlink Integrity & Local Path Leak Prevention Linter.
+Validates:
+ 1. Zero local file paths (file://, /Users/) across all Markdown source files.
+ 2. Zero local file paths in compiled static documentation (index.html).
+ 3. Zero raw relative file links (.md, .py, ../path/) leaking in compiled index.html.
+ 4. Zero external GitHub repository jumps (github.com/vadde/DesignPatterns/blob or /tree)
+ for content that is already compiled into the documentation portal.
+ 5. 100% resolution of in-page fragment anchors (href="#..."):
+ Every single internal anchor must map to a valid element id on the page.
+==============================================================================
+"""
+
+import os
+import re
+import sys
+import glob
+from pathlib import Path
+
+ROOT_DIR = Path(__file__).resolve().parent.parent
+DOCS_HTML = ROOT_DIR / "docs" / "site" / "index.html"
+SITE_HTML = ROOT_DIR / "_site" / "index.html"
+
+CYAN = "\033[0;36m"
+GREEN = "\033[0;32m"
+RED = "\033[0;31m"
+YELLOW = "\033[1;33m"
+RESET = "\033[0m"
+
+def audit_source_markdown() -> bool:
+ print(f"{CYAN}β 1. Auditing Markdown sources for local filesystem paths & link typos...{RESET}")
+ violations = []
+
+ for md_path in sorted(ROOT_DIR.glob("**/*.md")):
+ p_str = str(md_path)
+ if any(x in p_str for x in [".agents", "node_modules", "specs", "docs/site", "_site", ".git"]):
+ continue
+
+ with open(md_path, "r", encoding="utf-8", errors="ignore") as f:
+ content = f.read()
+
+ if "file://" in content or "/Users/" in content:
+ violations.append((md_path.relative_to(ROOT_DIR), "Contains 'file://' or '/Users/' local path"))
+
+ if violations:
+ for f, err in violations:
+ print(f"{RED}β {f}: {err}{RESET}")
+ return False
+
+ print(f" {GREEN}β
100% of Markdown source files are free of local paths.{RESET}")
+ return True
+
+def audit_compiled_html(html_path: Path) -> bool:
+ print(f"{CYAN}β 2. Auditing {html_path.relative_to(ROOT_DIR)} for hyperlink integrity & SPA containment...{RESET}")
+ if not html_path.exists():
+ print(f"{RED}β File not found: {html_path}{RESET}")
+ return False
+
+ with open(html_path, "r", encoding="utf-8") as f:
+ html = f.read()
+
+ forbidden_terms = [
+ ("file://", "Local file scheme in href"),
+ ("/Users/", "Local user directory in href"),
+ ]
+
+ leak_found = False
+ for term, desc in forbidden_terms:
+ count = html.count(term)
+ if count > 0:
+ print(f"{RED}β Fatal: Found {count} occurrences of '{term}' ({desc}) in {html_path.name}{RESET}")
+ leak_found = True
+
+ if leak_found:
+ return False
+
+ hrefs = re.findall(r'href=["\']([^"\']+)["\']', html)
+ print(f" {CYAN}Auditing {len(hrefs)} hyperlinks in {html_path.name}...{RESET}")
+
+ unresolved_md = []
+ unresolved_py = []
+ forbidden_gh_jumps = []
+
+ for h in hrefs:
+ # Check raw .md links
+ if re.search(r'\.md(?:#[^\s"\']*)?$', h):
+ unresolved_md.append(h)
+ # Check raw .py links
+ elif re.search(r'\.py(?:#[^\s"\']*)?$', h):
+ unresolved_py.append(h)
+ # Check GitHub repo jumps into internal codebase files
+ elif "github.com/vadde/DesignPatterns" in h and any(k in h for k in ["/blob/", "/tree/"]):
+ forbidden_gh_jumps.append(h)
+
+ errors = False
+ if unresolved_md:
+ print(f"{RED}β Found {len(unresolved_md)} raw .md links that break in production SPA:{RESET}")
+ for l in unresolved_md[:5]: print(f" {l}")
+ errors = True
+
+ if unresolved_py:
+ print(f"{RED}β Found {len(unresolved_py)} raw .py links:{RESET}")
+ for l in unresolved_py[:5]: print(f" {l}")
+ errors = True
+
+ if forbidden_gh_jumps:
+ print(f"{RED}β Found {len(forbidden_gh_jumps)} external GitHub repo jumps for internal files:{RESET}")
+ for l in forbidden_gh_jumps[:5]: print(f" {l}")
+ errors = True
+
+ if errors:
+ return False
+
+ print(f" {GREEN}β
Zero raw .md, raw .py, or internal GitHub jumps.{RESET}")
+
+ # Validate all internal fragment anchors (href="#...")
+ all_ids = set(re.findall(r'id=["\']([^"\']+)["\']', html))
+ internal_anchors = re.findall(r'href=["\']#([^"\']+)["\']', html)
+
+ missing_targets = set()
+ for a in internal_anchors:
+ if not a or a == "top": continue
+ if a not in all_ids:
+ missing_targets.add(a)
+
+ if missing_targets:
+ print(f"{RED}β Found {len(missing_targets)} broken fragment anchors that point to non-existent IDs:{RESET}")
+ for a in sorted(missing_targets)[:10]:
+ print(f" #{a}")
+ return False
+
+ print(f" {GREEN}β
100% of internal anchors ({len(internal_anchors)} references) resolve to valid element IDs.{RESET}")
+ return True
+
+def main():
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+ print("β π Universal Hyperlink Integrity & Local Path Prevention Linterβ")
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+
+ source_ok = audit_source_markdown()
+ if not source_ok:
+ sys.exit(1)
+
+ targets = [f for f in [SITE_HTML] if f.exists()]
+ if not targets:
+ print(f"{RED}β _site/index.html not found. Run 'make docs-build' first.{RESET}")
+ sys.exit(1)
+
+ html_ok = True
+ for t in targets:
+ if not audit_compiled_html(t):
+ html_ok = False
+
+ if source_ok and html_ok:
+ print()
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+ print(f"{GREEN}π 100% HYPERLINK INTEGRITY & SPA CONTAINMENT INVARIANTS PASSED!{RESET}")
+ sys.exit(0)
+ else:
+ print()
+ print(f"{RED}β Hyperlink integrity or SPA containment invariants violated.{RESET}")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/audit_monospace_badging.py b/scripts/audit_monospace_badging.py
new file mode 100755
index 0000000..259c79b
--- /dev/null
+++ b/scripts/audit_monospace_badging.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+"""
+scripts/audit_monospace_badging.py
+==============================================================================
+Gate 14: Monospace Semantic Badging & Implementation Tag Linter.
+Validates:
+ 1. 100% elimination of meaningless 'β‘ TEXT Implementation' and 'β‘ NONE Implementation'.
+ 2. Integrity of content-aware semantic badges in compiled index.html:
+ - β‘ Python 3.14 Implementation (.dna-label-code)
+ - Framework Badges (.dna-label-django, .dna-label-fastapi, .dna-label-sqlalchemy, .dna-label-celery)
+ - π Monospace Reference Matrix (.dna-label-matrix)
+ - π Master Architecture / Blueprint (.dna-label-blueprint)
+ - π Technical Specification & Proof (.dna-label-spec)
+==============================================================================
+"""
+
+import re
+import sys
+from pathlib import Path
+
+ROOT_DIR = Path(__file__).resolve().parent.parent
+SITE_HTML = ROOT_DIR / "_site" / "index.html"
+
+CYAN = "\033[0;36m"
+GREEN = "\033[0;32m"
+RED = "\033[0;31m"
+RESET = "\033[0m"
+
+def audit_file(html_path: Path) -> bool:
+ print(f"{CYAN}β Auditing {html_path.relative_to(ROOT_DIR)} for semantic badging...{RESET}")
+ if not html_path.exists():
+ print(f"{RED}β File not found: {html_path}{RESET}")
+ return False
+
+ with open(html_path, "r", encoding="utf-8") as f:
+ content = f.read()
+
+ # 1. Elimination of mislabeled badges
+ if "β‘ TEXT Implementation" in content:
+ print(f"{RED}β Fatal: Found 'β‘ TEXT Implementation' in {html_path.name}{RESET}")
+ return False
+ if "β‘ NONE Implementation" in content:
+ print(f"{RED}β Fatal: Found 'β‘ NONE Implementation' in {html_path.name}{RESET}")
+ return False
+
+ print(f" {GREEN}β
Zero occurrences of 'β‘ TEXT Implementation' or 'β‘ NONE Implementation'.{RESET}")
+
+ # 2. Semantic Badges Presence & Distribution
+ badge_matches = re.findall(r'([^<]+) ', content)
+ if not badge_matches:
+ print(f"{RED}β Fatal: No .dna-label elements found in {html_path.name}{RESET}")
+ return False
+
+ badge_types = {}
+ for cls, _ in badge_matches:
+ for c in cls.split():
+ badge_types[c] = badge_types.get(c, 0) + 1
+
+ expected_classes = [
+ "dna-label-code",
+ "dna-label-blueprint",
+ "dna-label-django",
+ "dna-label-fastapi",
+ "dna-label-sqlalchemy"
+ ]
+ for rc in expected_classes:
+ if rc not in badge_types or badge_types[rc] == 0:
+ print(f"{RED}β Fatal: Missing semantic badge class '{rc}' in {html_path.name}{RESET}")
+ return False
+
+ print(f" {GREEN}β
Validated semantic badge diversity ({len(badge_matches)} blocks classified):{RESET}")
+ for rc, count in sorted(badge_types.items()):
+ print(f" β’ {rc}: {count} blocks")
+
+ return True
+
+def main():
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+ print("β π·οΈ Monospace Semantic Badging & Implementation Linter β")
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+
+ if not SITE_HTML.exists():
+ print(f"{RED}β _site/index.html not found. Run 'make docs-build' first.{RESET}")
+ sys.exit(1)
+
+ if audit_file(SITE_HTML):
+ print()
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+ print(f"{GREEN}π 100% MONOSPACE BADGING INVARIANTS PASSED!{RESET}")
+ sys.exit(0)
+ else:
+ print()
+ print(f"{RED}β Monospace badging invariants violated.{RESET}")
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/build-docs.py b/scripts/build-docs.py
new file mode 100755
index 0000000..4250236
--- /dev/null
+++ b/scripts/build-docs.py
@@ -0,0 +1,725 @@
+#!/usr/bin/env python3
+"""
+==============================================================================
+build-docs.py β Zero-Dependency Design Patterns Living Documentation Compiler
+Compiles 28 chapters, 5 architectural tiers, 38 Python 3.14 implementations,
+and 84 Mermaid diagrams into a futuristic Year 2500 Command Deck static site.
+Features full Markdown-to-HTML rendering, interactive code workbenches,
+fullscreen theater modal, and deep search indexing.
+==============================================================================
+"""
+
+import os
+import re
+import sys
+import json
+import html
+import shutil
+import urllib.parse
+from pathlib import Path
+
+ROOT_DIR = Path(__file__).resolve().parent.parent
+DOCS_SITE_DIR = ROOT_DIR / "docs" / "site"
+SITE_DIR = ROOT_DIR / "_site"
+CATALOG_DIR = SITE_DIR / "catalog"
+
+TIERS = {
+ "Foundations": {
+ "icon": "ποΈ",
+ "tagline": "First Principles & Foundations",
+ "desc": "Object-oriented first principles, SOLID, Composition vs Inheritance, and UML primer.",
+ "patterns": ["00 - Foundations"],
+ },
+ "Creational": {
+ "icon": "π¨",
+ "tagline": "Creational Patterns",
+ "desc": "How objects are created β controlling instantiation to keep systems decoupled and flexible.",
+ "patterns": [
+ "01 - Singleton (Creational)",
+ "02 - Factory Method (Creational)",
+ "03 - Abstract Factory (Creational)",
+ "04 - Builder (Creational)",
+ "05 - Prototype (Creational)",
+ ],
+ },
+ "Structural": {
+ "icon": "π§±",
+ "tagline": "Structural Patterns",
+ "desc": "How objects are composed β assembling larger, resilient structures from individual parts.",
+ "patterns": [
+ "06 - Adapter (Structural)",
+ "07 - Bridge (Structural)",
+ "08 - Composite (Structural)",
+ "09 - Decorator (Structural)",
+ "10 - Facade (Structural)",
+ "11 - Flyweight (Structural)",
+ "12 - Proxy (Structural)",
+ ],
+ },
+ "Behavioral": {
+ "icon": "π¬",
+ "tagline": "Behavioral Patterns",
+ "desc": "How objects communicate β defining interaction protocols and responsibility distribution.",
+ "patterns": [
+ "13 - Chain of Responsibility (Behavioral)",
+ "14 - Command (Behavioral)",
+ "15 - Iterator (Behavioral)",
+ "16 - Mediator (Behavioral)",
+ "17 - Memento (Behavioral)",
+ "18 - Observer (Behavioral)",
+ "19 - State (Behavioral)",
+ "20 - Strategy (Behavioral)",
+ "21 - Template Method (Behavioral)",
+ "22 - Visitor (Behavioral)",
+ ],
+ },
+ "Architectural": {
+ "icon": "π",
+ "tagline": "Architectural & Advanced",
+ "desc": "Beyond GoF β patterns that shape enterprise applications, persistence, and state at scale.",
+ "patterns": [
+ "23 - Repository Pattern (Architectural)",
+ "24 - Unit of Work (Architectural)",
+ "25 - Dependency Injection (Architectural)",
+ "26 - Event Sourcing & CQRS (Architectural)",
+ ],
+ },
+ "Capstone": {
+ "icon": "π―",
+ "tagline": "Capstone & Wild Sightings",
+ "desc": "Decision matrix, anti-patterns, real-world framework sightings, and interview playbook.",
+ "patterns": ["27 - Patterns in the Wild (Capstone)"],
+ },
+}
+
+def get_tier_for_folder(folder_name: str) -> str:
+ for tier, data in TIERS.items():
+ if folder_name in data["patterns"]:
+ return tier
+ return "Architectural"
+
+def slugify(text: str) -> str:
+ """Generate a clean URL/anchor slug from a title or folder name."""
+ clean = re.sub(r'[\(\)]', '', text)
+ clean = re.sub(r'[^\w\s-]', '', clean).strip().lower()
+ return re.sub(r'[-\s]+', '-', clean)
+
+def get_chapter_slug(folder_name: str) -> str:
+ """e.g. '01 - Singleton (Creational)' -> 'chapter-01-singleton'"""
+ m = re.match(r'^(\d{2})\s*-\s*([^(]+)', folder_name)
+ if m:
+ num = m.group(1)
+ name = slugify(m.group(2).strip())
+ return f"chapter-{num}-{name}"
+ return f"chapter-{slugify(folder_name)}"
+
+_DIAGRAM_COUNTER = 0
+
+def sanitize_mermaid(content: str) -> str:
+ """
+ Sanitize Mermaid syntax:
+ - Escapes unescaped < and > in node labels as < and >
+ - Fixes potential label or bracket syntax outliers
+ """
+ # Replace raw angle brackets inside square bracket labels
+ def repl_bracket(m):
+ inner = m.group(1)
+ # Preserve and
+ inner_clean = re.sub(r' ', '__BR_PLACEHOLDER__', inner)
+ inner_clean = inner_clean.replace('<', '<').replace('>', '>')
+ inner_clean = inner_clean.replace('__BR_PLACEHOLDER__', ' ')
+ return f'[{inner_clean}]'
+
+ content = re.sub(r'\[([^\]\n]+)\]', repl_bracket, content)
+
+ # Enclose unquoted edge labels containing () or [] in quotes
+ def repl_edge(m):
+ arr = m.group(1)
+ lbl = m.group(2).strip()
+ if (lbl.startswith('"') and lbl.endswith('"')) or (lbl.startswith("'") and lbl.endswith("'")):
+ return m.group(0)
+ clean = lbl.replace('"', "'")
+ return f'{arr}|"{clean}"|'
+ content = re.sub(r'(-->|-.->|==>)\|([^|\n]*[\(\)\[\]][^|\n]*)\|', repl_edge, content)
+
+ return content
+
+def classify_code_block(lang: str, code: str) -> tuple[str, str, str]:
+ """Classify a code block into a badge title, CSS class, and language."""
+ raw_lang = (lang or "").strip().lower()
+ if raw_lang in ("python", "py", "python3"):
+ return "β‘ Python 3.14 Implementation", "dna-label-code", "python"
+ elif raw_lang in ("json",):
+ return "β‘ JSON Schema & Contract", "dna-label-spec", "json"
+ elif raw_lang in ("bash", "sh", "shell", "zsh"):
+ return "β‘ Shell Command / Script", "dna-label-code", "bash"
+ elif raw_lang in ("sql",):
+ return "β‘ SQL Schema & Query", "dna-label-code", "sql"
+ elif raw_lang in ("tree", "hierarchy"):
+ return "π³ Structural Hierarchy & Topology", "dna-label-tree", "plaintext"
+ elif raw_lang in ("matrix", "table", "ascii-table"):
+ return "π Monospace Reference Matrix", "dna-label-matrix", "plaintext"
+
+ # Heuristic detection
+ code_stripped = code.strip()
+ if any(box in code_stripped for box in ["β", "β", "β", "+---", "|---"]):
+ return "π Monospace Reference Matrix", "dna-label-matrix", "plaintext"
+ if any(c in code_stripped for c in ["/ \\", "/ \\", "βββ", "βββ"]):
+ return "π³ Structural Hierarchy & Topology", "dna-label-tree", "plaintext"
+ if "def " in code_stripped or "class " in code_stripped or "import " in code_stripped:
+ return "β‘ Python 3.14 Implementation", "dna-label-code", "python"
+
+ return "π Technical Blueprint & Specification", "dna-label-spec", "plaintext"
+
+def detect_diagram_tag(code: str) -> tuple[str, str]:
+ """Detect dynamic semantic diagram tag and caption from mermaid source code."""
+ cleaned = code.strip()
+ first_line = cleaned.splitlines()[0].strip().lower() if cleaned else ""
+ if first_line.startswith("mindmap"):
+ return ("π§ Conceptual Mindmap & Taxonomy", "Taxonomic pattern relationships & mental models")
+ elif first_line.startswith("classdiagram"):
+ return ("π Class Structure & UML Blueprint", "Object-oriented class hierarchy & relationship contracts")
+ elif first_line.startswith("sequencediagram"):
+ return ("β‘ Runtime Interaction & Sequence Flow", "Temporal message passing & execution lifecycle")
+ elif first_line.startswith("statediagram"):
+ return ("βοΈ State Machine & Lifecycle", "State transitions, triggers & invariant guards")
+ elif first_line.startswith("erdiagram"):
+ return ("ποΈ Entity Relationship Diagram", "Schema entity models & relational cardinalities")
+ elif "subgraph" in cleaned.lower():
+ return ("ποΈ System Architecture & Subgraphs", "Component topology & systemic boundary constraints")
+ else:
+ return ("π Architectural Decision & Flow Logic", "Decision branching & algorithmic state transitions")
+
+def render_markdown(text: str, current_folder: str = "") -> str:
+ """
+ Converts markdown content into semantic, accessible HTML with:
+ - Unique Mermaid diagrams wrapped in theater-enabled workbenches
+ - Table touch wrappers with min-width
+ - Semantic with
+ - Relative link conversion to in-page hashes
+ - Syntax-highlighted code blocks with copy action
+ """
+ global _DIAGRAM_COUNTER
+
+ # 1. Protect code blocks and mermaid diagrams
+ code_blocks = []
+ mermaid_blocks = []
+
+ def save_mermaid(m):
+ global _DIAGRAM_COUNTER
+ _DIAGRAM_COUNTER += 1
+ raw_code = m.group(1).strip()
+ sanitized = sanitize_mermaid(raw_code)
+ diag_id = f"mermaid-diagram-{_DIAGRAM_COUNTER}"
+ placeholder = f"___MERMAID_PLACEHOLDER_{len(mermaid_blocks)}___"
+ mermaid_blocks.append((diag_id, sanitized))
+ return placeholder
+
+ text = re.sub(r'```mermaid\s*\n(.*?)\n```', save_mermaid, text, flags=re.DOTALL)
+
+ def save_code(m):
+ lang = m.group(1).strip() if m.group(1) else ""
+ code = m.group(2)
+ badge_title, badge_cls, prism_lang = classify_code_block(lang, code)
+ escaped_code = html.escape(code.rstrip())
+ placeholder = f"___CODE_PLACEHOLDER_{len(code_blocks)}___"
+
+ rendered = (
+ f'\n'
+ f' \n'
+ f'
{escaped_code}\n'
+ f'
'
+ )
+ code_blocks.append(rendered)
+ return placeholder
+
+ text = re.sub(r'```([a-zA-Z0-9_-]*)\s*\n(.*?)\n```', save_code, text, flags=re.DOTALL)
+
+ # 2. Convert and to semantic .md-details and .md-summary
+ def repl_details(m):
+ inner = m.group(1).strip()
+ summary_text = "Answers"
+ sum_match = re.search(r'(.*?) ', inner, flags=re.DOTALL | re.IGNORECASE)
+ if sum_match:
+ summary_text = sum_match.group(1).strip()
+ body_text = inner[sum_match.end():].strip()
+ else:
+ body_text = inner
+
+ # Recursively render body
+ body_html = render_markdown(body_text, current_folder)
+ return (
+ f'\n'
+ f' {summary_text} \n'
+ f' \n{body_html}\n
\n'
+ f' '
+ )
+
+ text = re.sub(r']*)?>(.*?) ', repl_details, text, flags=re.DOTALL | re.IGNORECASE)
+
+ # 3. Tables
+ def repl_table(m):
+ table_str = m.group(0).strip()
+ lines = [l.strip() for l in table_str.splitlines() if l.strip()]
+ if len(lines) < 2:
+ return table_str
+
+ header_cols = [c.strip() for c in lines[0].split('|')[1:-1]]
+ # line 1 is separator |---|---|
+ body_rows = lines[2:]
+
+ out = ['']
+ out.append(' ')
+ for h in header_cols:
+ out.append(f' {inline_markdown(h)} ')
+ out.append(' ')
+ out.append(' ')
+ for r in body_rows:
+ cols = [c.strip() for c in r.split('|')[1:-1]]
+ out.append(' ')
+ for c in cols:
+ out.append(f' {inline_markdown(c)} ')
+ out.append(' ')
+ out.append('
')
+ return '\n'.join(out)
+
+ table_pattern = re.compile(r'((?:^[ \t]*\|[^\n]+\|[ \t]*\n)+)', re.MULTILINE)
+ text = table_pattern.sub(repl_table, text)
+
+ # 4. Headers (##, ###, ####)
+ def repl_h4(m):
+ title = m.group(1).strip()
+ return f'{inline_markdown(title)} '
+ def repl_h3(m):
+ title = m.group(1).strip()
+ hid = slugify(title)
+ return f'{inline_markdown(title)} '
+ def repl_h2(m):
+ title = m.group(1).strip()
+ hid = slugify(title)
+ return f'{inline_markdown(title)} '
+ def repl_h1(m):
+ title = m.group(1).strip()
+ hid = slugify(title)
+ return f'{inline_markdown(title)} '
+
+ text = re.sub(r'^####\s+(.+)$', repl_h4, text, flags=re.MULTILINE)
+ text = re.sub(r'^###\s+(.+)$', repl_h3, text, flags=re.MULTILINE)
+ text = re.sub(r'^##\s+(.+)$', repl_h2, text, flags=re.MULTILINE)
+ text = re.sub(r'^#\s+(.+)$', repl_h1, text, flags=re.MULTILINE)
+
+ # 5. Blockquotes (> ...)
+ def repl_quote(m):
+ quote_text = m.group(1).strip()
+ lines = [re.sub(r'^[ \t]*>[ \t]?', '', l) for l in quote_text.splitlines()]
+ inner_rendered = inline_markdown('\n'.join(lines))
+ return f'{inner_rendered} '
+
+ text = re.sub(r'((?:^[ \t]*>[^\n]*\n?)+)', repl_quote, text, flags=re.MULTILINE)
+
+ # 6. Unordered lists
+ def repl_ul(m):
+ items = m.group(0).strip().splitlines()
+ lis = []
+ for it in items:
+ it_clean = re.sub(r'^[ \t]*[-*]\s+', '', it)
+ lis.append(f' {inline_markdown(it_clean)} ')
+ return '\n' + '\n'.join(lis) + '\n '
+
+ text = re.sub(r'((?:^[ \t]*[-*]\s+[^\n]+\n?)+)', repl_ul, text, flags=re.MULTILINE)
+
+ # 7. Ordered lists
+ def repl_ol(m):
+ items = m.group(0).strip().splitlines()
+ lis = []
+ for it in items:
+ it_clean = re.sub(r'^[ \t]*\d+\.\s+', '', it)
+ lis.append(f' {inline_markdown(it_clean)} ')
+ return '\n' + '\n'.join(lis) + '\n '
+
+ text = re.sub(r'((?:^[ \t]*\d+\.\s+[^\n]+\n?)+)', repl_ol, text, flags=re.MULTILINE)
+
+ # 8. Horizontal rules
+ text = re.sub(r'^[ \t]*---[ \t]*$', ' ', text, flags=re.MULTILINE)
+
+ # 9. Paragraphs
+ paragraphs = []
+ for chunk in text.split('\n\n'):
+ chunk = chunk.strip()
+ if not chunk:
+ continue
+ if any(chunk.startswith(prefix) for prefix in [
+ '{inline_markdown(chunk)}')
+ text = '\n\n'.join(paragraphs)
+
+ # 10. Restore code blocks
+ for i, cb in enumerate(code_blocks):
+ text = text.replace(f"___CODE_PLACEHOLDER_{i}___", cb)
+
+ # 11. Restore mermaid blocks into Canvas Containers (1:1 DSA standard)
+ for i, (diag_id, code) in enumerate(mermaid_blocks):
+ escaped_mermaid = html.escape(code.strip())
+ tag_title, caption_text = detect_diagram_tag(code)
+ wb = (
+ f'\n'
+ f' \n'
+ f'
\n'
+ f'
\n'
+ f'
\n{escaped_mermaid}\n \n'
+ f'
\n'
+ f'
\n'
+ f'
{caption_text}
\n'
+ f'
'
+ )
+ text = text.replace(f"___MERMAID_PLACEHOLDER_{i}___", wb)
+
+ return text
+
+def inline_markdown(text: str) -> str:
+ """Format inline markdown: bold, italic, code, links, strikethrough."""
+ # Inline code
+ text = re.sub(r'`([^`]+)`', r'\1', text)
+ # Bold italic
+ text = re.sub(r'\*\*\*([^*]+)\*\*\*', r'\1 ', text)
+ # Bold
+ text = re.sub(r'\*\*([^*]+)\*\*', r'\1 ', text)
+ # Italic
+ text = re.sub(r'\*([^*]+)\*', r'\1 ', text)
+ text = re.sub(r'_([^_]+)_', r'\1 ', text)
+ # Strikethrough
+ text = re.sub(r'~~([^~]+)~~', r'\1', text)
+
+ # Links: [text](href)
+ def repl_link(m):
+ ltxt = m.group(1)
+ lhref = m.group(2).strip()
+
+ # Check if internal chapter directory link e.g. ./01%20-%20Singleton%20%28Creational%29/
+ # or ./24%20-%20Unit%20of%20Work%20%28Architectural%29/
+ unquoted = urllib.parse.unquote(lhref)
+ # Extract folder match
+ dir_match = re.search(r'(\d{2})\s*-\s*([^(/\\]+)', unquoted)
+ if dir_match:
+ num = dir_match.group(1)
+ name = slugify(dir_match.group(2).strip())
+ return f'{ltxt} '
+
+ if lhref.startswith('http://') or lhref.startswith('https://'):
+ return f'{ltxt} '
+ return f'{ltxt} '
+
+ text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', repl_link, text)
+ return text
+
+def parse_python_example(py_path: Path) -> dict:
+ """Extract metadata, scenario, key insight, and code from a Python example file."""
+ code_text = py_path.read_text(encoding="utf-8", errors="ignore")
+ lines = code_text.splitlines()
+
+ title = py_path.stem.replace("example_", "").replace("_", " ").title()
+ framework = "Pure Python"
+ scenario = ""
+ key_insight = ""
+
+ # Parse header docstring if present
+ doc_match = re.search(r'^\s*"""(.*?)"""', code_text, flags=re.DOTALL)
+ if doc_match:
+ doc = doc_match.group(1)
+ # Extract Example: Title
+ m_title = re.search(r'Example:\s*([^\n]+)', doc, re.IGNORECASE)
+ if m_title:
+ title = m_title.group(1).strip()
+ # Extract Framework:
+ m_fw = re.search(r'Framework:\s*([^\n]+)', doc, re.IGNORECASE)
+ if m_fw:
+ framework = m_fw.group(1).strip()
+ # Extract Real-World Scenario
+ m_scen = re.search(r'REAL-WORLD SCENARIO:\s*-+\s*([^\n]+(?:\n[^\n]+)*?)(?=\n[A-Z\s-]+:|\Z)', doc, re.IGNORECASE)
+ if m_scen:
+ scenario = " ".join(l.strip() for l in m_scen.group(1).strip().splitlines() if l.strip())
+ # Extract Key Insight
+ m_ins = re.search(r'KEY INSIGHT:\s*-+\s*([^\n]+(?:\n[^\n]+)*?)(?=\n[A-Z\s-]+:|\Z)', doc, re.IGNORECASE)
+ if m_ins:
+ key_insight = " ".join(l.strip() for l in m_ins.group(1).strip().splitlines() if l.strip())
+
+ line_count = len(lines)
+ escaped_code = html.escape(code_text.rstrip())
+
+ # Framework badge styling
+ fw_lower = framework.lower()
+ badge_cls = "dna-label-code"
+ if "django" in fw_lower:
+ badge_cls = "dna-label-django"
+ elif "fastapi" in fw_lower:
+ badge_cls = "dna-label-fastapi"
+ elif "sqlalchemy" in fw_lower:
+ badge_cls = "dna-label-sqlalchemy"
+ elif "celery" in fw_lower:
+ badge_cls = "dna-label-celery"
+
+ return {
+ "filename": py_path.name,
+ "title": title,
+ "framework": framework,
+ "scenario": scenario,
+ "key_insight": key_insight,
+ "line_count": line_count,
+ "escaped_code": escaped_code,
+ "badge_cls": badge_cls,
+ }
+
+def main():
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+ print("β π Compiling Design Patterns Living Documentation Portal β")
+ print("ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ")
+
+ # Discover all numbered chapter folders
+ folders = sorted([
+ d for d in ROOT_DIR.iterdir()
+ if d.is_dir() and re.match(r'^\d{2}\s*-', d.name)
+ ], key=lambda d: d.name)
+
+ print(f"β Discovered {len(folders)} pattern chapter directories.")
+
+ SITE_DIR.mkdir(parents=True, exist_ok=True)
+ CATALOG_DIR.mkdir(parents=True, exist_ok=True)
+
+ manifest_patterns = []
+ manifest_examples = []
+ chapters_html = []
+ sidebar_items_html = []
+
+ total_examples = 0
+ total_diagrams = 0
+
+ for idx, f_path in enumerate(folders):
+ folder_name = f_path.name
+ slug = get_chapter_slug(folder_name)
+ tier = get_tier_for_folder(folder_name)
+ tier_data = TIERS[tier]
+
+ # Extract number, clean title, and suffix label
+ # E.g. "01 - Singleton (Creational)" -> num="01", raw_title="Singleton", suffix_label="Creational"
+ # "00 - Foundations" -> num="00", raw_title="Foundations", suffix_label="Foundations"
+ # "27 - Patterns in the Wild (Capstone)" -> num="27", raw_title="Patterns in the Wild", suffix_label="Capstone"
+ m_info = re.match(r'^(\d{2})\s*-\s*([^(]+?)(?:\s*\(([^)]+)\))?$', folder_name)
+ if m_info:
+ num = m_info.group(1).strip()
+ raw_title = m_info.group(2).strip()
+ suffix_label = m_info.group(3).strip() if m_info.group(3) else tier
+ else:
+ num = f"{idx:02d}"
+ raw_title = folder_name
+ suffix_label = tier
+
+ print(f" [{num}] Compiling {raw_title} ({tier} - {suffix_label})...")
+
+ # 1. Read theory.md
+ theory_file = f_path / "theory.md"
+ theory_content = ""
+ gof_intent = ""
+ summary_5yo = ""
+ if theory_file.exists():
+ theory_content = theory_file.read_text(encoding="utf-8", errors="ignore")
+ # Extract 5yo explanation
+ m_5yo = re.search(r'## π§ The 5-Year-Old Explanation\s*\n+([^\n#]+)', theory_content)
+ if m_5yo:
+ summary_5yo = m_5yo.group(1).strip()
+ # Extract GoF Intent
+ m_gof = re.search(r'### Intent \(GoF\)\s*\n+>\s*([^\n]+)', theory_content)
+ if m_gof:
+ gof_intent = m_gof.group(1).strip()
+
+ rendered_theory = render_markdown(theory_content, folder_name)
+
+ # 2. Discover and parse Python example files
+ py_files = sorted(f_path.glob("*.py"))
+ examples_data = []
+ for py_f in py_files:
+ ex = parse_python_example(py_f)
+ examples_data.append(ex)
+ total_examples += 1
+
+ manifest_examples.append({
+ "slug": f"{slug}-{slugify(ex['filename'])}",
+ "chapter_slug": slug,
+ "chapter_num": num,
+ "chapter_title": raw_title,
+ "tier": tier,
+ "filename": ex["filename"],
+ "title": ex["title"],
+ "framework": ex["framework"],
+ "scenario": ex["scenario"],
+ "key_insight": ex["key_insight"],
+ "lines": ex["line_count"],
+ })
+
+ # Render examples HTML
+ examples_html_parts = []
+ if examples_data:
+ examples_html_parts.append(
+ f'\n'
+ f'
β‘ Interactive Python 3.14 Implementations ({len(examples_data)}) '
+ )
+ for ex in examples_data:
+ ex_id = f"example-{slug}-{slugify(ex['filename'])}"
+ meta_block = ""
+ scenario_html = f'
Scenario: {ex["scenario"]}
' if ex["scenario"] else ""
+ insight_html = f'
Key Insight: {ex["key_insight"]}
' if ex["key_insight"] else ""
+ if scenario_html or insight_html:
+ meta_block = f'
\n {scenario_html}\n {insight_html}\n
\n'
+
+ examples_html_parts.append(
+ f'
\n'
+ f' \n'
+ f'{meta_block}'
+ f'
\n'
+ f'
{ex["escaped_code"]}\n'
+ f'
\n'
+ f'
\n'
+ )
+ examples_html_parts.append('
')
+ rendered_examples = "\n".join(examples_html_parts)
+
+ # Build chapter card (1:1 DSA standard)
+ tier_class = tier.lower()
+ chapter_card = (
+ f'\n'
+ f' \n'
+ f' \n'
+ f'
\n'
+ f'{rendered_theory}\n'
+ f'
\n'
+ f'{rendered_examples}\n'
+ f'
\n'
+ f' '
+ )
+ chapters_html.append(chapter_card)
+
+ # Build sidebar navigation tree group (1:1 DSA standard with expandable tree children)
+ prob_links = []
+ prob_links.append(f'π Pattern Anatomy & Theory ')
+ for ex in examples_data:
+ ex_id = f"example-{slug}-{slugify(ex['filename'])}"
+ prob_links.append(f'β‘ {html.escape(ex["title"])} ')
+
+ sidebar_items_html.append(f'''
+
+
+
+ {''.join(prob_links)}
+
+
+ ''')
+
+ manifest_patterns.append({
+ "num": num,
+ "slug": slug,
+ "title": raw_title,
+ "tier": tier,
+ "folder": folder_name,
+ "gof_intent": gof_intent,
+ "summary_5yo": summary_5yo,
+ "example_count": len(examples_data),
+ })
+
+ # Save manifest.json
+ manifest = {
+ "version": "2.0.0",
+ "generated_at": "2026-11-03",
+ "tiers": TIERS,
+ "patterns": manifest_patterns,
+ "examples": manifest_examples,
+ "stats": {
+ "patterns_count": len(manifest_patterns),
+ "examples_count": total_examples,
+ "diagrams_count": _DIAGRAM_COUNTER,
+ }
+ }
+ with open(CATALOG_DIR / "manifest.json", "w", encoding="utf-8") as f:
+ json.dump(manifest, f, indent=2)
+
+ print(f"β
Generated manifest.json ({len(manifest_patterns)} patterns, {total_examples} examples, {_DIAGRAM_COUNTER} diagrams).")
+
+ # Read shell index template from docs/site/index.html
+ template_path = DOCS_SITE_DIR / "index.html"
+ if not template_path.exists():
+ print(f"β Error: {template_path} not found.")
+ sys.exit(1)
+
+ template_html = template_path.read_text(encoding="utf-8")
+
+ # Inject generated content
+ hydrated_html = template_html.replace(
+ "",
+ "\n".join(chapters_html)
+ ).replace(
+ "",
+ "\n".join(sidebar_items_html)
+ ).replace(
+ "{{PATTERNS_COUNT}}", str(len(manifest_patterns))
+ ).replace(
+ "{{EXAMPLES_COUNT}}", str(total_examples)
+ ).replace(
+ "{{DIAGRAMS_COUNT}}", str(_DIAGRAM_COUNTER)
+ )
+
+ with open(SITE_DIR / "index.html", "w", encoding="utf-8") as f:
+ f.write(hydrated_html)
+
+ # Copy style.css, app.js, and any assets
+ if (DOCS_SITE_DIR / "style.css").exists():
+ shutil.copy(DOCS_SITE_DIR / "style.css", SITE_DIR / "style.css")
+ if (DOCS_SITE_DIR / "app.js").exists():
+ shutil.copy(DOCS_SITE_DIR / "app.js", SITE_DIR / "app.js")
+ if (DOCS_SITE_DIR / "assets").exists():
+ shutil.copytree(DOCS_SITE_DIR / "assets", SITE_DIR / "assets", dirs_exist_ok=True)
+
+ print(f"π Build complete: Static bundle written to {SITE_DIR}/")
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/build-docs.sh b/scripts/build-docs.sh
new file mode 100755
index 0000000..f635570
--- /dev/null
+++ b/scripts/build-docs.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+# ==============================================================================
+# build-docs.sh β Static Packaging Pipeline for Design Patterns Documentation
+# Compiles 28 chapters into _site/ directory for GitHub Pages
+# ==============================================================================
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
+SITE_DIR="${ROOT_DIR}/_site"
+
+CYAN='\033[0;36m'
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+NC='\033[0m'
+
+echo -e "${CYAN}ποΈ Packaging Design Patterns Living Documentation into _site/...${NC}"
+
+# Clean existing build output
+rm -rf "${SITE_DIR}"
+mkdir -p "${SITE_DIR}/catalog"
+
+# Run compiler
+python3 "${SCRIPT_DIR}/build-docs.py"
+
+# Verify critical artifacts exist
+for asset in index.html style.css app.js catalog/manifest.json; do
+ if [ ! -f "${SITE_DIR}/${asset}" ]; then
+ echo -e "${RED}β Fatal: Missing compiled asset: ${SITE_DIR}/${asset}${NC}"
+ exit 1
+ fi
+done
+
+# Touch .nojekyll so GitHub Pages does not run Jekyll processing
+touch "${SITE_DIR}/.nojekyll"
+
+BUNDLE_SIZE_MB=$(du -sm "${SITE_DIR}" | cut -f1)
+echo -e "${GREEN}β
Build succeeded! Static bundle packaged into _site/ (${BUNDLE_SIZE_MB}MB).${NC}"
diff --git a/scripts/test-docs.sh b/scripts/test-docs.sh
new file mode 100755
index 0000000..c5762a0
--- /dev/null
+++ b/scripts/test-docs.sh
@@ -0,0 +1,240 @@
+#!/usr/bin/env bash
+# ==============================================================================
+# test-docs.sh β 15-Gate Headless Verification Suite for Design Patterns
+# Validates HTML markup, KaTeX math delimiters, Mermaid syntax & sizing,
+# draggable sidebar resizer, Year 2500 mobile navigation drawer,
+# table overflow containment, relative subpath invariants, bundle integrity,
+# Unicode monospace box-drawing alignment, collapsible details invariants,
+# monospace semantic badging, and universal hyperlink integrity.
+# ==============================================================================
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
+SITE_DIR="${ROOT_DIR}/_site"
+
+CYAN='\033[0;36m'
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+YELLOW='\033[1;33m'
+NC='\033[0m'
+
+echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
+echo "β π§ͺ Running Design Patterns 15-Gate Headless Audit Suite β"
+echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
+
+# Ensure _site is built
+if [ ! -d "${SITE_DIR}" ] || [ ! -f "${SITE_DIR}/index.html" ]; then
+ echo -e "${YELLOW}β‘ _site directory not found or incomplete. Building now...${NC}"
+ bash "${SCRIPT_DIR}/build-docs.sh"
+fi
+
+# ------------------------------------------------------------------------------
+# Gate 1: Core Assets Presence
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 1. Auditing Core Assets in _site/...${NC}"
+for f in index.html style.css app.js catalog/manifest.json; do
+ if [ ! -f "${SITE_DIR}/${f}" ]; then
+ echo -e "${RED}β Gate 1 Failed: Missing required asset ${SITE_DIR}/${f}${NC}"
+ exit 1
+ fi
+done
+echo -e " ${GREEN}β
Core static assets verified (index.html, style.css, app.js, catalog/manifest.json)${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 2: Catalog Completeness & Manifest Integrity
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 2. Auditing Catalog Completeness & Search Index...${NC}"
+python3 -c "
+import json
+with open('${SITE_DIR}/catalog/manifest.json') as f:
+ data = json.load(f)
+patterns = data.get('patterns', [])
+examples = data.get('examples', [])
+assert len(patterns) == 28, f'Expected 28 patterns, found {len(patterns)}'
+assert len(examples) >= 35, f'Expected >= 35 examples, found {len(examples)}'
+print(f' β
Validated {len(patterns)} patterns and {len(examples)} indexed Python implementations.')
+"
+
+# ------------------------------------------------------------------------------
+# Gate 3: Mermaid Node Label Escaping
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 3. Auditing Mermaid label escaping invariants (< and > inside node labels)...${NC}"
+UNESCAPED_LT=$(sed -n '//,/<\/pre>/p' "${SITE_DIR}/index.html" | grep -n '\[.*<[0-9].*\]' || true)
+if [ -n "${UNESCAPED_LT}" ]; then
+ echo -e "${RED}β Gate 3 Failed: Detected unescaped '<' inside Mermaid node label in index.html:${NC}"
+ echo "${UNESCAPED_LT}"
+ exit 1
+fi
+echo -e " ${GREEN}β
Mermaid node labels are cleanly escaped.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 4: CSS SVG Sizing Invariants
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 4. Auditing SVG sizing invariants in style.css...${NC}"
+if grep -E '\.mermaid svg.*width:\s*auto\s*!important' "${SITE_DIR}/style.css" > /dev/null; then
+ echo -e "${RED}β Gate 4 Failed: Fatal CSS anti-pattern 'width: auto !important' found on .mermaid svg.${NC}"
+ echo " This collapses SVG elements to 0px x 0px inside flex containers."
+ exit 1
+fi
+echo -e " ${GREEN}β
CSS SVG sizing conforms to responsive viewBox standards.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 5: KaTeX Delimiters & Script Presence
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 5. Auditing KaTeX math engine integration...${NC}"
+if ! grep -q "katex.min.css" "${SITE_DIR}/index.html"; then
+ echo -e "${RED}β Gate 5 Failed: KaTeX stylesheet missing in index.html head${NC}"
+ exit 1
+fi
+if ! grep -q "auto-render.min.js" "${SITE_DIR}/index.html"; then
+ echo -e "${RED}β Gate 5 Failed: KaTeX auto-render script missing in index.html${NC}"
+ exit 1
+fi
+if ! grep -q "renderMathInElement" "${SITE_DIR}/app.js"; then
+ echo -e "${RED}β Gate 5 Failed: renderMathInElement call missing in app.js${NC}"
+ exit 1
+fi
+echo -e " ${GREEN}β
KaTeX mathematical typesetting engine verified.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 6: Draggable Sidebar Resizer & Collapsible Rail Invariants
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 6. Auditing Draggable Sidebar Resizer & Collapsible Rail invariants...${NC}"
+for id in sidebar-resizer sidebar-dock-toggle sidebar-close-btn floating-sidebar-toggle; do
+ if ! grep -q "id=\"${id}\"" "${SITE_DIR}/index.html"; then
+ echo -e "${RED}β Gate 6 Failed: Missing #${id} element in index.html${NC}"
+ exit 1
+ fi
+done
+if ! grep -q 'col-resize' "${SITE_DIR}/style.css"; then
+ echo -e "${RED}β Gate 6 Failed: Missing col-resize cursor rule in style.css${NC}"
+ exit 1
+fi
+if ! grep -q 'body.sidebar-collapsed' "${SITE_DIR}/style.css"; then
+ echo -e "${RED}β Gate 6 Failed: Missing body.sidebar-collapsed rule in style.css${NC}"
+ exit 1
+fi
+for fn in initSidebarResizer initDesktopSidebarToggle; do
+ if ! grep -q "${fn}" "${SITE_DIR}/app.js"; then
+ echo -e "${RED}β Gate 6 Failed: Missing ${fn} in app.js${NC}"
+ exit 1
+ fi
+done
+if ! grep -q 'dp_sidebar_collapsed' "${SITE_DIR}/app.js"; then
+ echo -e "${RED}β Gate 6 Failed: Missing dp_sidebar_collapsed persistence key in app.js${NC}"
+ exit 1
+fi
+if ! grep -q 'HapticAudio' "${SITE_DIR}/app.js"; then
+ echo -e "${RED}β Gate 6 Failed: Missing HapticAudio engine in app.js${NC}"
+ exit 1
+fi
+echo -e " ${GREEN}β
Draggable sidebar resizer, collapsible toggle & audio engine verified.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 7: Year 2500 Mobile Drawer & Anti-Clobbering Invariants
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 7. Auditing Mobile Navigation Drawer & Anti-Clobbering invariants...${NC}"
+if ! grep -q 'id="mobile-nav-toggle"' "${SITE_DIR}/index.html"; then
+ echo -e "${RED}β Gate 7 Failed: Missing #mobile-nav-toggle hamburger button in index.html${NC}"
+ exit 1
+fi
+if ! grep -q 'id="mobile-drawer-backdrop"' "${SITE_DIR}/index.html"; then
+ echo -e "${RED}β Gate 7 Failed: Missing #mobile-drawer-backdrop overlay in index.html${NC}"
+ exit 1
+fi
+if ! grep -q 'initMobileDrawer' "${SITE_DIR}/app.js"; then
+ echo -e "${RED}β Gate 7 Failed: Missing initMobileDrawer in app.js${NC}"
+ exit 1
+fi
+if ! grep -q 'overflow-x: clip' "${SITE_DIR}/style.css"; then
+ echo -e "${RED}β Gate 7 Failed: Missing sticky-safe 'overflow-x: clip' in style.css${NC}"
+ exit 1
+fi
+echo -e " ${GREEN}β
Mobile drawer & sticky-safe anti-clobbering rules verified.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 8: Table & Touch Containment Invariants
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 8. Auditing Table & Touch Containment invariants...${NC}"
+if ! grep -q 'class="table-wrapper"' "${SITE_DIR}/index.html"; then
+ echo -e "${RED}β Gate 8 Failed: Missing .table-wrapper elements in index.html${NC}"
+ exit 1
+fi
+if ! grep -q 'min-width' "${SITE_DIR}/style.css"; then
+ echo -e "${RED}β Gate 8 Failed: Missing table min-width rule in style.css${NC}"
+ exit 1
+fi
+echo -e " ${GREEN}β
Table touch scrolling and min-width containment verified.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 9: Relative Path & Subpath Invariants (/DesignPatterns/)
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 9. Auditing Relative Path invariants (GitHub Pages compliance)...${NC}"
+BAD_PATHS=$(grep -E '(href|src)="/(style|app|assets|catalog)' "${SITE_DIR}/index.html" || true)
+if [ -n "${BAD_PATHS}" ]; then
+ echo -e "${RED}β Gate 9 Failed: Found root-relative paths in index.html that will break on /DesignPatterns/:${NC}"
+ echo "${BAD_PATHS}"
+ exit 1
+fi
+echo -e " ${GREEN}β
All stylesheet, script, and catalog links use relative addressing (./).${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 10: Static Bundle Size & Integrity
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 10. Auditing Static Bundle Size & Distribution Integrity...${NC}"
+BUNDLE_SIZE_MB=$(du -sm "${SITE_DIR}" | cut -f1)
+if [ "${BUNDLE_SIZE_MB}" -gt 25 ]; then
+ echo -e "${RED}β Gate 10 Failed: Bundle size (${BUNDLE_SIZE_MB}MB) exceeds 25MB threshold.${NC}"
+ exit 1
+fi
+echo -e " ${GREEN}β
Bundle footprint is optimal (${BUNDLE_SIZE_MB}MB < 25MB).${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 11: Mermaid Diagram ID Uniqueness & Clean Navigation
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 11. Auditing Mermaid Diagram ID Uniqueness & Isolation...${NC}"
+python3 -c "
+import re
+with open('${SITE_DIR}/index.html') as f:
+ content = f.read()
+
+diagram_ids = re.findall(r']*class=[\"\']mermaid[\"\'][^>]*id=[\"\']([^\"\']+)[\"\']', content)
+assert len(diagram_ids) >= 70, f'Expected >= 70 mermaid diagrams, found {len(diagram_ids)}'
+assert len(diagram_ids) == len(set(diagram_ids)), f'Duplicate diagram IDs detected! {len(diagram_ids)} total vs {len(set(diagram_ids))} unique'
+print(f' β
Validated {len(diagram_ids)} isolated Mermaid diagrams with 100% unique IDs.')
+"
+echo -e " ${GREEN}β
Diagram containment and unique IDs verified.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 12: Unicode Monospace Box-Drawing Table & Card Alignment
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 12. Auditing Unicode Box-Drawing Alignment Invariants...${NC}"
+python3 "${SCRIPT_DIR}/audit_ascii_boxes.py" --check
+echo -e " ${GREEN}β
100% of ASCII and Unicode box-drawing tables and cards are aligned.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 13: Collapsible Details & Zero Raw HTML Block Escaping
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 13. Auditing Collapsible Details & Zero Raw HTML Block Escaping...${NC}"
+python3 "${SCRIPT_DIR}/audit_collapsible_elements.py"
+echo -e " ${GREEN}β
100% of collapsible details and accordions verified.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 14: Monospace Semantic Badging
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 14. Auditing Monospace Semantic Badging & Implementation Linter...${NC}"
+python3 "${SCRIPT_DIR}/audit_monospace_badging.py"
+echo -e " ${GREEN}β
100% semantic badges valid.${NC}"
+
+# ------------------------------------------------------------------------------
+# Gate 15: Universal Hyperlink Integrity & Local Path Prevention
+# ------------------------------------------------------------------------------
+echo -e "${CYAN}β 15. Auditing Hyperlink Integrity & Local Path Prevention...${NC}"
+python3 "${SCRIPT_DIR}/audit_links_and_anchors.py"
+echo -e " ${GREEN}β
100% hyperlink integrity & zero local path leaks verified.${NC}"
+
+echo ""
+echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
+echo -e "β ${GREEN}π ALL 15 QUALITY GATES PASSED DETERMINISTICALLY! ${NC}β"
+echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
diff --git a/specs/SPEC-001-design-patterns-futuristic-docs-portal.md b/specs/SPEC-001-design-patterns-futuristic-docs-portal.md
new file mode 100755
index 0000000..c514b27
--- /dev/null
+++ b/specs/SPEC-001-design-patterns-futuristic-docs-portal.md
@@ -0,0 +1,304 @@
+# SPEC-001: The Design Patterns Futuristic Living Documentation Portal & Command Deck
+
+> **Document ID:** SPEC-001-DESIGN-PATTERNS-FUTURISTIC-PORTAL
+> **Author:** Appa Rao Vadde (in collaboration with Antigravity AI)
+> **Classification:** High-Performance Static Documentation & Year 2500 Developer Cockpit
+> **Status:** RATIFICATION READY
+> **Date:** November 3, 2026
+> **Canonical Repository:** `vadde/DesignPatterns` (Target URL: `https://vadde.github.io/DesignPatterns/`)
+> **Target Branch:** `feature/docs-website`
+
+---
+
+## 1. Executive Summary & Vision 2500
+
+This specification formalizes the architecture, design system, client-side runtime, build engine, repository configuration, and automated quality gates for the **Design Patterns Living Documentation Portal**.
+
+The objective is to synthesize all 28 chapters, 5 architectural tiers, 38 typed Python 3.14 runnable implementations, and 84 Mermaid diagrams into a **Vision 2500 Command Deck**βa static GitHub Pages web application featuring:
+
+1. **Cosmic Glassmorphic & Aero Mica Halos:** Multi-layered specular borders, ambient mouse-following glow orbs, and four switchable futuristic themes (*Deep Space Liquid Glass, Fluent Aero Mica, Holo 2050 Cyberpunk HUD, and Matrix Obsidian*).
+2. **Sub-100ms Skimmability & Deep Cognitive Triage:** Zero-friction access to the **Master Decision Matrix** ("I have a problem, which pattern do I reach for?"), the **Master Pattern Relationships Flowchart** in a zoomable canvas, **5 Architectural Tiers** (Foundations, Creational, Structural, Behavioral, Architectural & Capstone), and **Framework Sightings** (Django, FastAPI, SQLAlchemy, Celery, stdlib).
+3. **High-Density, Zero-Toolchain Static Architecture:** Built with pure vanilla HTML5, CSS3, ES2022 JavaScript, and standard CDN libraries (KaTeX for formulas, Mermaid for diagrams, Prism for syntax highlighting). Builds in $<1$ second with standard Python 3.x, requires zero `npm install` or `node_modules` weight, and runs 100% offline or on GitHub Pages.
+4. **Autonomous DevEx & Full Makefile Discipline:** Zero ad-hoc one-off scripts. All developer, local preview, and CI/CD operations are unified behind canonical `Makefile` targets (`make docs-build`, `make docs-serve`, `make docs-test`, `make test-boxes`, `make format-boxes`, `make lint`, `make ci`, `make clean`).
+5. **15-Gate Automated Headless Verification Suite:** Every build is deterministically audited across 15 automated gates ensuring zero broken links, perfect WebKit SVG sizing, clean Mermaid escaping, KaTeX integration, draggable sidebar invariants, touch overflow containment, mobile drawer responsiveness, theme foreground/background contrast correlation, and Unicode box alignment.
+6. **Repository Settings Facelift:** Full audit and configuration guide for GitHub Actions Pages deployment, workflow permissions, repository topics, social previews, and branch protections.
+
+```
+ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+β DESIGN PATTERNS COMMAND DECK (YEAR 2500) β
+β β
+β [ Pattern Finder (F) ] [ Decision Graph (D) ] [ Search (βK) ] β
+β Intent-Based Quick ID Zoomable Master Diagram 38 Implementationsβ
+βββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
+ β
+ βββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββ
+ βΌ βΌ
+βββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββ
+β NAVIGATION TREE β β READING STAGE (HUD) β
+β β’ 00 - Foundations β ββββΊ β β’ 5-Year-Old Analogies β
+β β’ 01-05 Creational Patterns β β β’ Signal Detection (Anti-sigs)β
+β β’ 06-12 Structural Patterns β β β’ UML Class & Sequence Flow β
+β β’ 13-22 Behavioral Patterns β β β’ Python 3.14 Code + Copy β
+β β’ 23-26 Architectural Models β β β’ Real-World Framework Sight β
+β β’ 27 - Capstone & Interview β β β’ Interview Defense Playbook β
+β β’ Draggable Resizer (240-560)β β β’ Self-Test Collapsible QA β
+β β’ Commute Gadget Drawer (π±) β β β’ Fullscreen Theater Zoom/Pan β
+βββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββ
+```
+
+---
+
+## 2. Epistemic Audit & Staff Pair-Programmer Critique
+
+Following our constitutional Epistemic Boundary Framework and past lessons from the DSA portal project, we openly audit technical tensions, traps, and architectural trade-offs:
+
+```mermaid
+flowchart TD
+ subgraph KnownKnowns["1. Known Knowns (Grounded Assets)"]
+ KK1["28 Chapter Folders (00 to 27) with rich theory.md"]
+ KK2["38 Typed, Runnable Python 3.14 Implementations"]
+ KK3["84 Mermaid Diagrams (Class, Sequence, Flowcharts)"]
+ KK4["Zero Python SyntaxErrors (Verified with compileall)"]
+ KK5["Lessons Learned & Tested Invariants from vadde/DSA"]
+ end
+
+ subgraph KnownUnknowns["2. Known Unknowns (Architectural Challenges)"]
+ KU1["Preventing 28 dense chapters + 38 code files from freezing DOM"]
+ KU2["Mermaid SVG flex collapsing bug in Safari/WebKit"]
+ KU3["Aero Mica theme contrast failures in code blocks and HUD buttons"]
+ KU4["Relative subpath 404s on GitHub Pages (vadde.github.io/DesignPatterns/)"]
+ end
+
+ subgraph CriticalCritique["3. Battle-Tested Resolutions"]
+ CC1["Adopt CSS content-visibility: auto + contain-intrinsic-size"]
+ CC2["Enforce explicit viewBox dimensions; forbid width: auto !important"]
+ CC3["Strict dark-on-bright high-contrast rules for Aero Mica theme"]
+ CC4["Strict relative addressing (./) for all assets and anchors"]
+ end
+
+ KnownKnowns --> KnownUnknowns
+ KnownUnknowns --> CriticalCritique
+```
+
+### The 7 Battle-Tested Lessons Learned from vadde/DSA
+
+1. **The Safari WebKit Flex-SVG Sizing Trap:**
+ - *Problem:* In WebKit/Safari, an SVG inside a flex container with `width: auto !important` or missing intrinsic height collapses to `0px Γ 0px`.
+ - *Invariant:* `.mermaid svg` must declare `width: 100% !important; height: auto !important; max-height: 580px !important; object-fit: contain;`. In JavaScript, extract `vbW` and `vbH` from SVG `viewBox` and inject explicit W3C attributes `width`, `height`, and `style.aspectRatio = vbW / vbH`.
+
+2. **The Aero Mica Contrast Disconnect:**
+ - *Problem:* Light themes frequently suffer from white-on-white text in code snippets and washed-out buttons over light frosted backgrounds.
+ - *Invariant:* `[data-theme="mica"] pre code` MUST enforce `background: rgba(255, 255, 255, 0.95); color: #0f172a !important;`. Modal controls must use high-contrast frosted pills (`background: rgba(255, 255, 255, 0.22); border: 1px solid rgba(255, 255, 255, 0.55); color: #ffffff !important;`).
+
+3. **Sub-10ms "Expand All" SLA:**
+ - *Problem:* Expanding all chapters triggers hundreds of simultaneous SVG layout calculations, freezing the main thread for 10+ seconds.
+ - *Invariant:* Guard accordion listeners with `STATE.isBatchExpanding = true`. Mute haptic audio and defer off-screen rendering until lazy intersection observers take over.
+
+4. **Sticky Scroll Invariant vs Horizontal Overflow:**
+ - *Problem:* Applying `overflow-x: hidden` to `html` or `body` breaks CSS `position: sticky` on the navigation bar, sidebar, and floating controls in WebKit and Blink.
+ - *Invariant:* Always use `overflow-x: clip;` on `html, body, .layout-container`. Wrap tables in `` with horizontal scrolling and `min-width: 520px`.
+
+5. **Anti-Dismissal Rule for Theater Mode Workbench:**
+ - *Problem:* Users inspecting diagrams in theater mode accidentally dismiss the modal when dragging or clicking outside nodes.
+ - *Invariant:* Clicks or drag-releases on the canvas MUST NEVER close the modal. Only the explicit `β` button or `Escape` key closes the dialog.
+
+6. **Sub-Millisecond Zoom/Pan SLA (100% vs Fit):**
+ - *Problem:* Animated transitions on zoom cause sluggish lag.
+ - *Invariant:* `.theater-content-surface` specifies `transition: none !important;`. `100%` sets scale to exact `1.0`. `Fit` dynamically calculates `Math.min(availW / vbW, availH / vbH)`.
+
+7. **Universal Delegated In-Page Navigation & Fragment Integrity:**
+ - *Problem:* Clicking in-page anchors targets elements inside collapsed accordions, failing to scroll.
+ - *Invariant:* Universal event delegation intercepts `a[href^="#"]`, uncollapses parent chapters/details, scrolls with 72px cushion, and triggers an 1800ms `flash-focus` pulse.
+
+---
+
+## 3. UI/UX Design System Specification (Year 2500 Standards)
+
+### 3.1 Four Cyberpunk / Sci-Fi Themes
+
+The portal features an instantaneous theme engine toggled via header pills or hotkey (`T`), persisting choice to `localStorage.getItem('dp_theme')`:
+
+| Theme | Selector | Base Canvas | Card Surface | Accent Primary | Accent Secondary | Visual Atmosphere |
+|---|---|---|---|---|---|---|
+| **Deep Space Liquid Glass (Default)** | `[data-theme="liquid"]` | `#04060f` to `#080c1a` | `rgba(15, 23, 42, 0.65)` | Cyan `#00f2fe` | Violet `#a855f7` | Cosmic refraction, glowing cyan edges, deep glass |
+| **Fluent Aero Mica** | `[data-theme="mica"]` | `#f4f1ec` to `#ebe7df` | `rgba(255, 255, 255, 0.78)` | Sapphire `#1e3a8a` | Emerald `#0f766e` | Frosted optical paper, deep navy ink, crisp contrast |
+| **Holo 2050 Cyberpunk HUD** | `[data-theme="holo"]` | `#03020a` | `rgba(20, 10, 30, 0.70)` | Amber `#ffaa00` | Neon Pink `#ff4de1` | Holographic telemetry, glowing amber HUD, scanlines |
+| **Matrix Obsidian** | `[data-theme="matrix"]` | `#000000` | `rgba(10, 20, 10, 0.60)` | Neon Green `#00ff66` | Emerald `#10b981` | Stealth OLED pure black, high-tech matrix green |
+
+### 3.2 Design System Color Tokens
+
+```css
+:root {
+ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ --font-mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, Consolas, monospace;
+ --sidebar-width: 330px;
+ --topbar-height: 64px;
+ --radius-sm: 8px;
+ --radius-md: 14px;
+ --radius-lg: 20px;
+ --radius-full: 9999px;
+ --shadow-glass: 0 16px 40px -10px rgba(0, 0, 0, 0.5), 0 0 1px 1px rgba(255, 255, 255, 0.08) inset;
+}
+```
+
+---
+
+## 4. Technical Architecture & File Layout
+
+```
+DesignPatterns/
+βββ Makefile # Canonical DevEx commands
+βββ specs/
+β βββ SPEC-001-design-patterns-futuristic-docs-portal.md # RATIFIED SPEC
+βββ docs/site/
+β βββ index.html # Hydrated Year 2500 Command Deck Shell
+β βββ style.css # Cosmic liquid glass tokens, halos, responsive grid
+β βββ app.js # ScrollSpy, resizer, audio, search HUD, theater modal
+βββ scripts/
+β βββ build-docs.py # Catalog compiler (28 chapters, 38 python examples)
+β βββ build-docs.sh # Bundle packaging script (outputs to _site/)
+β βββ test-docs.sh # 15-Gate headless automated verification suite
+β βββ audit_ascii_boxes.py # Unicode UAX #11 box-drawing linter and formatter
+β βββ audit_collapsible_elements.py # Accordion & HTML integrity auditor
+β βββ audit_links_and_anchors.py # Universal link & local path leak prevention
+β βββ audit_monospace_badging.py # Monospace badge & syntax auditor
+βββ .agents/skills/design-patterns-docs-portal/
+β βββ SKILL.md # Living documentation & operational engineering guide
+βββ .github/workflows/
+β βββ ci.yml # CI verification (Python compile, ruff, 15-gate audit)
+β βββ docs-publish.yml # CD workflow deploying to GitHub Pages
+βββ 00 - Foundations/ ... 27 - Patterns in the Wild/
+βββ README.md
+```
+
+---
+
+## 5. Catalog Compiler & Interactive Features
+
+### 5.1 The 5 Architectural Tiers
+
+1. **Foundations (Chapter 00):** SOLID Principles, DRY, KISS, YAGNI, Composition vs Inheritance, UML Primer.
+2. **Creational Patterns (Chapters 01β05):** Singleton, Factory Method, Abstract Factory, Builder, Prototype.
+3. **Structural Patterns (Chapters 06β12):** Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy.
+4. **Behavioral Patterns (Chapters 13β22):** Chain of Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor.
+5. **Architectural & Advanced (Chapters 23β26):** Repository Pattern, Unit of Work, Dependency Injection, Event Sourcing & CQRS.
+6. **Capstone & Wild Sightings (Chapter 27):** Master Decision Matrix, Anti-Patterns, Interview Playbook.
+
+### 5.2 Interactive Pattern Selector / Decision Matrix
+
+A quick-access interactive widget in the portal header:
+- **"What is your challenge?"** Filter pills:
+ - *Control Instantiation* β Highlights Singleton, Factory Method, Abstract Factory, Builder, Prototype.
+ - *Connect Interfaces* β Highlights Adapter, Facade, Bridge, Proxy.
+ - *Compose Structures* β Highlights Composite, Decorator, Flyweight.
+ - *Decouple Behavior* β Highlights Observer, Mediator, Command, Strategy, State, Chain of Responsibility.
+ - *Enterprise Architecture* β Highlights Repository, Unit of Work, Dependency Injection, Event Sourcing & CQRS.
+- **Framework Sightings Filter:**
+ - `Django` | `FastAPI` | `SQLAlchemy` | `Celery` | `Pure Python`
+
+### 5.3 Runnable Code Blocks & One-Click Copy
+
+Every Python example (`example_*.py`) in a chapter folder is extracted and rendered as an interactive code block:
+- Syntax highlighting via Prism.js with custom futuristic theme styling.
+- Interactive header displaying filename, framework badge, and file size.
+- One-click copy button that copies clean code to clipboard and triggers celebratory audio chime (`HapticAudio.copySuccess()`).
+
+---
+
+## 6. Curated Web Audio Haptic Engine (`HapticAudio`)
+
+Directional micro-transients synthesized purely via Web Audio API oscillators:
+
+| Interaction | Waveform | Frequency Ramp | Duration | Sensation |
+|---|---|---|---|---|
+| **Expand Chapter** | Sine | 540Hz β 880Hz | 38ms | Mechanical switch opening |
+| **Collapse Chapter** | Sine | 780Hz β 420Hz | 38ms | Snappy latch folding |
+| **Sidebar Drag / Toggle**| Triangle | 440Hz β 760Hz | 50ms | Smooth sliding panel reveal |
+| **Copy Code** | Arpeggiated Sine | C6 (1046Hz) + E6 (1318Hz) | 90ms | Celebratory success chime |
+| **Theme Change** | Triangle | 600Hz β 1200Hz | 60ms | Cosmic palette shift |
+| **Theater Launch** | Harmonic Sine | 440Hz β 880Hz | 70ms | Cinematic workbench focus |
+| **Search Open (βK)** | High-transient Sine | 1180Hz β 1480Hz | 40ms | Holographic HUD ping |
+
+---
+
+## 7. The 15-Gate Automated Headless Verification Suite
+
+All 15 quality gates run in under 4 seconds via `make docs-test`:
+
+1. **Gate 1: Core Assets Presence** β `index.html`, `style.css`, `app.js`, `catalog/manifest.json`.
+2. **Gate 2: Catalog Completeness & Manifest Integrity** β 28 chapters, 38 Python code implementations indexed.
+3. **Gate 3: Mermaid Node Label Escaping** β Zero unescaped `<` or `>` crashing Mermaid parser.
+4. **Gate 4: CSS SVG Sizing Invariants** β Zero `width: auto !important` on `.mermaid svg`.
+5. **Gate 5: KaTeX Delimiters & Script Presence** β Mathematical typesetting engine verified.
+6. **Gate 6: Draggable Sidebar Resizer & Collapsible Rail Invariants** β Clamping (240β560px), `col-resize`, double-click reset, βB shortcut, and `localStorage` persistence.
+7. **Gate 7: Year 2500 Mobile Drawer & Anti-Clobbering Invariants** β Backdrop `z-index: 1100`, drawer `z-index: 1200`, sticky-safe `overflow-x: clip;`.
+8. **Gate 8: Table & Touch Containment Invariants** β Wrapped in `.table-wrapper` with horizontal scrolling and `min-width: 520px`.
+9. **Gate 9: Relative Path & Subpath Invariants** β Zero leading-slash `/` paths; 100% relative `./` for GitHub Pages.
+10. **Gate 10: Static Bundle Size & Integrity** β Static bundle strictly $<25\text{MB}$.
+11. **Gate 11: Mermaid Diagram ID Uniqueness & Clean Navigation** β 84+ diagrams with unique IDs and isolated rendering.
+12. **Gate 12: Unicode Monospace Box-Drawing Alignment** β Monospace tables conforming to Unicode UAX #11 display width rules.
+13. **Gate 13: Collapsible Details & Zero Raw HTML Block Escaping** β Semantic `` with `.md-summary` and `.md-details-body`.
+14. **Gate 14: Monospace Semantic Badging** β Framework and pattern badges valid and rendered.
+15. **Gate 15: Universal Hyperlink Integrity & Local Path Prevention** β Zero `file://` or `/Users/` leaks; zero external GitHub jumps for internal files; 100% internal fragment anchor resolution.
+
+---
+
+## 8. Canonical Developer Makefile Interface
+
+```makefile
+# Design Patterns Autonomous Command Deck
+make docs-build # Compiles 28 chapters and packages site into _site/
+make docs-serve # Serves documentation portal on http://localhost:4000
+make docs-test # Runs full 15-gate headless verification suite
+make test-boxes # Audits ASCII and Unicode box-drawing alignment
+make format-boxes # Realigns and formats all ASCII/Unicode boxes in place
+make test # Python AST compilation check across all 38 implementations
+make lint # Ruff syntax and hygiene linting
+make ci # Full local CI verification (test + lint + docs-test)
+make clean # Cleans _site/ and pycache artifacts
+```
+
+---
+
+## 9. GitHub Repository Settings Facelift Guide
+
+To ensure flawless automatic deployment and presentation on GitHub Pages, the following repository settings are verified and configured:
+
+1. **GitHub Pages Source Configuration:**
+ - In GitHub: **Settings β Pages β Build and deployment β Source**.
+ - Must be set to: **`GitHub Actions`** (enabling modern OIDC token artifact deployment via `actions/deploy-pages@v4`).
+2. **GitHub Actions Workflow Permissions:**
+ - In GitHub: **Settings β Actions β General β Workflow permissions**.
+ - Must be set to: **`Read and write permissions`** (or granular permissions configured in `.github/workflows/docs-publish.yml` with `contents: read`, `pages: write`, `id-token: write`).
+3. **Repository Metadata & Discovery:**
+ - **Description:** *"ποΈ Design Patterns β The Definitive Python 3.14 Reference. 23 GoF + Architectural patterns, real-world framework sightings (Django, FastAPI, SQLAlchemy), interactive Year 2500 Command Deck & Living Documentation Portal."*
+ - **Website / Homepage:** `https://vadde.github.io/DesignPatterns/`
+ - **Topics:** `design-patterns`, `python`, `python3`, `architecture`, `gof-patterns`, `fastapi`, `django`, `sqlalchemy`, `solid-principles`, `software-engineering`, `system-design`, `living-documentation`.
+4. **Git Hygiene & Ignore Rules:**
+ - `.gitignore` updated to strictly ignore `_site/`, `.playwright-mcp/`, `__pycache__/`, `.ruff_cache/`.
+
+---
+
+## 10. Phased Agile Implementation Roadmap
+
+- **Phase 1: Ratification & Custom Skill Ingestion** (This Step)
+ - Write ratified `SPEC-001`.
+ - Author `.agents/skills/design-patterns-docs-portal/SKILL.md`.
+ - Present comprehensive plan and PRD to user for tie-breaker review.
+- **Phase 2: Compiler & Static Assets Generation**
+ - Implement `scripts/build-docs.py` tailored for 28 chapters, theory deep-dives, and runnable Python examples.
+ - Implement `docs/site/style.css` with 4 futuristic themes, liquid glass, and Aero Mica contrast tokens.
+ - Implement `docs/site/app.js` with resizer, mobile drawer, search HUD (βK), theater modal, and haptic feedback.
+ - Implement `scripts/build-docs.sh` packaging pipeline.
+- **Phase 3: 15-Gate Verification Engine & Makefile DevEx**
+ - Implement `scripts/test-docs.sh`, `scripts/audit_ascii_boxes.py`, `scripts/audit_collapsible_elements.py`, `scripts/audit_links_and_anchors.py`, `scripts/audit_monospace_badging.py`.
+ - Implement root `Makefile` exposing all canonical targets.
+ - Update `.gitignore` to protect against build outputs.
+- **Phase 4: CI/CD Workflows & GitHub Deployment**
+ - Implement `.github/workflows/docs-publish.yml` (Pages deploy via GHA).
+ - Update `.github/workflows/ci.yml` with parallel quality gates.
+- **Phase 5: Local Server Verification & Visual Auditing**
+ - Build site via `make docs-build`.
+ - Launch local server via `make docs-serve` on port 4000.
+ - Test with Playwright MCP / curl to verify 60fps rendering, theme switching, search HUD, and theater mode.
+ - Run full `make ci` and verify 15 gates passing deterministically.