From df18f69516eaa5eb8a59891af90c4530492ac6c1 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Thu, 12 Mar 2026 23:24:02 +0100 Subject: [PATCH] feat: Add architecture decision and product requirements documents for per-layer SVG map architecture --- .../brainstorming-session-2026-03-12-002.md | 246 ++++++++++++++++++ .../architecture-layered-map-dom-split.md | 179 +++++++++++++ .../prd-layered-map-dom-split.md | 162 ++++++++++++ 3 files changed, 587 insertions(+) create mode 100644 _bmad-output/brainstorming/brainstorming-session-2026-03-12-002.md create mode 100644 _bmad-output/planning-artifacts/architecture-layered-map-dom-split.md create mode 100644 _bmad-output/planning-artifacts/prd-layered-map-dom-split.md diff --git a/_bmad-output/brainstorming/brainstorming-session-2026-03-12-002.md b/_bmad-output/brainstorming/brainstorming-session-2026-03-12-002.md new file mode 100644 index 00000000..b177fef9 --- /dev/null +++ b/_bmad-output/brainstorming/brainstorming-session-2026-03-12-002.md @@ -0,0 +1,246 @@ +--- +stepsCompleted: [1, 2, 3, 4] +inputDocuments: + - "_bmad-output/planning-artifacts/prd.md" + - "docs/architecture-globals.md" +session_topic: "Per-layer SVG architecture replacing the single #map SVG, with shared globals and broad dependency updates across the app" +session_goals: "Generate PRD-ready scope, architectural options, dependency impact themes, migration strategy, acceptance criteria, and key risks for splitting the map into one SVG per layer while preserving current user-facing behavior" +selected_approach: "ai-recommended" +techniques_used: + - "First Principles Thinking" + - "Morphological Analysis" + - "Reversal Inversion" +ideas_generated: 18 +context_file: "" +session_active: false +workflow_completed: true +technique_execution_complete: true +facilitation_notes: "Focused on preserving the user-visible layer stack contract while identifying codebase dependencies on the single #map SVG, shared defs, viewbox, and direct DOM selection patterns." +--- + +# Brainstorming Session Results + +**Facilitator:** Azgaar +**Date:** 2026-03-12 + +## Session Overview + +**Topic:** Per-layer SVG architecture replacing the single `#map` SVG, with shared globals and broad dependency updates across the app. + +**Goals:** Generate PRD-ready scope, architectural options, dependency impact themes, migration strategy, acceptance criteria, and key risks for splitting the map into one SVG per layer while preserving current user-facing behavior. + +### Session Setup + +This session was framed as a brownfield architectural expansion of the current WebGL layer initiative. The problem is not changing business behavior for users. The problem is changing the rendering substrate so SVG layers and WebGL layers can be interleaved in any order without exposing implementation details to users. + +Key observed constraints from the current codebase: + +- The map currently renders as a single `#map` SVG with shared `` and a single `#viewbox` group. +- Shared globals such as `svg`, `viewbox`, `scale`, `viewX`, and `viewY` are part of the runtime contract. +- Existing code already mixes SVG and WebGL for relief, but still assumes one primary map SVG and one shared canvas stack. +- Several utilities operate on a concrete `SVGSVGElement`, not an abstract layer model, so the dependency surface is broader than rendering alone. + +## Technique Selection + +**Approach:** AI-Recommended Techniques +**Analysis Context:** Per-layer SVG map architecture with focus on preserving current behavior while splitting DOM ownership and dependency contracts. + +**Recommended Techniques:** + +- **First Principles Thinking:** Strip the problem back to the real user contract: visible layer order, editability, exportability, and shared map state. +- **Morphological Analysis:** Enumerate architecture axes such as defs ownership, zoom ownership, layer identity, export assembly, and compatibility mode to avoid premature fixation on one implementation. +- **Reversal Inversion:** Deliberately invert current assumptions like “there is one map SVG” and “all code can touch `svg` directly” to expose hidden dependencies and migration traps. + +**AI Rationale:** These techniques fit a brownfield architecture problem better than purely generative methods. The hard part is not imagining layers. The hard part is separating stable user-facing contracts from unstable internal assumptions and then sequencing the migration so existing code continues to work while the DOM model changes underneath it. + +## Technique Execution + +### Technique 1: First Principles Thinking + +**[Category #1]**: Layer Contract Before DOM +_Concept_: Treat the authoritative product contract as “a stack of visible, reorderable map layers driven by shared map state,” not “a single SVG named `#map`.” Every architectural decision should preserve this contract regardless of whether a layer is SVG or WebGL. +_Novelty_: It reframes the migration away from DOM surgery toward contract preservation, which makes mixed rendering a natural consequence instead of a special case. + +**[Category #2]**: Shared Camera Bus +_Concept_: Make zoom, pan, viewport size, and world bounds a first-class shared camera contract consumed by all rendering layers. SVG layers, WebGL layers, and future export assemblers subscribe to the same state instead of inferring it from one DOM node. +_Novelty_: This shifts `viewbox` from being both model and renderer into being just one consumer of shared map camera state. + +**[Category #3]**: One Layer, One Surface +_Concept_: Each map layer gets its own surface: an SVG root for vector layers or a registered WebGL draw surface for GPU layers. No grouped “all SVG below, all WebGL above” buckets are allowed. +_Novelty_: It enforces full interleaving capability as a core rule, not an optional enhancement. + +**[Category #4]**: Layer Registry as Source of Truth +_Concept_: Introduce a central layer registry that owns IDs, ordering, visibility, render technology, DOM handles, and export participation. UI controls and renderers query the registry instead of hard-coding DOM positions or selector assumptions. +_Novelty_: The registry becomes the migration seam that decouples business layer semantics from concrete DOM structure. + +**[Category #5]**: Shared Resource Federation +_Concept_: Filters, masks, patterns, symbols, and text paths cannot stay implicitly attached to one SVG root. They need a deliberate resource federation model with ownership, namespacing, and lookup rules. +_Novelty_: This identifies `` as a product requirement, not a markup convenience, which prevents late-stage export and filter regressions. + +**[Category #6]**: Interaction Ownership Split +_Concept_: Pointer handling should belong to interaction layers and tools, not whichever visual surface happens to be on top. The rendering stack must remain visually reorderable without changing editing semantics. +_Novelty_: It prevents the common failure mode where DOM stacking accidentally rewrites input behavior. + +### Technique 2: Morphological Analysis + +**[Category #7]**: Compatibility Adapter Layer +_Concept_: Create an adapter that exposes legacy globals like `svg`, `viewbox`, and layer selectors through a compatibility API while the underlying implementation transitions to multiple SVG roots. +_Novelty_: Instead of a flag day rewrite, older code can keep working while dependency hotspots are migrated on a controlled schedule. + +**[Category #8]**: SVG Shell Per Layer +_Concept_: Each SVG layer gets a minimal shell with its own `` root, width, height, viewBox, and a predictable internal group layout. Layer-local drawing code targets its shell, while global orchestration manages ordering and visibility. +_Novelty_: This preserves familiar SVG authoring patterns while removing the single-root bottleneck. + +**[Category #9]**: Shared Defs Host Plus Layer Mirrors +_Concept_: Maintain one dedicated defs host for reusable symbols and filter resources, while layer SVGs reference those assets through stable IDs or cloned subsets when export requires local materialization. +_Novelty_: It separates runtime rendering efficiency from export correctness instead of forcing one mechanism to serve both poorly. + +**[Category #10]**: Layer Capability Metadata +_Concept_: Annotate each layer with capabilities such as “needs defs,” “needs clip paths,” “participates in export,” “interactive,” and “supports WebGL.” The PRD can then classify migration complexity by capability instead of by layer name alone. +_Novelty_: This creates a scalable planning tool for future migrations beyond relief. + +**[Category #11]**: Export Assembler Pipeline +_Concept_: Stop assuming the live DOM is already the export document. Introduce an export assembler that composes a temporary unified SVG from layer surfaces and shared resources. +_Novelty_: It breaks the hidden coupling between editing DOM and export DOM, which becomes increasingly important once rendering surfaces diverge. + +**[Category #12]**: Layer Reorder Transaction Model +_Concept_: Reordering should update one registry transaction that fans out to SVG z-order, WebGL render order, control panel state, and persistence. No subsystem should infer order independently. +_Novelty_: This turns layer order into a single atomic business event rather than a series of DOM manipulations. + +### Technique 3: Reversal Inversion + +**[Category #13]**: Assume `#map` Disappears Entirely +_Concept_: Design the system as if there is no canonical map SVG anymore. What remains must still support current tools, visibility toggles, exports, screenshots, and font discovery. +_Novelty_: This immediately exposes hidden dependencies like utilities that accept a single `SVGSVGElement`, direct `#map` selectors, and code that expects one shared query scope. + +**[Category #14]**: Make Direct DOM Access Illegal +_Concept_: Invert the current pattern by requiring code to ask the layer system for a surface, resource, or selector scope instead of directly querying `#map`, `#viewbox`, or concrete layer groups. +_Novelty_: This surfaces the real root cause of brittleness: implicit global DOM reachability. + +**[Category #15]**: Treat WebGL as Normal, Not Special +_Concept_: Instead of “insert canvas into SVG stack,” define a render-surface model where SVG and WebGL are just different surface kinds attached to the same layer registry and camera contract. +_Novelty_: This prevents the architecture from ossifying around relief as a one-off exception. + +**[Category #16]**: Push Shared Globals Up a Level +_Concept_: Globals like `svg` and `viewbox` should stop meaning “the map DOM node” and start meaning “the active map scene controller” or be replaced with narrower globals for camera, layer lookup, and resource lookup. +_Novelty_: This retains the legacy global pattern where necessary but redefines it around stable concepts rather than unstable implementation details. + +**[Category #17]**: Invert Dependency Discovery into a Migration Gate +_Concept_: Before any layer is split, require a dependency census for direct `svg`, `viewbox`, `#map`, ``, and DOM-order usage. A layer cannot migrate until its dependency class is known. +_Novelty_: This turns unknown dependency spread from an implementation surprise into an explicit planning artifact. + +**[Category #18]**: Design for the Hard Layers First +_Concept_: Plan as if labels, borders with text paths, masks, and filtered overlays must eventually fit the model, even if the first implementation only migrates simpler layers. The architecture should not dead-end on easy layers. +_Novelty_: It keeps the PRD honest by forcing early accommodation of the very SVG features most likely to break in a split-root model. + +## Idea Organization and Prioritization + +### Thematic Organization + +**Theme 1: Core Layer Model** + +- Layer Contract Before DOM +- Shared Camera Bus +- One Layer, One Surface +- Layer Registry as Source of Truth +- Layer Capability Metadata + +**Pattern Insight:** The project should be specified as a scene-graph and orchestration problem, not a markup rewrite. + +**Theme 2: Shared Dependency Refactoring** + +- Shared Resource Federation +- Compatibility Adapter Layer +- Shared Defs Host Plus Layer Mirrors +- Interaction Ownership Split +- Push Shared Globals Up a Level +- Make Direct DOM Access Illegal + +**Pattern Insight:** Most complexity comes from shared assumptions around global selectors, defs, and input behavior rather than from layer drawing itself. + +**Theme 3: Migration and Persistence** + +- SVG Shell Per Layer +- Layer Reorder Transaction Model +- Export Assembler Pipeline +- Invert Dependency Discovery into a Migration Gate + +**Pattern Insight:** A successful migration needs operational scaffolding: discovery, compatibility, export assembly, and atomic order management. + +**Theme 4: Future-Proofing for Mixed Rendering** + +- Treat WebGL as Normal, Not Special +- Assume `#map` Disappears Entirely +- Design for the Hard Layers First + +**Pattern Insight:** The architecture should be generic enough for arbitrary SVG and WebGL interleaving without creating a second special-case stack later. + +### Prioritization Results + +**Top Priority Ideas:** + +1. **Layer Registry as Source of Truth** because arbitrary SVG/WebGL ordering cannot be implemented safely if DOM order, UI order, and renderer order are maintained separately. +2. **SVG Shell Per Layer** because the PRD needs a concrete target DOM model, not just an abstract service layer. +3. **Shared Resource Federation** because ``, masks, filters, and text paths are the highest-probability regression area in a split-SVG architecture. +4. **Compatibility Adapter Layer** because layers are used across the codebase and a flag-day migration is too risky. +5. **Export Assembler Pipeline** because a multi-SVG live scene will otherwise break assumptions that the export artifact is already present in the DOM. + +**Quick Win Opportunities:** + +- Build a dependency census for all direct references to `svg`, `viewbox`, `#map`, `querySelector`, and layer group IDs. +- Define the layer registry schema and capability metadata before touching any render code. +- Prototype a two-layer split with one pure SVG layer and one existing WebGL layer to validate reorder semantics. + +**Breakthrough Concepts:** + +- Reframing globals as scene-controller contracts rather than DOM-node shortcuts. +- Decoupling runtime scene composition from export document composition. +- Treating render technology as metadata on a layer, not as a separate subsystem. + +## Action Planning + +### Immediate Next Steps for the New PRD + +1. **Write the problem statement around architectural constraints, not user behavior changes.** + The PRD should state that business requirements remain the same while the implementation contract changes from one SVG root to a multi-surface layer scene. + +2. **Define the target architecture in three explicit contracts.** + The PRD should separate: + - shared scene/camera globals, + - layer registry and ordering, + - resource federation and export assembly. + +3. **Add a dependency inventory section.** + Capture hotspot classes already visible in the codebase: single `#map` assumptions, one `#viewbox` transform owner, shared ``, and utilities that take a single `SVGSVGElement`. + +4. **Scope the rollout as phased migration.** + Phase 1 should establish orchestration and compatibility. Phase 2 should split selected low-risk SVG layers. Phase 3 should support fully arbitrary SVG/WebGL interleaving and export assembly. + +5. **Specify acceptance criteria around behavior parity.** + Reordering, visibility, interaction, styles, export, and performance must remain correct whether a layer is SVG or WebGL. + +### Resources Needed + +- A codebase-wide dependency audit for layer and SVG assumptions. +- A target list of candidate low-risk layers and high-risk layers. +- A design decision on runtime defs hosting versus per-layer defs cloning for export. +- A test strategy covering render order, selectors, export output, and zoom/pan synchronization. + +### Success Indicators + +- The PRD can describe a target architecture without using “single map SVG” as a prerequisite. +- Each existing layer can be classified by capability and migration complexity. +- There is an explicit compatibility story for code that currently depends on `svg` and `viewbox`. +- Export and shared defs are handled as first-class requirements rather than deferred cleanup. + +## Session Summary and Insights + +**Key Achievements:** + +- Identified the true product contract as mixed-render layer orchestration, not a single-root SVG DOM. +- Surfaced the highest-risk dependency classes: shared defs, direct DOM queries, single-SVG utilities, and interaction ownership. +- Produced a migration frame that can seed a dedicated PRD for per-layer SVG splitting. + +**Session Reflections:** + +The main architectural danger is treating this as a rendering refactor only. It is also a state ownership, resource ownership, and export ownership refactor. The cleanest path is to introduce an explicit layer registry and compatibility adapter before splitting many layers. Without that seam, the codebase will accumulate brittle one-off exceptions for every migrated layer. diff --git a/_bmad-output/planning-artifacts/architecture-layered-map-dom-split.md b/_bmad-output/planning-artifacts/architecture-layered-map-dom-split.md new file mode 100644 index 00000000..32c1acb4 --- /dev/null +++ b/_bmad-output/planning-artifacts/architecture-layered-map-dom-split.md @@ -0,0 +1,179 @@ +--- +status: complete +workflowType: architecture +project_name: Fantasy-Map-Generator +user_name: Azgaar +date: 2026-03-12 +inputDocuments: + - _bmad-output/planning-artifacts/prd-layered-map-dom-split.md + - docs/architecture-globals.md +--- + +# Architecture Decision Document - Per-Layer SVG Map Architecture + +**Project:** Fantasy-Map-Generator +**Author:** Azgaar (via Winston/Architect) +**Date:** 2026-03-12 +**Status:** Complete + +## 1. Architectural Intent + +The current map is one SVG with one `#viewbox`, one shared `` space, and many callers that treat that structure as the application model. The new architecture separates those concerns. The application model becomes a **layered map scene**. Rendering is only one implementation detail of that scene. + +The solution is deliberately simple: + +- one authoritative layer registry +- one shared scene state for camera and map data +- one surface per logical layer +- one compatibility layer for legacy single-SVG assumptions +- one export assembler that rebuilds a unified SVG when needed + +This avoids over-engineering. We do not introduce a generic rendering engine, a plugin DSL, or a second parallel layer system. + +## 2. Core Decisions + +### Decision 1: Introduce `Layers` as the Single Source of Truth + +Every logical layer is registered once with: + +- `id` +- `kind`: `svg` or `webgl` +- `order` +- `visible` +- `surface` + +All reordering, toggling, and lookup operations go through this registry. No feature code should infer order from DOM position. + +### Decision 2: Replace One Map SVG with a Scene Container and Layer Surfaces + +`#layers` remains the outer host. Inside it, the runtime scene is a stack of independent surfaces. + +- SVG-backed layers render into their own `` shell +- WebGL-backed layers render into registered canvas surfaces +- a dedicated defs host is kept separate from individual layer surfaces + +This makes SVG and WebGL peers in the same scene instead of special cases. + +### Decision 3: Move Shared Transform Ownership from `#viewbox` to Scene State + +Zoom, pan, viewport size, graph bounds, and scale remain shared globals because the project already depends on that runtime model. What changes is their meaning. + +- `scale`, `viewX`, `viewY`, `graphWidth`, `graphHeight` remain authoritative scene values (all available on `window` as before) +- `svg` and `viewbox` stop being the architectural source of truth +- legacy code that still needs them is routed through a temporary compatibility layer until it can move to scene or layer lookups + +The clean-code rule here is narrow ownership: scene state owns transforms, surfaces consume transforms. High-level scene orchestration manages the rest. No direct DOM queries for camera state, no direct `viewbox` manipulation outside of the compatibility layer. Clean non-leaking abstractions that do one thing. + +### Decision 4: Add a Thin Compatibility Layer for Existing Single-SVG Callers + +The current codebase depends heavily on single-root access patterns. That is a migration problem, not a reason to keep the old architecture. + +Add a minimal compatibility layer that exposes: + +- `getLayerSvg(id)` +- `getLayerSurface(id)` +- `queryMap(selector)` for controlled cross-layer queries + +This layer exists only to support migration. New code should talk to `Layers`, not to old DOM shortcuts. + +### Decision 5: Runtime Rendering and Export Rendering Are Different Pipelines + +The live DOM no longer needs to be the export document. Moveover, after the change DOM becomes just an implementation detail of the runtime, not the application model. Save files (.map) won't contain svg anymore, just data and registry state. + +- runtime uses split surfaces for layering flexibility and simpler ownership +- export assembles one SVG from registry order, layer outputs, and shared defs resources + +This is the only clean way to preserve export fidelity once the runtime is no longer a single SVG. + +## 3. Runtime Structure + +The target runtime shape is: + +```html +
+
+ + + + + +
+
+
+
+
+
+
+ +
+``` + +Important constraint: no grouped SVG buckets. Each logical layer gets its own surface so user-defined ordering stays arbitrary. + +## 4. Shared Resource Strategy + +The architecture uses a **dedicated defs host** at runtime. + +- filters, patterns, masks, symbols, markers, and text paths are registered there +- layer SVGs reference those resources by stable IDs +- export clones only the resources actually used by exported layers into the final assembled SVG + +This keeps runtime simple and export deterministic. + +## 5. Clean Code Rules for This Change + +This solution follows a simple clean-code approach: + +- keep abstractions narrow and named after graphical software concepts: scene, camera, layer, surface, defs, export assembler +- do not let abstractions leak implementation details such as DOM structure, render technology, or shared state management +- do not add generic factories, strategy trees, or metadata schemas beyond what the current migration needs +- do not let feature code query random DOM globally when a layer or defs lookup exists +- do not hide behavior behind flags when two separate concepts deserve two separate functions +- keep layer modules responsible only for drawing their own surface +- use simple JS-style names, prefer 1-2 words + +Preferred module ownership: + +- `scene`: shared runtime state +- `layers`: layer registry +- `layer`: one layer surface and local lifecycle +- `defs`: shared SVG resources + +## 6. Migration Plan + +### Phase 1: Foundation + +- migrate shared svg element resources to a dedicated defs host +- create `Scene` module for shared runtime state and camera management +- create `Layers` module for layer registry +- create `Layer` module for individual layer state and surface ownership +- add compatibility lookups for current `svg`, `viewbox`, and shared query patterns + +### Phase 2: First Split Layers + +- move low-risk SVG layers to standalone SVG shells +- keep their visual behavior unchanged +- validate reorder, toggle, and pointer behavior against the registry + +### Phase 3: Mixed Rendering + +- register WebGL layers through the same ordering model +- keep SVG and WebGL layers reorderable through one control path + +### Phase 4: Export [low priority] + +- build unified SVG export from registry state +- clone only required defs resources +- validate text paths, masks, and filtered layers + +## 7. Testing Clause + +Testing is intentionally out of scope for this update. + +Reason: + +- the change is architectural and cross-cutting +- intermediate states are not reliable test targets +- partial testing during the split would produce high noise and low confidence + +Implementation should focus on completing the runtime architecture first. Automated tests, manual verification, and regression coverage will be planned and executed later as a separate activity once the new layer model is stable enough to test meaningfully. diff --git a/_bmad-output/planning-artifacts/prd-layered-map-dom-split.md b/_bmad-output/planning-artifacts/prd-layered-map-dom-split.md new file mode 100644 index 00000000..75d3b068 --- /dev/null +++ b/_bmad-output/planning-artifacts/prd-layered-map-dom-split.md @@ -0,0 +1,162 @@ +--- +status: draft +basedOn: + - "_bmad-output/brainstorming/brainstorming-session-2026-03-12-002.md" + - "_bmad-output/planning-artifacts/prd.md" + - "docs/architecture-globals.md" +--- + +# Product Requirements Draft - Per-Layer SVG Map Architecture + +**Author:** Azgaar +**Date:** 2026-03-12 + +## Executive Summary + +Fantasy-Map-Generator currently treats the interactive map as a single `#map` SVG with a shared `#viewbox`, shared ``, and a broad set of rendering and utility code that assumes one canonical SVG root. This blocks the next stage of the rendering architecture: arbitrary interleaving of SVG and WebGL layers in user-defined order. + +This initiative replaces the single-root map DOM model with a per-layer surface architecture. Each logical map layer will own its own render surface, typically one SVG root per SVG layer and one registered surface per WebGL layer, while shared map state remains centralized through shared globals and scene orchestration. Users must continue to experience the same layer controls, visibility behavior, edit workflows, and output quality without needing to know whether a layer is rendered with SVG or WebGL. + +## Problem Statement + +The current architecture couples business concepts like “map layer,” “layer order,” and “layer visibility” to one concrete implementation detail: a single SVG document. That coupling appears in multiple forms: + +- One canonical `#map` root and `#viewbox` transform owner. +- Shared `` and resource assumptions. +- Utilities that operate on one `SVGSVGElement`. +- Direct DOM access by layer ID or CSS selector. +- Existing WebGL support that is additive rather than fully peer-based. + +As a result, the application cannot reliably place SVG and WebGL layers in any arbitrary order without accumulating special cases. Splitting the single map SVG is therefore a prerequisite for a generalized mixed-render layer stack. + +## Product Goal + +Enable the map to render as a stack of independent layer surfaces, one surface per logical layer, while preserving current user-visible behavior and allowing SVG and WebGL layers to be interleaved in any order. + +## Core Product Principles + +1. The user-visible contract is the layer stack, not the rendering technology. +2. Business behavior must remain stable across SVG and WebGL implementations. +3. Layer ordering must be driven by one authoritative source of truth. +4. Shared map state must remain available through stable globals or equivalent stable contracts. +5. Export, styles, filters, masks, and text resources are first-class requirements, not cleanup work. + +## In Scope + +- Replace the single-root `#map` SVG architecture with per-layer SVG roots for SVG-backed layers. +- Introduce a central layer registry that owns order, visibility, technology, and DOM/render handles. +- Preserve shared map globals for camera and scene state, while narrowing or adapting globals that currently point at one concrete SVG root. +- Support arbitrary SVG and WebGL interleaving without grouped rendering buckets. +- Define runtime resource ownership for shared defs, masks, filters, symbols, and text paths. +- Define an export assembly strategy for recomposing a unified SVG artifact from split surfaces. +- Inventory and adapt code that assumes one map SVG or one shared selector scope. + +## Out of Scope + +- Changing user-facing layer semantics or introducing new layer controls. +- Reworking the globe renderer. +- Rewriting all layers to WebGL. +- Solving every export enhancement beyond preserving current expected export fidelity. +- Automated and manual testing for this update during the implementation phase. Testing is deferred and will be handled later as a separate activity after the architectural change is in place. + +## Current Architecture Hotspots + +The PRD should explicitly cover at least these dependency classes: + +- The map root in `src/index.html` is one SVG with shared `` and one `#viewbox` group. +- The runtime globals described in `docs/architecture-globals.md` expose `svg` and `viewbox` as core contracts. +- Utilities such as font collection currently accept a single `SVGSVGElement` and query multiple layer subtrees within it. +- Relief rendering already straddles SVG and WebGL, but still assumes a specific parent element and shared scene context. + +## Proposed Target Architecture + +### 1. Shared Scene Contract + +The map camera, zoom, pan, viewport dimensions, and map data remain shared. These contracts stay globally accessible, but they no longer imply one DOM root. The PRD should define which globals remain stable, which are redefined, and which move behind compatibility adapters. + +### 2. Layer Registry + +The layer registry becomes the authoritative source for: + +- layer ID +- display name +- order +- visibility +- render technology +- surface handle +- export participation +- dependency capabilities such as defs, masks, text paths, or interaction ownership + +### 3. Layer Surface Model + +Each logical layer owns one render surface. For SVG layers this is one dedicated SVG shell. For WebGL layers this is one registered draw surface within the same scene ordering model. The user does not see a distinction. + +### 4. Shared Resource Federation + +The PRD must define how shared defs-based resources are created, referenced, and exported. This includes symbols, patterns, filters, masks, clip paths, and text paths. + +### 5. Export Assembly + +The export artifact is no longer assumed to be identical to the live runtime DOM. The PRD should define an explicit export assembly step that reconstructs a unified SVG from the layer registry and shared resources. + +## Functional Requirements + +1. Users can reorder layers in any sequence supported today, regardless of whether the layer is implemented in SVG or WebGL. +2. Visibility toggles behave exactly as they do now. +3. Editing and pointer interaction remain correct after layer splitting. +4. Shared styles, filters, masks, and text path resources remain available where needed. +5. Existing layer-based workflows continue to function without exposing rendering implementation details. +6. Export produces equivalent output to the current behavior for supported layers. +7. Legacy code paths that depend on `svg`, `viewbox`, or one selector scope have a compatibility path during migration. + +## Non-Functional Requirements + +1. The architecture must support incremental migration rather than a flag-day rewrite. +2. Test design and execution are out of scope for this implementation tranche and will be handled in a separate follow-up activity. +3. Layer order changes must update all runtime surfaces atomically. +4. Performance must not regress for existing SVG-only layers. +5. The architecture must remain compatible with the existing global-variable runtime model. + +## Phased Delivery Strategy + +### Phase 1: Orchestration Foundation + +- Create the layer registry. +- Define the shared scene contract. +- Add compatibility adapters for single-SVG assumptions. +- Build dependency census and migration classification. + +### Phase 2: Initial Layer Splits + +- Split selected low-risk SVG layers into standalone SVG shells. +- Validate mixed ordering with at least one WebGL layer. +- Prove visibility, reorder, and interaction parity. + +### Phase 3: Resource and Export Hardening + +- Implement defs federation and export assembly. +- Validate filters, masks, clip paths, and text paths. +- Expand migration coverage to more complex layers. + +## Acceptance Criteria Themes + +- There is no architectural requirement that a single `#map` SVG must exist at runtime. +- Layer order, visibility, and interaction semantics remain unchanged from the user perspective. +- Shared camera state drives every layer surface consistently. +- Shared defs-dependent features continue to work for runtime and export. +- Dependency hotspots are cataloged and each has a migration or compatibility strategy. + +## Open Questions for the Full PRD + +1. Which layers should remain unsplit initially because of high defs or text-path complexity? +2. Should runtime shared defs live in one dedicated hidden SVG host, in a primary scene SVG, or in mirrored per-layer subsets? +3. Which globals should remain named `svg` and `viewbox`, and which should be replaced with more stable abstractions? +4. Should export assemble from layer metadata or from cloned runtime surfaces? +5. What is the minimum viable compatibility layer for existing utilities and third-party integrations? + +## Recommended Next Inputs + +1. A codebase inventory of direct `#map`, `svg`, `viewbox`, and defs usage. +2. A capability matrix for every existing layer. +3. A first-pass list of low-risk versus high-risk candidate layers for splitting. +4. A design note for shared resource federation.